Description
Bug Report
The types for Intl.RelativeTimeFormat.prototype.formatToParts
in lib.e2020.intl.d.ts have a few issues.
-
According to the spec (and MDN docs), either singular or plural names for units are accepted as input, but only singular names are output. The current types assume that plural names can also be output, which is incorrect. The relevant step in the spec is Step 5 in https://tc39.es/ecma402/#sec-PartitionRelativeTimePattern, where plural inputs are converted to singular before being used in the output.
-
Also, there's a missed opportunity here to narrow the return type of this method, because for any input unit, the return unit will be the same unit, unless it's a plural in which case it's the plural unit converted to singular. (See https://tc39.es/ecma402/#sec-makepartslist.) So the return type could be a generic where
unit
in the output depends onunit
in the input. -
Finally, there's another missed opportunity to narrow the return type using the
type
property, because according to https://tc39.es/ecma402/#sec-FormatRelativeTimeToParts and https://tc39.es/ecma402/#sec-makepartslist, iftype === 'literal'
thenunit
will be omitted, while iftype
is any other value, thenunit
will be present in the output.
I'd be happy to submit a PR to change these types. (If a PR would be welcome.)
Here's excerpts from the current relevant types in lib.e2020.intl.d.ts:
TypeScript/lib/lib.es2020.intl.d.ts
Lines 114 to 118 in cb158e7
TypeScript/lib/lib.es2020.intl.d.ts
Lines 183 to 186 in cb158e7
TypeScript/lib/lib.es2020.intl.d.ts
Lines 38 to 47 in cb158e7
🔎 Search Terms
Intl
RelativeTimeFormat
formatToParts
plural
singular
🕗 Version & Regression Information
Introduced in #36084.
⏯ Playground Link
💻 Code
const rtf = new Intl.RelativeTimeFormat();
const parts = rtf.formatToParts(42, 'minutes');
// ResultUnit is the actual type returned per the ECMA-402 spec
type ResultUnit = "year" | "quarter" | "month" | "week" | "day" | "hour" | "minute" | "second";
const partsWithUnit = parts.filter(p => p.unit);
const unit: ResultUnit = partsWithUnit[0].unit!;
// ^^^^
// Type 'RelativeTimeFormatUnit' is not assignable to type 'ResultUnit'.
// Type '"years"' is not assignable to type 'ResultUnit'.(2322)
🙁 Actual behavior
TS error 2322
🙂 Expected behavior
No error because the unit of the return type is always singular.