简体   繁体   中英

Typescript: incorrect type for object spread operator?

Consider this code snippet:

type Foo = {
  x: string;
  y: number;
};

let a: Foo = {
  x: "@",
  y: 3,
};

let b: Partial<Foo> = { x: "#", y: undefined };

let c = { ...a, ...b };

Clearly type of c cannot be Foo because property y is undefined : runtime value of c is {x: "#", y: undefined} (at least in Chrome). Yet Typescript infers c type as { x: string; y: number;} { x: string; y: number;} . You can check in https://www.typescriptlang.org/play for version 4.0.5. I'm confused.

EDIT: here is the link from the comments to the github issue with the exact same problem https://github.com/microsoft/TypeScript/issues/13195#issuecomment-373178677 . For now this is the answer.

The main issue there is the type Partial<Foo> :

let b: Partial<Foo> = { x: "#", y: undefined };

When you specify the variable type, the ts compiler usually ignores the right side of the assignment and doesn't use it for type inference (there are some exceptions, but in general it works this way).

TL;DR

Use --exactOptionalPropertyTypes .

Details

This was a known issue with the TypeScript compiler: it did not properly distinguish between missing properties vs set-to-undefined properties.

See: microsoft/TypeScript#13195 .

Since Typescript 4.4 ( released in August 2021 ), there is a new compiler flag called --exactOptionalPropertyTypes . The flag was introduced exactly to solve this problem and properly distinguish between missing and undefined properties.

So the solution is to enable the flag.

The TS team even announced that it will become the default for new projects initialized with tsc --init .

However, as of September 2022, it still seems like the ecosystem is not completely ready for the new flag to be enabled in every project -- because a lot of existing libraries (including some React components) still declaring partial objects the old way, which brings significant inconveniences, if the flag is enabled.

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