Les types conditionnels utilisant le mot-clé infer permettent d'extraire des types à partir de types de données complexes. Un exemple classique est l'extraction du type d'un élément d'un tableau:
type ElementType<T> = T extends (infer U)[] ? U : T;
Ici, infer U permet de calculer le type de l'élément du tableau T. Si T est un tableau, le type de ses éléments sera retourné, sinon — T lui-même.
Où ils sont utilisés :
Exemple :
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
Peut-on utiliser plusieurs infer dans un même type conditionnel ? Comment TypeScript interprète-t-il ce cas ?
Réponse incorrecte :
Réponse correcte :
type FirstArgument<T> = T extends (infer F, ...any[]) => any ? F : never; // Mais c'est plus correct avec des fonctions: type Args<T> = T extends (...args: infer A) => any ? A : never;
Histoire
Un développeur a écrit une méthode pour obtenir le type d'un objet retourné par une fonction, mais il n'a pas pris en compte que la fonction peut retourner un Promise. En conséquence, le type de valeur retournée était toujours Promise<any>, car un conditional imbriqué avec extract/infer n'était pas utilisé. Il a dû refactoriser le code dans toute la base.
Histoire
Dans le projet, un type générique pour déballer des tableaux imbriqués a été introduit, mais le branchement else final dans la condition a été oublié. TypeScript ne donnait pas d'erreur, mais dans certains cas, le résultat était never, entraînant des ruptures dans certaines typisations utilitaires dans des bibliothèques externes.
Histoire
Un collègue a tenté d'extraire les types des propriétés d'une grande interface via un type combine-conditional/infer, mais il n'a pas pris en compte que certaines propriétés étaient elles-mêmes des types union. En conséquence, des combinaisons inattendues de types union ont été obtenues, le compilateur acceptait cela, mais la logique ne fonctionnait pas correctement.