Exhaustive checking helps you catch all possible cases in your code. Using never ensures you don't miss any case, making your program safer and less buggy.
Exhaustive checking with never in Typescript
function assertNever(value: never): never { throw new Error(`Unexpected value: ${value}`); } switch (value) { case 'a': // handle 'a' break; case 'b': // handle 'b' break; default: assertNever(value); // ensures all cases handled }
The assertNever function takes a never type, which means it should never be called if all cases are handled.
If a new case is added to the union type but not handled in the switch, TypeScript will show an error at assertNever.
Fruit but not handled, TypeScript will error at assertNever.type Fruit = 'apple' | 'banana'; function checkFruit(fruit: Fruit) { switch (fruit) { case 'apple': console.log('Apple is red'); break; case 'banana': console.log('Banana is yellow'); break; default: assertNever(fruit); } } function assertNever(x: never): never { throw new Error(`Unexpected value: ${x}`); }
default case uses assertNever to catch any unknown shape kind.type Shape = { kind: 'circle'; radius: number } | { kind: 'square'; size: number };
function area(shape: Shape): number {
switch (shape.kind) {
case 'circle':
return Math.PI * shape.radius ** 2;
case 'square':
return shape.size ** 2;
default:
return assertNever(shape);
}
}
function assertNever(x: never): never {
throw new Error(`Unexpected shape: ${JSON.stringify(x)}`);
}This program moves in a direction. The assertNever function ensures all directions are handled. If you add a new direction but forget to handle it, TypeScript will warn you.
type Direction = 'up' | 'down' | 'left' | 'right'; function move(direction: Direction) { switch (direction) { case 'up': console.log('Moving up'); break; case 'down': console.log('Moving down'); break; case 'left': console.log('Moving left'); break; case 'right': console.log('Moving right'); break; default: assertNever(direction); } } function assertNever(x: never): never { throw new Error(`Unknown direction: ${x}`); } move('up'); move('left');
Always use never with a function like assertNever to get compile-time checks.
This technique works best with union types and switch statements.
If you get an error at assertNever, it means you forgot to handle a case.
Exhaustive checking helps catch missing cases in your code.
Using never with a helper function forces you to handle all cases.
This makes your code safer and easier to maintain.