The never
type in TypeScript represents the set of values for functions that never return a valid value.
This generally means that the function throws an exception or enters an infinite loop and never completes its execution normally.
Although it is less common than types like string
, number
, or boolean
, the never
type plays an important role in handling cases that should not occur (such as errors or unreachable situations).
Some characteristics of the never
type are:
- Has no values:
never
does not support values of any type. - Subtype of all types:
never
is a subtype of any other type. This means thatnever
can be assigned to any other type, but not the other way around.
How to use the never type
The never
type is primarily used in two contexts:
- Functions that throw exceptions or enter infinite loops
- In control flow structures to handle unreachable cases.
Let’s see it with some examples,
Functions that throw exceptions
function throwError(message: string): never {
throw new Error(message);
}
throwError("A critical error has occurred");
In this example, the throwError
function takes an error message as a parameter and throws an exception. Since this function never completes its execution normally (instead of returning a value, it always throws an error), its return type is never
.
Functions with infinite loops
function infiniteLoop(): never {
while (true) {
// The loop never ends
}
}
The infiniteLoop
function enters a loop that never ends, so it cannot return any value or reach a normal conclusion. Therefore, its return type is never
.
Unreachable cases in control flow structures
The never
type is also used in exhaustive checks to ensure that all possible cases have been handled in a control flow structure, such as a switch
.
type Animal = "Dog" | "Cat" | "Bird";
function describeAnimal(animal: Animal): string {
switch (animal) {
case "Dog":
return "It's a dog";
case "Cat":
return "It's a cat";
case "Bird":
return "It's a bird";
default:
// Here, the type of `animal` should be `never`, as all possible cases have been handled
const _: never = animal;
throw new Error("Unexpected animal type");
}
}
In this example,
- The
default
case in theswitch
should handle any value that has not been covered by the previous cases - The assignment of
never
to the variable_
ensures that the TypeScript compiler checks that all possible cases are covered - If more types are added to
Animal
and theswitch
cases are not updated, TypeScript will generate an error