Hur tvingar jag TypeScript att kontrollera mot alla föreningsmedlemmar?
Så jag har den här koden och den fungerar ganska bra:
interface A {
type: "a";
payload: { isDisabled?: boolean };
}
interface B1 {
type: "b1";
payload: { children: A[] };
}
interface B2 {
type: "b2";
payload: { child: B | null };
}
type B = B1 | B2;
const items: B[] = [
{
type: "b2",
payload: {
child: {
type: "b1",
payload: {
children: [
{
type: "a",
payload: {
isDisabled: false,
},
},
],
},
},
},
},
];
tsconfig :
{
"compilerOptions": {
"rootDir": "./src",
"outDir": "./lib",
"strict": true
},
"include": ["src/**/*.tsx"]
}
Problemet uppstår när jag (till exempel) ersätter isDisabled: false med isDisabled: 1234. Jag förväntar mig att felet ska vara:
Type 'number' is not assignable to type 'boolean'.
Istället får jag detta:
Type '"b1"' is not assignable to type '"b2"'.
Type '{ children: { type: "a"; payload: { isDisabled: number; }; }[]; }' is not assignable to type '{ child: B | null; }'.
Object literal may only specify known properties, and 'children' does not exist in type '{ child: B | null; }'.
Det verkar som att TypeScript exkluderar B1 från B och försöker kontrollera items[0].payload.child mot endast B2 (ignorerar type: "b1").
Det finns dock ett par lösningar:
- Deklarera
B2['payload']som{ child: B }. Att utelämnanullåtgärdar det tidigare nämnda beteendet. Tyvärr är detta inte riktigt ett alternativ, eftersom jag vill attchildska kunna vara null. - Ett annat sätt att kringgå problemet är att använda någon annan typ istället för
nulliB2['payload']['child']. Tyvärr verkar de enda typerna som fungerar där vara tomma tuppler ([]) och tomma objekt (Record<string, never>), och jag skulle verkligen vilja använda ett primitivt värde. - Att sätta
strictNullTypes: falsei tsconfig fungerar också, men detta är inte lämpligt av uppenbara skäl. - Slutligen är det möjligt att använda typen påstås:
const items: B[]=[ ... ] as B[];. Detta verkar överflödigt, det är väldigt lätt att glömma att lägga till det och det är också väldigt svårt att verifiera (till exempel med en linter).
Så, frågan är: är det möjligt att få TypeScript att respektera B1 och rapportera det förväntade felet utan att förlita sig på någon av de tidigare nämnda lösningarna?