ProgrammationDéveloppeur TypeScript/Fullstack

Comment fonctionnent les types conditionnels avec infer en TypeScript, dans quelles situations sont-ils nécessaires, et quelles erreurs rencontrent-on en pratique ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

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 :

  • Pour écrire des types helpers universels (par exemple, extraction du type de retour d'une fonction, type de valeur d'un Promise, etc.).

Exemple :

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;

Question piège.

Peut-on utiliser plusieurs infer dans un même type conditionnel ? Comment TypeScript interprète-t-il ce cas ?

Réponse incorrecte :

  • "On ne peut pas utiliser plus d'un infer, TypeScript ne le permettra pas."

Réponse correcte :

  • On peut utiliser plusieurs variables infer dans un même modèle. Par exemple, en analysant un tuple:
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;
  • TypeScript infère correctement plusieurs types via différentes variables infer.

Exemples d'erreurs réelles dues à un manque de connaissance des subtilités du sujet.


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.