Skip to main content

Never in a function

What the never type means

The never type denotes:

"This function will never complete successfully and will never return anything."

In other words, there is no path in the code where the function could return a value. It either:

  • throws an exception (throw),
  • or runs an infinite loop (while (true)),
  • or its completion is simply logically impossible.

Example 1. A function that throws an error

javascript
function throwError(message: string): never { throw new Error(message); }
  • The function does not return a value, it throws an exception.
  • After throw, execution never continues.

The never type shows that the code "interrupts execution" forever.


Example 2. A function with an infinite loop

javascript
function infiniteLoop(): never { while (true) { console.log("Running forever..."); } }
  • The loop never ends, so there is no point where a value could be returned.
  • TypeScript understands that the function can never complete, and assigns it the never type.

Example 3. An impossible code branch (exhaustiveness check)

This is the most common and most useful application of never, for checking that we have handled all possible cases in a switch or if.

javascript
type Shape = | { kind: "circle"; radius: number } | { kind: "square"; side: number }; function getArea(shape: Shape): number { switch (shape.kind) { case "circle": return Math.PI * shape.radius ** 2; case "square": return shape.side ** 2; default: // this branch is unreachable! const _exhaustiveCheck: never = shape; throw new Error(`Unknown shape: ${_exhaustiveCheck}`); } }

If later you add a new type, for example:

javascript
type Shape = | { kind: "circle"; radius: number } | { kind: "square"; side: number } | { kind: "triangle"; base: number; height: number };

TypeScript will raise an error:

Type 'triangle' is not assignable to type never.

That means you need to add a new case "triangle": branch.

This way, never helps you control the exhaustiveness of the logic.


Example 4. never in callbacks and generics

Sometimes never appears automatically, when TypeScript cannot infer a possible type (for example, in an empty array):

javascript
const arr: never[] = []; // an array that can never hold values

or in functions with a narrow type:

javascript
function fail(): never { throw new Error("Error"); } function process<T>(value: T): T { if (typeof value === "string") { return value.toUpperCase() as T; } fail(); // returns never, so TypeScript knows the code below never runs }

Key features of never

PropertyDescription
SemanticsThe function never returns a value
Occurs withthrow, while(true), "impossible" branches
Subtype of all typesnever can be assigned to anything (string, number, void, etc.)
But no type can be assigned to neverexcept never itself
Common useChecking exhaustive conditions (exhaustive check)

Comparison of never with other types

TypeDescriptionExample
voidThe function completes but returns nothingfunction log(): void { console.log("ok"); }
undefinedThe function returns undefinedfunction f(): undefined { return undefined; }
neverThe function never completesfunction loop(): never { while(true){} }

The simple way to remember it

The void type: the function completed, but did not return a value.

The never type: the function did not complete at all (an error, an infinite loop, unreachable code).


Final example

javascript
function doSomething(action: "run" | "stop" | "pause") { switch (action) { case "run": console.log("Running"); break; case "stop": console.log("Stopping"); break; case "pause": console.log("Pausing"); break; default: const impossible: never = action; // exhaustiveness check throw new Error(`Unexpected action: ${impossible}`); } }

If you forget one case, TypeScript will force you to add it.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.