Chapter 2 · Practice 3 of 6
Make switches exhaustive with a never check
Why it matters
When you add a new variant to a union, every switch that handles it should fail to compile until it handles the new case. TypeScript can do this for you: after all cases are handled, the value's type narrows to never. Assigning it to a never variable in the default branch is an error the moment a case is missing.
The handbook calls this exhaustiveness checking. It turns "remember to update all the switches" into a compiler error that lists each place to change.
Do
- End every switch over a union with a
defaultthat assigns tonever - Keep the helper in a shared utility so the pattern is consistent
Avoid
- A
defaultbranch that silently returns a fallback for unknown variants
Example
function assertNever(value: never): never {
throw new Error(`Unhandled case: ${JSON.stringify(value)}`);
}
function icon(state: RequestState<unknown>): string {
switch (state.status) {
case 'idle': return 'circle';
case 'loading': return 'spinner';
case 'success': return 'check';
case 'error': return 'alert';
default: return assertNever(state); // error here if a status is added
}
}