Skip to content

finding(core): DateDisplayOptions.style is read by formatDateTime alone — on formatDate it is inert AND collides with a positional parameter of the same name #7745

Description

@claude

Carved out of the contract review of PR #7621 (card objectui#7443) by the domain:ui PM seat. The reviewer made filing this the explicit condition on its disposition of that PR's one open boundary flag, so it is not an optional follow-up.

The state PR #7621 ships

DateDisplayOptions is the one options bag that formatDate, formatRelativeDate and formatDateTime all take. PR #7621 added style?: string to it (packages/core/src/utils/date-display.ts:75) — and only formatDateTime reads it (:236).

Measured by the reviewer at head a43aa8101:

call result
formatDate(v, undefined, { style: 'short', locale: 'en-US' }) Jul 4, 2024 — the default face, no diagnostic
formatRelativeDate(v, { style: 'compact' }) ignored

⭐ The sharpest form of it, which the implementing dev did not name

On formatDate the inert key collides with a positional parameter of the same name:

formatDate(value: string | Date | number, style?: string, options?: DateDisplayOptions)

So that one function now has two spellings for one concept, and one of them does nothing. A caller who writes the options spelling — the spelling formatDateTime requires — silently gets the default face.

Why this was accepted for the interim, and what that costs

The reviewer ruled the shipped shape (A) correct at the contract tier for the interim, on two measured grounds:

  1. The precedent is real and the same shape. dueLike is read only at formatRelativeDate:119, t only at :122; formatDateTime(v, { dueLike: true, t: () => 'X', locale }) renders Jul 4, 2024, 07:00 AM — both keys silently inert. The module already has a one-bag convention with inert keys.
  2. It is NOT an AGENTS.md #0.1 instance. #0.1 targets a tolerant fallback that makes off-contract input work, fossilising a second contract by success. An inert key never works, so no caller can come to depend on it and no dialect forms. It does share #0.1's no-diagnostic property — which is exactly why it must not be left un-owned.

Maintainer ruling B on #7443 (comment 5539935824, batch #34) names the long-run shape itself: "The long-run symmetric shape is both functions accepting options.style — additive on formatDate, and ⛔ not this card's." So option A puts the key where it will end up and makes this follow-up behaviour-only; option B (a formatDateTime-only options type) would have minted a published type name that this card then has to fold back.

What this card is

Make formatDate read options.style. Additive; the ruling already names it as the target shape.

⚠️ Open questions the implementer must answer rather than assume:

Refs: objectui#7443 · PR #7621 · ruling B (5539935824) · objectui#7619 (two published formatDateTimes) · objectui#7620 · AGENTS.md #0.1.


Generated by Claude Code

Activity

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions