Skip to content

Disallow timeZone option in Temporal.ZonedDateTime.prototype.toLocaleString - #65434

Open
Ryan Cavanaugh (RyanCavanaugh) with Copilot wants to merge 3 commits into
mainfrom
copilot/fix-illegal-timezone-option
Open

Ryan Cavanaugh (RyanCavanaugh) with Copilot wants to merge 3 commits into
mainfrom
copilot/fix-illegal-timezone-option

Conversation

Copilot AI commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

ZonedDateTime#toLocaleString always formats in the receiver's own time zone. JavaScriptCore, SpiderMonkey and V8 all throw TypeError if a timeZone option is passed. The lib typed options as plain Intl.DateTimeFormatOptions, so the bad call type-checked:

const zdt = Temporal.Now.zonedDateTimeISO("America/Chicago");
zdt.toLocaleString(undefined, { timeZone: "Europe/Berlin" });
//                              ~~~~~~~~ now TS2353

Changes

  • lib.esnext.temporal.d.ts
    • New Temporal.ZonedDateTimeToLocaleStringOptions extends Omit<Intl.DateTimeFormatOptions, "timeZone"> {}, the shape the issue proposed. It follows the YearMonthLikeObject extends Omit<…> pattern already in this file.
    • ZonedDateTime.toLocaleString now takes this type. The other Temporal types still accept timeZone, matching the spec.
  • Tests
    • New temporalZonedDateTimeToLocaleStringTimeZone.ts covers:
      • object literals with timeZone, which now error;
      • valid ZonedDateTime options;
      • an Intl.DateTimeFormatOptions variable, which is still accepted;
      • Instant / PlainDateTime still accepting timeZone.
    • In the existing temporal.ts, the line already marked /* WRONG */ now reports the error.
    • temporal.types reflects the new parameter type.

Design notes

  • Why Omit and not timeZone?: never: Omit only rejects timeZone in object literals, through the excess-property check. Values already typed as Intl.DateTimeFormatOptions are still accepted. timeZone?: never (suggested on Reject timeZone in ZonedDateTime.toLocaleString options #64346) would also catch non-literal values, but it would reject every Intl.DateTimeFormatOptions-typed variable. That would break the common const opts: Intl.DateTimeFormatOptions = …; zdt.toLocaleString(l, opts) pattern.
  • Error wording: the message names the type Omit<DateTimeFormatOptions, "timeZone"> rather than the interface name. TS 6.0.3 prints the same name for an interface that extends Omit<…>.

@typescript-automation typescript-automation Bot added Author: Team For Milestone Bug PRs that fix a bug with a specific milestone labels Nov 10, 2026
@typescript-automation typescript-automation Bot added For Uncommitted Bug PR for untriaged, rejected, closed or missing bug and removed For Milestone Bug PRs that fix a bug with a specific milestone labels Nov 10, 2026
Copilot AI and others added 2 commits November 10, 2026 21:55
…caleString

Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com>
…String

Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix illegal option timeZone in Temporal.ZonedDateTime Disallow timeZone option in Temporal.ZonedDateTime.prototype.toLocaleString Nov 10, 2026
@RyanCavanaugh
Ryan Cavanaugh (RyanCavanaugh) marked this pull request as ready for review November 10, 2026 22:24
Copilot AI balanced review requested due to automatic review settings November 10, 2026 22:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

No active review issues are reported for the Temporal locale-options declaration change.

No open issues 🎉

What changed in this PR

Updates TypeScript’s Temporal declarations to reject timeZone in object-literal options passed to ZonedDateTime.toLocaleString, addressing #64227 while preserving compatibility with Intl.DateTimeFormatOptions variables.

Changes:

  • Adds a dedicated options interface that omits timeZone.
  • Adds regression coverage for rejected literals, valid options, and unchanged behavior of other Temporal types.
  • Updates diagnostic, type, and symbol baselines.
File Description
tsc/​testdata/​tests/​cases/​compiler/​temporalZonedDateTimeToLocaleStringTimeZone.ts Adds focused regression coverage.
tsc/​testdata/​baselines/​reference/​compiler/​temporalZonedDateTimeToLocaleStringTimeZone.types Records types for the new test.
tsc/​testdata/​baselines/​reference/​compiler/​temporalZonedDateTimeToLocaleStringTimeZone.symbols Records symbol bindings for the new test.
tsc/​testdata/​baselines/​reference/​compiler/​temporalZonedDateTimeToLocaleStringTimeZone.errors.txt Records two rejected timeZone literals.
tsc/​testdata/​baselines/​reference/​compiler/​temporal.types Updates existing method signature baselines.
tsc/​testdata/​baselines/​reference/​compiler/​temporal.errors.txt Adds the diagnostic for existing invalid usage.
tsc/​internal/​bundled/​libs/​lib.esnext.temporal.d.ts Defines and applies the dedicated options interface.

Review effort: Balanced

This branch has not been deployed

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

Labels

Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The options arg of Temporal.ZonedDateTime.prototype.toLocaleString() currently accepts "illegal" option timeZone

3 participants