简体   繁体   中英

Typescript inference based on the expected function type parameters

type DateFormat = {
  year: "numeric";
}

function calculateDate (dateFormat: DateFormat) {
  /**
   * 
   */
}

const format = {
  year: "numeric"
}



calculateDate(format)

Sandbox

Currently in Typescript 4.2, the inferred type definition for format is:

{
    year: string;
}

This doesn't match the expected type alias, DateFormat , in the function call ( calculateDate ), because the year property of type string , isn't as specific as the string literal numeric .

If however, I passed the format object argument directly from the function call, TS seems to be able to infer the type in the context of the call - and correctly validate the type against DateFormat.

calculateDate({
  year: "numeric"
})

Therefore, I'm wondering whether this is a limitation in Typescript inference-algorithm ability, or an active design decision of the language?

you must use a const assertion as const :

const format = {
  year: "numeric"
} as const;

Quote from the docs:

When we construct new literal expressions with const assertions, we can signal to the language that

  • no literal types in that expression should be widened (eg no going from "hello" to string)
  • object literals get readonly properties array
  • literals become readonly tuples

Playground link

To answer the question in the comment:
Yes, it is a design decision, because there are use-cases for the wide and for the tight type.

An example where we want to have the wide type is this:

function foo(opts = {
  color: 'blue'
}) {}

foo({
  color: 'green'
})

In this case, we want the color property to be of type string - not blue .

Playground example 2

This algorithm called Excess Property Checks

Object literals get special treatment and undergo excess property checking when assigning them to other variables, or passing them as arguments. If an object literal has any properties that the “target type” doesn't have, you'll get an error:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM