Type union en TypeScript : une valeur, plusieurs types possibles

Un type union énumère les formes qu'une valeur peut prendre, séparées par une barre verticale : rétrécissement, union discriminée et exhaustivité.
3 min de lecture
Believemy logo

Une réponse d'API est soit une facture, soit un message d'erreur. Un statut vaut « brouillon », « envoyée » ou « payée », et rien d'autre.

Le type union sert à écrire exactement cela, puis à obliger le code à traiter chaque cas.


Définition

Un type union énumère les types qu'une valeur est autorisée à prendre, séparés par une barre verticale. La valeur en vaut un seul à la fois, et le compilateur refuse tout ce qui ne figure pas dans la liste.

JAVASCRIPT
type Statut = "brouillon" | "envoyee" | "payee";

let statutFacture: Statut = "payee";
statutFacture = "annulee";
// Type '"annulee"' is not assignable to type 'Statut'.

type Identifiant = string | number;

Les trois valeurs de Statut ne sont pas des types au sens habituel : ce sont des types littéraux, chacun n'acceptant qu'une seule chaîne. C'est ce qui remplace avantageusement une constante d'énumération maison.


Le rétrécissement

Tant que la valeur est une union, seules les propriétés communes à tous les membres sont accessibles. Un test suffit à réduire l'ensemble, et le compilateur suit le raisonnement branche par branche.

JAVASCRIPT
function taille(valeur: string | number): number {
  if (typeof valeur === "string") {
    return valeur.length;   // ici, valeur est une chaîne
  }
  return valeur;            // ici, c'est forcément un nombre
}

Trois opérateurs servent à ce rétrécissement : typeof pour les types primitifs, instanceof pour les classes, et in pour tester la présence d'une propriété. Une Égalité stricte (===) sur un type littéral fonctionne aussi.


L'union discriminée

Le cas le plus utile en pratique : chaque membre porte un champ commun dont la valeur l'identifie. Tester ce champ suffit alors à débloquer les autres propriétés du membre.

JAVASCRIPT
type ReponseApi =
  | { ok: true; facture: { id: number } }
  | { ok: false; erreur: string };

function afficher(reponse: ReponseApi) {
  if (reponse.ok) {
    console.log(reponse.facture.id);
  } else {
    console.log(reponse.erreur);
  }
}
Bon à savoir

Lire reponse.facture avant le test est refusé : la propriété n'existe pas sur le membre d'échec. L'union rend impossible l'oubli qui, en JavaScript, produit un undefined silencieux.


Questions fréquentes

Question

Quelle différence avec une intersection ?

L'union se note avec une barre verticale et signifie « l'un ou l'autre » ; l'intersection se note avec une esperluette et signifie « les deux à la fois ». La première réduit ce qui est accessible, la seconde l'augmente. On les confond souvent au début, parce que « ou » donne intuitivement l'impression d'élargir.


Question

Comment être certain de traiter tous les cas ?

Un switch sur le champ discriminant, sans branche default, avec un type de retour annoté : si un membre est oublié, le compilateur signale qu'un chemin ne rend rien. C'est le contrôle d'exhaustivité, et il se rappelle à vous le jour où un quatrième statut est ajouté.


Question

Une union peut-elle contenir null ?

Oui, et c'est même son usage le plus courant en mode strict : string | null décrit une valeur qui peut manquer, et le compilateur exige un test avant toute lecture. La Coalescence des nuls (??) et le Chaînage optionnel (?.) deviennent alors les deux outils qui allègent ces tests.

Termes connexes

Découvrez notre glossaire JavaScript

Tous les mots de JavaScript expliqués simplement : mots-clés, objets natifs, méthodes, erreurs et concepts. Définitions claires et exemples qui tournent, pour apprendre et pour se dépanner.

Partager cet article

Tu veux nous aider ? Fais un lien vers cet article sur tes réseaux ou encore mieux : sur ton site, dans un article ou dans ta newsletter.