Types conditionnels TypeScript

Les types conditionnels dans TypeScript permettent de créer des types qui dépendent d'une condition. Ils permettent une plus grande flexibilité et une plus grande expressivité dans les définitions de type, ce qui permet de modéliser des relations de type complexes de manière claire et concise. Cet article explore le fonctionnement des types conditionnels dans TypeScript et fournit des exemples pour illustrer leur utilisation.

Que sont les types conditionnels ?

Les types conditionnels permettent de créer des types sélectionnés en fonction d'une condition. Ils sont similaires aux instructions conditionnelles en programmation, mais fonctionnent au niveau du type. La syntaxe de base d'un type conditionnel est la suivante:

type ConditionalType = T extends U ? X : Y;

Dans cette syntaxe:

  • T est le type vérifié.
  • U est le type à comparer.
  • X est le type renvoyé si T étend U.
  • Y est le type renvoyé si T n'étend pas U.

Exemple de base de types conditionnels

Voici un exemple simple d'un type conditionnel qui renvoie différents types selon qu'un type donné est une chaîne ou non:

type IsString = T extends string ? "String" : "Not a string";

type Result1 = IsString;  // Result1 is "String"
type Result2 = IsString;  // Result2 is "Not a string"

Dans cet exemple, IsString vérifie si T étend string. Si c'est le cas, le résultat est "String"; sinon, il s'agit de "Not a string".

Utilisation de types conditionnels avec des types génériques

Les types conditionnels peuvent également être utilisés avec des types génériques pour créer des définitions de type plus flexibles et réutilisables. Par exemple, un type qui extrait le type de retour d'une fonction:

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

type FunctionType = (x: number) => string;

type Result = ReturnType;  // Result is string

Dans cet exemple, ReturnType utilise le mot-clé infer pour déduire le type de retour R du type de fonction T. Si T est un type de fonction, ReturnType sera le type de retour; sinon, la valeur par défaut est never.

Types conditionnels avec types d'union

Les types conditionnels peuvent également fonctionner avec les types d'union pour gérer plusieurs types possibles. Par exemple, pour faire la distinction entre les différents membres d'une union:

type ExtractString = T extends string ? T : never;

type UnionType = string | number | boolean;

type Result = ExtractString;  // Result is string

Dans cet exemple, ExtractString extrait string d'un type d'union UnionType, ce qui donne string.

Types conditionnels avec mappages de types

Les types conditionnels peuvent être combinés avec des mappages de types pour créer des transformations de types plus complexes. Par exemple, le mappage sur un tableau de types pour appliquer un type conditionnel:

type MapArray = {
  [K in keyof T]: T[K] extends string ? T[K] : never;
};

type ArrayType = [string, number, boolean];

type MappedArray = MapArray;  // MappedArray is [string, never, never]

Dans cet exemple, MapArray mappe chaque élément du tableau T et applique un type conditionnel à chaque élément, ce qui donne un tableau où seuls les éléments de chaîne sont conservés.

Conclusion

Les types conditionnels dans TypeScript sont un outil puissant pour créer des définitions de types flexibles et expressives. En exploitant les types conditionnels, les développeurs peuvent modéliser des relations de type complexes, gérer divers scénarios et améliorer la sécurité des types dans leur code TypeScript. Comprendre comment utiliser efficacement les types conditionnels peut améliorer considérablement la capacité à écrire du code TypeScript robuste et maintenable.