Suggest an editImprove this articleRefine the answer for “Exhaustive check through never”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**An exhaustive check** through `never` is a technique where, after handling every `case` of a discriminated union, the compiler verifies that the remaining type of the variable is `never`. **Key point:** if a new union variant is added without a matching `case`, TypeScript raises a compile error before the code ever runs.Shown above the full answer for quick recall.Answer (EN)ImageShort answer: make a **discriminated union** and add a `never`-based "guard" to the `switch`. Then, when a new variant is added, TypeScript will raise a compile error. --- ## The basic technique (exhaustive check through `never`) ```javascript type Shape = | { kind: "circle"; radius: number } | { kind: "square"; side: number } | { kind: "triangle"; base: number; height: number }; function area(s: Shape): number { switch (s.kind) { case "circle": return Math.PI * s.radius ** 2; case "square": return s.side ** 2; case "triangle": return (s.base * s.height) / 2; default: // if a new variant appears, s will NOT be 'never' here → error const _exhaustive: never = s; throw new Error(`Unhandled case: ${_exhaustive}`); } } ``` - When you add, for example, `{ kind: "rectangle" }`, `s` in `default` stops being `never` → a **compile error** forces you to add the `case`. --- ## A variant with a helper function `assertNever` Convenient if you do this check often: ```javascript function assertNever(x: never): never { throw new Error(`Unhandled case: ${String(x)}`); } function area(s: Shape): number { switch (s.kind) { case "circle": return Math.PI * s.radius ** 2; case "square": return s.side ** 2; case "triangle": return (s.base * s.height) / 2; default: return assertNever(s); // a type error fires here on a new variant } } ``` --- ## Without `default`: a "post-switch" guard If you don't want a `default`, you can require every branch to return a value, and then check `never` after the `switch`: ```javascript function area(s: Shape): number { switch (s.kind) { case "circle": return Math.PI * s.radius ** 2; case "square": return s.side ** 2; case "triangle": return (s.base * s.height) / 2; } const _exhaustive: never = s; // fires when a new kind is added return _exhaustive; } ``` --- ## Useful settings and linting - The ESLint rule `@typescript-eslint/switch-exhaustiveness-check` highlights unclosed `switch` statements. - The compiler flag `noFallthroughCasesInSwitch` helps avoid fallthrough between `case`s (not about exhaustiveness, but useful). --- ### Summary To guarantee that a `switch` handles **all** variants of a union: 1. Use a **discriminant field** (for example, `kind`). 2. Add an **exhaustive check** by assigning to `never` (in `default` or after the `switch`). 3. (Optionally) Extract the check into `assertNever`.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.