Let’s break down never in TypeScript in detail with examples, subtype/supertype explanation, and a comparison table with any and unknown.
TypeScript has some special types that play a key role in its type system. One of the most powerful — and sometimes confusing — is never.
At first glance, it looks abstract, but understanding it helps you write safer, more predictable code.
What is never?
neverrepresents the type of values that never occur.- It is the opposite of
any:anymeans “it could be anything”.nevermeans “it could be nothing”.
- It is used in functions that cannot produce a value because:
- They throw an error.
- They run forever (infinite loop).
- A variable cannot logically exist in a certain branch.
never in the Type Hierarchy
neveris a subtype of all types.- But it is not a supertype of anything.
- That means you can assign
neverto any type, but nothing can be assigned tonever(exceptneveritself).
let neverValue: never;
// neverValue = "Hello"; // ❌ Error
// neverValue = 123; // ❌ Error
// But never can be assigned to other types:
let str: string;
let num: number;
function fail(): never {
throw new Error("This will never return");
}
str = fail(); // ✅ OK
num = fail(); // ✅ OK
Example 1: Functions that Always Throw
A function that throws an error never returns a value → its return type is never.
function throwError(message: string): never {
throw new Error(message);
}
Example 2: Functions with Infinite Loops
A function that never ends also has return type never.
function infiniteLoop(): never {
while (true) {
console.log("Running forever...");
}
}
Example 3: Exhaustiveness Checking with never
never is very useful in type-safe switch statements.
type Shape = { kind: "circle"; radius: number }
| { kind: "square"; size: number };
function getArea(shape: Shape): number {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.size * shape.size;
default:
// If we add a new shape and forget to handle it,
// TypeScript will detect an error here.
const _exhaustiveCheck: never = shape;
return _exhaustiveCheck;
}
}
If you later add { kind: "triangle" } to Shape, TypeScript will force you to handle it in the switch.
Comparison: any vs unknown vs never
| Feature | any | unknown | never |
|---|---|---|---|
| Meaning | “Can be anything” | “Can be anything, but must be checked before use” | “Can never exist” |
| Supertype / Subtype | Both supertype and subtype of all types | Supertype of all types (subtype only of itself and any) | Subtype of all types (supertype of nothing) |
| Assignable to all types | ✅ Yes | ❌ No | ✅ Yes |
| Accepts all values | ✅ Yes | ✅ Yes | ❌ No |
| Typical usage | Quick prototyping, legacy JS | API responses, unknown data | Impossible code paths, functions that don’t return |
| Safety | ❌ Unsafe | ✅ Safe | ✅ Very strict |
Practical Use Cases for never
- Error-throwing functions
function crash(): never { throw new Error("Something went wrong!"); } - Infinite processes (e.g., server loop)
function listenForever(): never { while (true) { // keep listening to messages } } - Exhaustive type checking in
switchorif-elsechains
Ensures all cases are handled in discriminated unions. - Helper for impossible cases
function assertNever(x: never): never { throw new Error("Unexpected object: " + x); }
Conclusion
neveris the type of nothing — values that can never exist.- It is a subtype of all types but not a supertype.
- Functions that never return (error, infinite loop) have return type
never. - It shines in exhaustive checks to ensure type safety in union types.
- Compared to
anyandunknown, it provides the strictest safety guarantees.
👉 If any means “everything” and unknown means “something, but check first”, then never means “nothing at all”.