typescript - Ujevn oppførsel når umulige skjæringer gir `never`-typen
Jeg oppdaget at TypeScript produserer never-typen på forskjellige nivåer når umulige kryssinger oppstår
type Foo = {name: string, age: string}
type Bar = {name: string, age: number}
type Baz = Foo & Bar
const baz: Baz = {name: '123,', age:13} // ❌ Type 'number' is not assignable to type 'never'.
Eksemplet ovenfor resulterer i at typen Baz blir {name: string, age:never}
Men hvis vi endrer Bar litt
type Foo = {name: string, age: string}
type Bar = {name: string, age: boolean}
type Baz = Foo & Bar // the whole `Baz` type is `never`
Nå er hele Baz-typen never. Jeg kan ikke finne ut hvorfor TypeScript gjorde dette. Kan noen hjelpe meg med å forstå dette?
Svar #1
Før TypeScript 3.9 ville begge snittpunktene oppføre seg som ditt første eksempel og være ekvivalent med {name: string, age: never}. TypeScript 3.9 introduserte funksjonalitet for å redusere snittpunkter ved hjelp av diskriminerende egenskaper. Diskriminerende egenskaper er, omtrent, de hvis verdier er av enkeltstående litteraltyper (som strenglitteraltyper, numeriske litteraltyper, boolske litteraltyper, null og undefined) eller unioner av slike typer. Disse brukes i diskriminerte unioner. Hvis en snitttype får en diskriminerende egenskap til å redusere til never, vil kompilatoren redusere hele snittet til never. Se microsoft/TypeScript#36696 for detaljer og motivasjon.
Uansett, typen boolean er representert som unionen true | false av boolske litteraler, og derfor anses age-egenskapen i ditt andre eksempel å være en diskriminerende egenskap. På den annen side er number en ikke-literal type, og derfor anses ikke age-egenskapen i ditt første eksempel å være en diskriminerende egenskap. Dette forklarer forskjellen i oppførsel som du ser.