ProgrammationDéveloppeur Frontend

Comment fonctionne le mécanisme de typage des types union (types unis) dans TypeScript ? À quoi sert-il, comment fonctionne le rétrécissement de type et quels sont les nuances liés aux types union ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Contexte :

Les types union sont apparus dans TypeScript pour décrire des variables et des paramètres qui peuvent prendre des valeurs de différents types. Cela a considérablement élargi la flexibilité de la typisation par rapport aux langages classiques.

Problème :

Dans JavaScript, les fonctions et les variables sont souvent polymorphes (par exemple, acceptant un nombre ou une chaîne), ce qui complique la typisation sécurisée. Sans types union, il fallait utiliser any ou dupliquer le code. Cela augmentait le nombre d'erreurs en production et compliquait le travail dans de grandes équipes.

Solution :

Les types union permettent de déclarer une variable qui peut être de l'un des plusieurs types, en garantissant des opérations correctes après vérification. Le rétrécissement de type (type narrowing) est également implémenté, ce qui aide le compilateur à "comprendre" avec quoi il a affaire.

Exemple de code :

function formatId(id: number | string): string { if (typeof id === 'string') { return id.toUpperCase(); } return id.toString(); }

Caractéristiques clés :

  • Permettent de spécifier explicitement les types possibles des variables et des paramètres.
  • Fonctionnent avec le mécanisme de rétrécissement de type par le biais de vérifications (par exemple, typeof ou in).
  • Compliquent le travail avec des objets où la même clé peut avoir différents types — nécessitant une gestion prudente de la logique d'accès.

Questions pièges.

Peut-on enregistrer une union d'objets avec différentes propriétés et accéder à n'importe quelle propriété sans vérification ?

Non. Les types union permettent d'accéder uniquement aux propriétés et méthodes présentes dans tous les types. Pour accéder aux propriétés spécifiques, un rétrécissement de type est nécessaire.

Exemple de code :

type Fish = { swim: () => void; }; type Bird = { fly: () => void; }; function move(animal: Fish | Bird) { // animal.swim(); // Erreur sans rétrécissement if ('swim' in animal) { animal.swim(); // OK } }

Pourquoi toutes les méthodes ne sont-elles pas accessibles pour le type union string | number ?

TypeScript ne permet que ce qui est présent dans tous les types inclus. Pour les méthodes individuelles, il faut d'abord vérifier le type réel.

Que se passe-t-il si on ne vérifie pas le type dans une union et qu'on essaie d'appeler une méthode spécifique ?

Dans ce cas, une erreur de compilation se produira, car la présence de la méthode n'est pas garantie. Cela ne fonctionne qu'après avoir vérifié le type spécifique.

Erreurs typiques et anti-patrons

  • Omettre la vérification de type avant utilisation (peut entraîner une erreur d'accès).
  • Décrire des types union trop larges (perte de sécurité typique).
  • Un rétrécissement incorrect entraîne des erreurs invisibles et des vérifications non exhaustives.

Exemple de la vie réelle

Cas négatif

On attribue à une variable le type string | number et sans vérification, on fait un toUpperCase(). En résultat, l'application plante avec des données numériques.

Avantages :

  • Code écrit rapidement.

Inconvénients :

  • Erreurs à l'exécution.
  • Perte de confiance dans la typisation statique de TypeScript.

Cas positif

On vérifie le type avant d'utiliser la méthode :

if (typeof value === 'string') { return value.toUpperCase(); } else { return value.toString(); }

Avantages :

  • Sécurité totale au moment de la compilation.
  • Meilleure maintenabilité du code.

Inconvénients :

  • Nécessité d'écrire des vérifications supplémentaires.