Skip to content

fix(string): preserve falsy variable values in template()#56

Open
maxtaran2010 wants to merge 1 commit into
antfu:mainfrom
maxtaran2010:fix/template-falsy-values
Open

fix(string): preserve falsy variable values in template()#56
maxtaran2010 wants to merge 1 commit into
antfu:mainfrom
maxtaran2010:fix/template-falsy-values

Conversation

@maxtaran2010

Copy link
Copy Markdown

Summary

The template() function uses vars[key] || fallback when doing named substitution, which causes it to fall through to the fallback value whenever a variable is explicitly set to a falsy value — 0, false, or "".

Buggy behavior:

template('{count}', { count: 0 }, 'N/A')    // returns 'N/A', expected '0'
template('{active}', { active: false }, 'unknown') // returns 'unknown', expected 'false'
template('{name}', { name: '' }, 'anonymous') // returns 'anonymous', expected ''

Fix

Replace vars[key] || fallback with key in vars ? vars[key] : fallback so only keys that are actually absent from vars trigger the fallback, not keys that are present but hold a falsy value.

- return str.replace(/\{(\w+)\}/g, (_, key) => vars[key] || ((typeof fallback === 'function' ? fallback(key) : fallback) ?? key))
+ return str.replace(/\{(\w+)\}/g, (_, key) => key in vars ? vars[key] : ((typeof fallback === 'function' ? fallback(key) : fallback) ?? key))

Test plan

  • Added test cases for 0, false, and "" values in named template mode
  • All existing tests continue to pass (pnpm test — 39 tests passing)

…le values

`vars[key] || fallback` incorrectly falls through to the fallback when
a variable is explicitly set to a falsy value like 0, false, or "".
Switch to `key in vars ? vars[key] : fallback` so only missing keys
trigger the fallback, not legitimate falsy values.

Adds test cases for 0, false, and "" to prevent regression.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 9, 2026 21:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Comment thread src/string.ts
if (isObject(firstArg)) {
const vars = firstArg as Record<string, any>
return str.replace(/\{(\w+)\}/g, (_, key) => vars[key] || ((typeof fallback === 'function' ? fallback(key) : fallback) ?? key))
return str.replace(/\{(\w+)\}/g, (_, key) => key in vars ? vars[key] : ((typeof fallback === 'function' ? fallback(key) : fallback) ?? key))

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of in, let's use "hasOwn" to be safer?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants