Skip to content

fix(intl): require explicit options next to a fallback in the Intl formatters - #245

Merged
dangreen merged 1 commit into
mainfrom
fix/intl-fallback-options
Sep 8, 2026
Merged

fix(intl): require explicit options next to a fallback in the Intl formatters#245
dangreen merged 1 commit into
mainfrom
fix/intl-fallback-options

Conversation

@dangreen

@dangreen dangreen commented Sep 8, 2026

Copy link
Copy Markdown
Member

Why

The overloads of number, datetime, relativetime, duration, list and range allowed a lone fallback, number(42), and the API page lists them as number(fallback?, options?). The runtime, however, treats the first argument as a fallback only when a second argument is present, so a lone fallback is passed to the Intl constructor as options and silently dropped:

number(42)(ctx)                   -> undefined
datetime(new Date(0))(ctx)        -> undefined
list(['red', 'green'])(ctx)       -> undefined
range(number, [1, 5])(ctx)        -> undefined
relativetime(-1)(ctx, 2)          -> RangeError: Invalid unit argument
duration({ hours: 1 })(ctx, {…})  -> RangeError: Value 1 out of range for options property hours

A runtime check by shape cannot fix this consistently: duration takes a plain object for both the fallback and the options, list accepts any iterable, datetime accepts a Date. A partial rule would cost bytes in the shared formatter and still leave some formatters needing explicit options.

What

  • The fallback overloads of all six formatters require options ({} for the defaults, or false for raw mode). number(42) is a type error now, number(42, {}) and number(42, false) behave as before. No runtime code changes.
  • The custom format overloads of number and datetime require the function and take the first two parameters as explicitly undefined-able, so they no longer swallow such calls. The internal RangeFrom type mirrors that shape.
  • relativetime(options?) becomes relativetime(options): formatting without a unit threw a TypeError for any input.
  • JSDoc of the fallback overloads mentions {} for the defaults, and the API page gets one sentence with the rule.

Checks

  • oxlint, tsc --noEmit, vitest run (117 tests) in packages/intl pass.

…rmatters

The overloads of `number`, `datetime`, `relativetime`, `duration`, `list` and `range` accepted a lone fallback such as `number(42)`, but the runtime reads a lone argument as options, so the fallback was silently dropped, and `duration({ hours: 1 })` even threw once the object reached `Intl.DurationFormat`. A fallback cannot be told apart from options by shape, `duration` takes plain objects for both, so the contract is now spelled out in the types: a fallback always comes with options, `{}` or `false`. The custom `format` overloads of `number` and `datetime` require the function, so they no longer swallow such calls, and `relativetime` requires its options, since formatting without a `unit` throws.
@codecov

codecov Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.32%. Comparing base (1e29516) to head (d9b233a).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #245   +/-   ##
=======================================
  Coverage   83.32%   83.32%           
=======================================
  Files          98       98           
  Lines        2554     2554           
  Branches      549      549           
=======================================
  Hits         2128     2128           
  Misses        314      314           
  Partials      112      112           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dangreen
dangreen merged commit 6b3d44e into main Sep 8, 2026
10 checks passed
@dangreen
dangreen deleted the fix/intl-fallback-options branch September 8, 2026 15:04
@github-actions github-actions Bot mentioned this pull request Sep 8, 2026
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.

1 participant