Vérifier l’exhaustivité avec never
Détecter les cas non traités à la compilation avec never.
Vérifier l’exhaustivité avec never est une leçon TypeScript Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage TypeScript Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours TypeScript Academy comprend 4 leçons au total.
Le problème de l'exhaustivité
Lorsque vous ajoutez un nouveau membre à une union, il est facile d'oublier de le traiter quelque part. La vérification de l'exhaustivité transforme cet oubli en erreur de compilation.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
// If we add "triangle" later, we want every switch to complain.Le type impossible
Le type never représente des valeurs qui ne peuvent jamais se produire. Si tous les cas sont traités, la valeur qui atteint la branche par défaut est de type never.
function fail(): never {
throw new Error("unreachable");
}
// never is assignable to nothing except never itself.Affecter le type impossible dans le cas par défaut
Dans la branche default, affectez la valeur à une variable de type never. Si toutes les variantes sont traitées, l'affectation est compilée ; sinon, elle provoque une erreur.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function area(s: Shape): number {
switch (s.kind) {
case "circle": return Math.PI * s.radius ** 2;
case "square": return s.side ** 2;
default:
const _exhaustive: never = s;
return _exhaustive;
}
}
console.log(area({ kind: "square", side: 3 }));Que se passe-t-il lorsque vous oubliez un cas ?
Si vous ajoutez un membre triangle mais oubliez son cas, s dans la branche par défaut n'est plus de type never et l'affectation échoue lors de la compilation.
// type Shape = ... | { kind: "triangle"; base: number; height: number };
// Now in default, s is { kind: "triangle"; ... }
// const _exhaustive: never = s; // Error: triangle not assignable to neverL'utilitaire assertNever
Une fonction assertNever réutilisable centralise ce modèle. Elle accepte une valeur de type never et lève une exception, indiquant que cette branche devrait être inaccessible.
function assertNever(value: never): never {
throw new Error("Unhandled case: " + JSON.stringify(value));
}
console.log(typeof assertNever);Utiliser assertNever dans une sélection
Appelez assertNever(s) dans le cas par défaut. Cela impose l'exhaustivité lors de la compilation et produit une erreur claire à l'exécution si cette branche est atteinte.
function assertNever(value: never): never {
throw new Error("Unhandled: " + JSON.stringify(value));
}
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function area(s: Shape): number {
switch (s.kind) {
case "circle": return Math.PI * s.radius ** 2;
case "square": return s.side ** 2;
default: return assertNever(s);
}
}
console.log(area({ kind: "circle", radius: 1 }).toFixed(2));Sécurité à la compilation et à l'exécution
La vérification avec never détecte les cas manquants avant l'exécution du code, et l'erreur levée vous protège si quelque chose échappe à la vérification des types lors de l'exécution.
function assertNever(x: never): never {
throw new Error("Unhandled: " + String(x));
}
// Compile error if a case is missing; runtime throw as a backstop.
console.log("two layers of safety");Exhaustivité sans cas par défaut
Si votre fonction possède un type de retour explicite et qu'une instruction switch couvre tous les cas, TypeScript peut également signaler une valeur de retour manquante : c'est une autre forme d'exhaustivité.
type Light = "red" | "yellow" | "green";
function next(l: Light): Light {
switch (l) {
case "red": return "green";
case "yellow": return "red";
case "green": return "yellow";
}
// No default needed; all cases return.
}
console.log(next("red"));Exhaustivité avec des chaînes de conditions
La même idée fonctionne avec if/else. Après avoir traité chaque variante, le dernier else reçoit une valeur de type never.
function assertNever(x: never): never { throw new Error("bad"); }
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function name(s: Shape): string {
if (s.kind === "circle") return "circle";
else if (s.kind === "square") return "square";
else return assertNever(s);
}
console.log(name({ kind: "square", side: 2 }));Pourquoi never est l'outil adapté
Comme aucun type ne peut être affecté à never, toute variante restante fait échouer l'affectation. Cela fait de never le détecteur idéal des cas non traités.
// Only never is assignable to never.
let x: never;
// x = "hi"; // Error
// Any concrete leftover type fails the same way.
console.log("never catches gaps");L'exhaustivité comme filet de sécurité lors de la refactorisation
Avec assertNever partout, l'ajout d'un membre à une union produit une liste claire d'erreurs de compilation indiquant précisément chaque endroit à mettre à jour.
function assertNever(x: never): never { throw new Error("unhandled"); }
type Status = "idle" | "busy";
function render(s: Status): string {
switch (s) {
case "idle": return "Idle";
case "busy": return "Busy";
default: return assertNever(s);
}
}
console.log(render("idle"));Vérification rapide : exhaustivité
Vérifiez votre compréhension de la vérification de l'exhaustivité.
Récapitulatif : exhaustivité avec le type impossible
Vous avez appris à affecter la valeur par défaut à never (ou à la transmettre à assertNever) afin que le compilateur vous oblige à traiter chaque variante. Les cas oubliés deviennent ainsi des erreurs de compilation.
function assertNever(x: never): never { throw new Error("unhandled"); }
type Shape = { kind: "circle"; radius: number } | { kind: "square"; side: number };
function f(s: Shape) {
switch (s.kind) {
case "circle": return s.radius;
case "square": return s.side;
default: return assertNever(s);
}
}
console.log(f({ kind: "circle", radius: 5 }));Questions Fréquemment Posées
La leçon « Vérifier l’exhaustivité avec never » est-elle gratuite ?
Oui — le texte complet de « Vérifier l’exhaustivité avec never » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours TypeScript Academy, passe à CoddyKit PRO. Le cours TypeScript Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Vérifier l’exhaustivité avec never » ?
Détecter les cas non traités à la compilation avec never. Tu pratiques TypeScript Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer TypeScript Academy ?
Aucune expérience préalable n'est requise. TypeScript Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.
Combien de temps prend la leçon « Vérifier l’exhaustivité avec never » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon TypeScript Academy ?
Oui. Chaque leçon TypeScript Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Construire des unions discriminées
- Restreindre selon le discriminant
- Vérifier l’exhaustivité avec never
- Modéliser des machines à états