Description
⚙ Compilation target
ESNext
⚙ Library
intl
Missing / Incorrect Definition
This was originally just going to highlight some missing NumberFormat definitions, but after a trawl through the library, rather grew in scope a bit.
I've therefore divided this issue down into three parts: two are details of changes that need to be made to the library, but the third is an RFD that arose out of inconsistencies in the Intl library definitions. If the project team feel this would be better forked elsewhere, then feel free.
1: Properties of NumberFormatOptions
/ResolvedNumberFormatOptions
diverging from previous specifications
es5.d.ts
– ECMA-402 1.0 (2012)
currencySign
is defined as a property here, but does not exist in the specificationcurrencyDisplay
is not defined as a property here, but exists in the specification as"code" | "symbol" | "name" | undefined
es2020.intl.d.ts
– ECMA-402 7.0 (2020)
currencyDisplay
should be removed (as should have been defined above)numberingSystem
is not defined as a property ofNumberFormatOptions
here, but exists in the specification asstring | undefined
- reference: Intl.NumberFormatOptions options are missing #52072
- note that
numberingSystem
was already a property ofResolvedNumberFormatOptions
in version 1.0 of the specification; this is already correctly implemented
2: NumberFormatOptions
changes in ECMA-402 10.0 (2023)
es2023.intl.d.ts
should ideally be created to house these changes.
- breaking changes from
es2020.intl.d.ts
:- useGrouping?: boolean | undefined; + useGrouping?: "min2" | "auto" | "always" | boolean | undefined; - signDisplay?: "auto" | "never" | "always" | "exceptZero" | undefined; + signDisplay?: "auto" | "never" | "always" | "exceptZero" | "negative" | undefined;
- the following new properties have been added in the specification:
roundingPriority?: "auto" | "morePrecision" | "lessPrecision" | undefined; roundingIncrement?: 1 | 2 | 5 | 10 | 20 | 25 | 50 | 100 | 200 | 250 | 500 | 1000 | 2000 | 2500 | 5000 | undefined; roundingMode?: "ceil" | "floor" | "expand" | "trunc" | "halfCeil" | "halfFloor" | "halfExpand" | "halfTrunc" | "halfEven" | undefined; trailingZeroDisplay?: "auto" | "stripIfInteger" | undefined;
- corresponding changes to
ResolvedNumberFormatOptions
:- useGrouping: boolean; + useGrouping: "min2" | "auto" | "always"; - signDisplay?: "auto" | "never" | "always" | "exceptZero"; + signDisplay?: "auto" | "never" | "always" | "exceptZero" | "negative";
roundingMode: "ceil" | "floor" | "expand" | "trunc" | "halfCeil" | "halfFloor" | "halfExpand" | "halfTrunc" | "halfEven"; roundingIncrement: 1 | 2 | 5 | 10 | 20 | 25 | 50 | 100 | 200 | 250 | 500 | 1000 | 2000 | 2500 | 5000; trailingZeroDisplay: "auto" | "stripIfInteger";
3: Discussion – primitives versus const unions for enum-like properties
There are a lot of properties in the Intl specification that accept an enum-like list of values as valid input.
There is no set standard in the library for how these are defined.
es5.d.ts
tended to keep types as wide as possible, such asstyle?: string | undefined
- subsequent library updates tended to narrow enum-like types to const unions, such as
compactDisplay?: "short" | "long" | undefined
The latter has obvious advantages in terms of developer usability. However, it has a significant drawback, in that these enum-like properties have had a tendency to be modified fairly frequently in recent versions of the specification.
When this occurs to properties defined using primitive types, this isn't an issue for developers, as the change is non-breaking.
For example, the style
property was defined in the original specification as "decimal" | "percent" | "currency" | undefined
, but was added to the library as string | undefined
; as such, when "unit"
was added as a style in ES2020, the change went unnoticed.
However, when this occurs to properties defined as const unions, such as with a couple of the examples above, it's a different story.
- Firstly, the new property values can't be used until they're added into the library, despite the primitive type of the property not having changed.
- Secondly, making the changes to the library is going to have to involve some sort of workaround, as modifying the type of an existing interface property is obviously not possible.
As such, I think the project needs to decide on a couple of conventions:
- Should enum-like properties in the Intl library be typed as
"const" | "unions" | "where" | "possible"
, or should they be widened to their equivalent primitive? - If the former is chosen, then whenever an enum-like property is modified in the specification, this will necessitate modifying existing interface properties in the Intl library; what is the best way of implementing these changes?
Sample Code
No response
Documentation Link
No response