Why exhaustiveness matters
When you extend a union type, existing switch statements silently miss new cases. Exhaustiveness checking turns that into a hard error:
type Event = { type: "click" } | { type: "keydown" };
// Add { type: "submit" } later -> assertNever fires
This is essential for domain models where an unhandled case should never compile, not just occasionally crash.
Narrowing to never
The compiler knows a fully narrowed union leaves no possible value:
const s: Shape = ...;
if (s.kind === "circle") { /* circle */ }
else if (s.kind === "square") { /* square */ }
else {
// here s: never
}
The final else block only runs if s is none of the union members, which is impossible. That impossibility is exactly what you assert on.