48

I have recently been alerted to an "error" by Visual Studio Code in the following snippet:

someDateObject.toLocaleDateString('de-DE', Travel.dateOptions));
someDateObject.toLocaleDateString('de-DE', Travel.dateOptions));

Where Travel.dateOptions is defined as such:

public static dateOptions = { year: 'numeric', month: '2-digit', day: '2-digit' };

This has been working fine for the better part of the last 2 years, but upon opening the class inside VSC recently, it displayed following error for Travel.dateOptions:

Argument of type '{ year: string; month: string; day: string; }' is not assignable to parameter of 
type 'DateTimeFormatOptions'.
Types of property 'year' are incompatible.
Type 'string' is not assignable to type '"numeric" | "2-digit"'. ts(2345)

I am dead confused as to why. Is this possibly a bug with VSC? The code seems to work fine (and has worked fine the entire time) once compiled - and according to the documentation for Date::toLocaleDateString() what I'm doing here seems perfectly valid.

Any ideas?

4 Answers 4

80

When you initialize a class property with a literal such as public foo = { bar: 'a' }, its type becomes { bar: string }, even if you declare it as readonly. TypeScript on purpose doesn't make the type too strict ({ bar: 'a' }).

Method toLocaleDateString accepts an object whose key year must be of type 'numeric' or '2-digit', but yours is of type string.

To make the type of the initialized object more specific, use as const:

public static dateOptions = { year: 'numeric', month: '2-digit', day: '2-digit' } as const;
Sign up to request clarification or add additional context in comments.

Comments

39

I've just hit the same problem, rather than redeclare the const as const (which feels like a code smell) I forced the variable type:

  formatDT(sourceDate: Date) {
    const options: Intl.DateTimeFormatOptions = { month: "long", day: 'numeric', year: 'numeric', hour: '2-digit', minute: "2-digit" };
    return new Intl.DateTimeFormat("en-GB", options).format(new Date(sourceDate));
  }

3 Comments

This makes more sense, it worked for me.
Why do you think as const is a code smell? You're also basically using as Int.DateTimeFormatOptions, just with a different syntax.
👍 very OOP 😃 🎉
23

Following your code example you must explicitly declare the DateTimeFormatOptions data type for dateOptions

const dateOptions: Intl.DateTimeFormatOptions = {
  year: 'numeric',
  month: '2-digit',
  day: '2-digit'
};

export const Travel = { dateOptions };

const someDateObject = new Date();

console.log(someDateObject.toLocaleDateString('de-DE', Travel.dateOptions));

Comments

8

Include Intl.DateTimeFormatOptions for the declaration.

const options :Intl.DateTimeFormatOptions = { 
    year: 'numeric', 
    month: '2-digit', 
    day: 'numeric', 
    hour: '2-digit', 
    minute: '2-digit', 
    hour12: false 
};

1 Comment

Please note that the same approach has been shown by Matias before.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.