Language: EN

tipo-never-typescript

Use of Never in TypeScript

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 that never 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 the switch 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 the switch cases are not updated, TypeScript will generate an error