The never Type
Using never for unreachable code, exhaustive switches, and filtering impossible union branches.
never is TypeScript's bottom type: a type with no possible values. It appears when a function never returns, when narrowing exhausts a union, and when type-level filtering removes a branch.
A function that always throws can return never. An assertUnreachable helper uses that fact to make missing cases fail at compile time.
function fail(message: string): never {
throw new Error(message);
}
function assertUnreachable(x: never): never {
return fail(`Unhandled case: ${JSON.stringify(x)}`);
}
type Direction = "north" | "south" | "east" | "west";
function move(dir: Direction): string {
switch (dir) {
case "north":
return "moving north";
case "south":
return "moving south";
case "east":
return "moving east";
case "west":
return "moving west";
default:
return assertUnreachable(dir);
}
}When a teammate adds a new union member, every switch that forgets it points at the never check.
type ApiEvent =
| { type: "success"; data: { id: string } }
| { type: "error"; message: string }
| { type: "loading" };
declare function renderUser(user: { id: string }): void;
declare function showError(message: string): void;
declare function showSpinner(): void;
function handleEvent(event: ApiEvent): void {
switch (event.type) {
case "success":
renderUser(event.data);
break;
case "error":
showError(event.message);
break;
case "loading":
showSpinner();
break;
default:
assertUnreachable(event);
}
}In production
Put assertUnreachable in a shared utils/types.ts. It turns a forgotten
branch into a CI failure, which is exactly what you want for events, reducer
actions, API statuses, and feature-flag states. The next lesson shows the
other major use: returning never to filter members out of a union.