Learn how the never type represents impossible values and enables compile-time exhaustive switch statement validation.
Discover how TypeScript infers types automatically and how let versus const declarations shape wide types versus narrow literal types.
In TypeScript's type theory, never represents the type of values that can never occur.
never Appears Automaticallynever is automatically inferred as the return type for functions that throw errors indefinitely or contain infinite loops:
// Infered return type: never
function throwError(message: string): never {
throw new Error(message);
}
function infiniteLoop(): never {
while (true) {}
}
The most powerful application of never is Exhaustiveness Checking inside switch statements. By assigning an unhandled union case to a variable of type never, TypeScript will throw a compile-time error whenever a new union case is added without updating the switch statement!
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number }
| { kind: "triangle"; base: number; height: number }; // Newly added shape!
function calculateArea(shape: Shape): number {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.side * shape.side;
case "triangle":
return 0.5 * shape.base * shape.height;
default: {
// Exhaustiveness check!
// If a case is missing, shape will NOT be 'never', triggering a compile error!
const _exhaustiveCheck: never = shape;
return _exhaustiveCheck;
}
}
}
[ Union Member Added ] ──> "triangle"
│
▼
[ Default Switch Branch ] ──> Assigned to 'never' -> Compile Error: Type 'triangle' not assignable to 'never'!
never, adding new union members silently fails at runtime without compile warnings!Use exhaustiveness checks on all discriminated unions. Next, let me explain Index Signatures and Mapped Types!