Conditionele Types met het sleutelwoord infer stellen je in staat om types uit complexe datatypes te extraheren. Een klassiek voorbeeld is het extraheren van het type element uit een array:
type ElementType<T> = T extends (infer U)[] ? U : T;
Hier stelt infer U je in staat om het type van het element van de array T te berekenen. Als T een array is, wordt het type van zijn elementen geretourneerd, anders zelf T.
Waar worden ze gebruikt:
Voorbeeld:
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
Kan je meerdere infer gebruiken in één conditioneel type? Hoe interpreteert TypeScript deze situatie?
Verkeerd antwoord:
Juist antwoord:
type FirstArgument<T> = T extends (infer F, ...any[]) => any ? F : never; // Maar het is nauwkeuriger met functies: type Args<T> = T extends (...args: infer A) => any ? A : never;
Verhaal
Een ontwikkelaar schreef een manier om het type object te krijgen dat door een functie wordt geretourneerd, maar vergat dat de functie mogelijk een Promise kan retourneren. Uiteindelijk was het type van de retourwaarde altijd Promise<any>, omdat een genest conditie met extract/infer niet werd gebruikt. De code moest in de hele basis opnieuw worden gefactoreerd.
Verhaal
In het project werd een universeel type geïntroduceerd voor het uitpakken van geneste arrays, maar men vergat de uiteindelijke else-tak in de voorwaarde te vermelden. TypeScript gaf geen fout, maar in sommige gevallen was het resultaat never, waardoor sommige utility-typisaties in externe bibliotheken sneuvelden.
Verhaal
Een collega probeerde de types van eigenschappen uit een grote interface te extraheren via een combine-conditioneel/infer-type, maar vergat dat sommige eigenschappen zelf union-types waren. Dit resulteerde in onverwachte combinaties van union-types aan de uitvoer, de compiler liet dit passeren, terwijl de logica niet correct functioneerde.