I Conditional Types che utilizzano la parola chiave infer permettono di estrarre i tipi da tipi di dati complessi. Un esempio classico è l'estrazione del tipo di un elemento da un array:
type ElementType<T> = T extends (infer U)[] ? U : T;
Qui infer U consente di calcolare il tipo dell'elemento dell'array T. Se T è un array, verrà restituito il tipo dei suoi elementi, altrimenti - lo stesso T.
Dove vengono utilizzati:
Esempio:
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
È possibile utilizzare più infer in un unico tipo condizionale? Come interpreta TypeScript questo caso?
Risposta errata:
Risposta corretta:
type FirstArgument<T> = T extends (infer F, ...any[]) => any ? F : never; // Ma è più corretto con le funzioni: type Args<T> = T extends (...args: infer A) => any ? A : never;
Storia
Uno sviluppatore ha scritto un modo per ottenere il tipo di un oggetto restituito da una funzione, ma non ha considerato che la funzione può restituire una Promise. Di conseguenza, il tipo di ritorno era sempre Promise<any>, poiché non è stato utilizzato un conditional annidato con extract/infer. È stato necessario rifattorizzare il codice in tutto il progetto.
Storia
Nel progetto è stato introdotto un tipo generico per disimballare array annidati, ma è stato dimenticato di scrivere il branch else finale nella condizione. TypeScript non ha segnalato alcun errore, ma in alcuni casi il risultato era never, causando problemi in alcune utility-typizzazioni in librerie esterne.
Storia
Un collega ha cercato di estrarre i tipi delle proprietà di una grande interfaccia tramite un tipo combinato condizionale/infer, non ha considerato che alcune proprietà erano union-types. Di conseguenza, ci sono state combinazioni inaspettate di union-types in uscita, il compilatore ha ignorato, mentre la logica ha funzionato in modo errato.