typescript - Modstridende typer i nogle bestanddele
Jeg prøver at få en metode til at returnere en specifik type afhængigt af en streng, der gives som argument. Dette er, hvad jeg har:
interface Base {
type: 'a' | 'b';
}
interface MyA extends Base {
type: 'a';
nameA: string;
}
interface MyB extends Base {
type: 'b';
nameB: string;
}
interface Mappings {
a: MyA;
b: MyB;
}
const testMethod = <K extends keyof Mappings>(
type: K
): Mappings[K][] => {
const values: Mappings[K][] = [];
if(type === 'a') {
values.push({
type: 'a',
nameA: 'My name a'
});
}
else if(type === 'b') {
values.push({
type: 'b',
nameA: 'My name b'
});
}
return values;
}
Så hvis jeg kører testMethod('a') ville det have en returtype på MyA[] og når jeg bruger testMethod('b') ville det returnere MyB[]. Men uanset hvad jeg gør, kan jeg ikke få det til at fungere. Fejlene er altid:
Argument af typen 'MyA' kan ikke tildeles parameteren af typen 'Mappings[K]'. Typen 'MyA' kan ikke tildeles typen 'never'. Snittet 'MyA & MyB' blev reduceret til 'never', fordi egenskaben 'type' har modstridende typer i nogle bestanddele.
Jeg troede, at arrayet kunne være problemet, men at returnere en variabel af typen Mappings[K] har det samme problem. Her er linket til playground. Jeg har gjort noget lignende tidligere som dette for at ændre en funktions argument i henhold til den streng, der gives som argument, men her er jeg helt fortabt.
Enhver vejledning eller TypeScript-ressourcer, jeg kan læse, vil blive værdsat!
Svar #1
Mærkeligt nok virkede dette for mig, så snart jeg specificerede, at Mappings udvidede Record<string, MyA | MyB>. Jeg fjernede den fælles forfader Base, da det ikke syntes at hjælpe.
interface MyA {
type: 'a';
nameA: string;
}
interface MyB {
type: 'b';
nameB: string;
}
interface Mappings extends Record<string, MyA | MyB> {
a: MyA;
b: MyB;
}
// same as above
const arrayOfMyA = testMethod('a'); // typed as MyA[]
const arrayOfMyB = testMethod('b'); // typed as MyB[]
Jeg har ikke en intuitiv forklaring, andet end at en eksplicit union er den eneste måde at overbevise TypeScript om, at 'a' | 'b' (keyof Mappings) udtømmende resulterer i MyA | MyB... på trods af at Mappings[keyof Mappings] korrekt resulterer i MyA | MyB både før og efter ændringen! Dette kan være en TypeScript-fejl, eller i det mindste en mulighed for en forbedring.
type MappingResults = Mappings[keyof Mappings];
// typed as MyA | MyB, regardless of whether
// Mappings extends Record<string, MyA | MyB>!
Legepladslink
