Typescript: forkert type for objekt spread-operator?


Overvej denne kodeuddrag:

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

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

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

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

Klar type af c kan ikke være Foo, fordi egenskaben y er undefined: runtime-værdien af c er {x: "#", y: undefined} (i det mindste i Chrome). Alligevel udleder Typescript typen af c som { x: string; y: number;}. Du kan tjekke det på https://www.typescriptlang.org/play for version 4.0.5. Jeg er forvirret.

REDIGER: her er linket fra kommentarerne til GitHub-udgaven med det helt samme problem https://github.com/microsoft/TypeScript/issues/13195#issuecomment-373178677 . For nu er dette svaret.

Svar #1

Hovedproblemet der er typen Partial<Foo>:

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

Når du angiver variabeltypen, ignorerer ts-kompilatoren normalt højre side af tildelingen og bruger den ikke til typeafledning (der er nogle undtagelser, men generelt fungerer det på denne måde).

Svar #2

Kort fortalt

Brug --exactOptionalPropertyTypes.

Detaljer

Dette var et kendt problem med TypeScript-kompilatoren: den skilte ikke korrekt mellem manglende egenskaber og egenskaber sat til undefined.

Se: microsoft/TypeScript#13195.

Siden Typescript 4.4 (udgivet i august 2021) er der en ny compiler-flag kaldet --exactOptionalPropertyTypes. Flaget blev indført netop for at løse dette problem og korrekt skelne mellem manglende og undefined-egenskaber.

Så løsningen er at aktivere flaget.

TS-teamet annoncerede endda, at det vil blive standarden for nye projekter initialiseret med tsc --init.

Men pr. september 2022 virker det stadig som om, at økosystemet ikke helt er klar til, at den nye flag kan aktiveres i hvert projekt -- fordi mange eksisterende biblioteker (inklusive nogle React-komponenter) stadig erklærer delvise objekter på den gamle måde, hvilket medfører betydelige ulemper, hvis flaget aktiveres.

Relaterede artikler