Issue
I've been having issues with this for a while. The code does run without issue, but I feel like I should figure out what TypeScript's linter is concerned about.
Here's the simplest repro I can get, LocaleConfig
is what gets the red highlight.
let Today = new Date();
let LocaleConfig = {dateStyle: "full"};
console.log(Today.toLocaleString([], LocaleConfig));
I've noticed that the linter has different errors depending on the target version. Here's the result from the default ES3.
No overload matches this call.
Overload 1 of 3, '(locales?: LocalesArgument, options?: DateTimeFormatOptions | undefined): string', gave the following error.
Argument of type '{ dateStyle: string; }' is not assignable to parameter of type 'DateTimeFormatOptions'.
Types of property 'dateStyle' are incompatible.
Type 'string' is not assignable to type '\"full\" | \"long\" | \"medium\" | \"short\" | undefined'.
Overload 2 of 3, '(locales?: string | string[] | undefined, options?: DateTimeFormatOptions | undefined): string', gave the following error.
Argument of type '{ dateStyle: string; }' is not assignable to parameter of type 'DateTimeFormatOptions'.
{source: ts, code: 2769, severity: 8}
And here's from ES6. Error is on the same word.
Type '{ dateStyle: string; }' has no properties in common with type 'DateTimeFormatOptions'.
{source: ts, code: 2559, severity: 8}
Solution
There are 2 separate issues here.
Type '{ dateStyle: string; }' has no properties in common with type 'DateTimeFormatOptions'.
This will happen when the target
is set to anything pre ES2020
, which is when the property was added to the spec. Find the draft here. ES6
== ES2015
and therefore it is missing when it is targeted.
Type 'string' is not assignable to type '"full" | "long" | "medium" | "short" | undefined'.
This is because of how string literals work. Without a type assertion, the dateStyle
can only be determined to be of type string
. Which could be changed at any time to be something not in the union of valid literals, which can therefore not reliably be assigned to it.
This can be resolved in multiple ways, but essentially you need to tell TS the dateStyle
property is of some literal type or union of literal types that fits within the expected type.
We know the full expected type, so we can use that:
let LocaleConfig: Intl.DateTimeFormatOptions = { dateStyle: 'full' };
We could type assert as a literal in multiple ways:
let LocaleConfig = { dateStyle: 'full' as 'full' };
let LocaleConfig = { dateStyle: 'full' as 'full' | 'long' };
let LocaleConfig = { dateStyle: 'full' as Intl.DateTimeFormatOptions['dateStyle'] };
We could type assert as const in multiple ways:
let LocaleConfig = { dateStyle: 'full' as const };
let LocaleConfig = { dateStyle: 'full' } as const;
The as const suffix acts like const but for the type system, ensuring that all properties are assigned the literal type instead of a more general version like string or number.
Also found this answer around this problem.
Answered By - AlienWithPizza
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.