ProgrammationDéveloppeur Frontend

Qu'est-ce que les types distributifs (Distributive Types) en TypeScript, où sont-ils utilisés et quelles particularités faut-il prendre en compte lors de leur utilisation ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

Les types distributifs (Distributive Types) sont une fonctionnalité de TypeScript qui se manifeste lors de l'utilisation des types conditionnels (T extends U ? X : Y). Lorsque la variable de type à gauche de extends est une union, TypeScript distribue la condition sur chaque élément de l'union.

Exemple :

// "Test<A> | Test<B> | Test<C>" type Test<T> = T extends string ? () => string : () => number; type Result = Test<'A' | 'B' | 'C'>;

Ici, Result se distribue comme :

  • Test<'A'> | Test<'B'> | Test<'C'>

Quand les appliquer — pour écrire des API génériques, pour manipuler des unions, par exemple pour le filtrage ou le matching.

Particularités :

  • Si on enveloppe T dans un tuple [T], la distribution ne se produira pas. C'est une manière de "désactiver" la distribution.
  • La distribution ne fonctionne que pour les variables de type (et non pour les littéraux).

Question piège

Question : Le type T[] extends number[] ? true : false sera-t-il distributif ?

Réponse correcte : Non, la distribution se produit uniquement si à gauche la variable de type n'est pas enveloppée dans un tableau ou un tuple. Par exemple, le type conditionnel T extends number ? ... distribuera, mais T[] extends number[] ? ... — non.


Exemples d'erreurs réelles dues à l'ignorance des subtilités du sujet


Histoire

Projet : Bibliothèque de validation des props pour des composants React. Nous voulions réaliser un type transformant les props union en une interface stricte, mais en raison d'une mauvaise compréhension de la distribution, le type est devenu inattendu complexe (les propriétés des membres de l'union se sont mélangées). Nous avons corrigé cela en ajoutant une enveloppe [T], afin que la distribution ne se produise pas.


Histoire

Projet : Développement d'une fonction de gestion qui acquerrait tous les types d'événements. Dans le type conditionnel, nous nous attendions à ce que la fonction accepte chaque type d'événement par distribution, mais sans utilisation explicite de celle-ci, nous avons mal implémenté le traitement, ce qui a conduit à des types d'arguments incorrects (union au lieu d'appels individuels pour chaque type).


Histoire

Projet : Lors de la création de nos propres types utilitaires (comme Exclude, Extract), nous avons oublié que la distribution ne se produirait pas pour les tuples et les tableaux. En conséquence, le type Exclude ne fonctionnait pas pour les tableaux (par exemple, le type Exclude<["a"|"b"], "b"> ne supprimait pas "b").