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.
