Typescript - Tips & Tricks - Never type

Today I want to talk about the never type. As you can understand, this type identifies a piece of...

#typescript#webdev
Luca Del PuppoLuca Del Puppo
Article Series · Part 14 of 21TypeScript - Tips & Tricks
View full series (21)
  1. #13Previous
    Non-null assertion operator
  2. #14Reading now
    Never type
  3. #15Up next
    Assert Function
Browse all 21 parts in this series
  1. #1typeof
  2. #2Literal Types
  3. #3keyof
  4. #4Union and Intersection
  5. #5Overloaded Functions
  6. #6this parameter
  7. #7any vs. unknown
  8. #8Optional modifier
  9. #9Index Signature
  10. #10readonly modifier
  11. #11Readonly Array
  12. #12Tuple
  13. #13Non-null assertion operator
  14. #14Never typeCurrent
  15. #15Assert Function
  16. #16Type Guard
  17. #17Conditional Type
  18. #18infer keyword
  19. #19Mapped Types
  20. #20Advanced Types
  21. #21Rest Parameters & Rest Arguments

Today I want to talk about the never type. As you can understand, this type identifies a piece of code that will never be executed or represents a state that shouldn’t exist. Here an example

const throwException: () => never = () => {
    throw new Error();
};
throwException()
console.log('never called');

In this simple example, you can see how the “throwException” method never permits the code execution of the console.log. In this case, the “throwException” method returns the never type because the method doesn’t return any value but throws an error. To better understand the never type I show you another simple example

type Square = {
    kind: "square";
    size: number;
};

type Rectangle = {
    kind: "rectangle";
    with: number;
    height: number;
};

type Circle = {
    kind: "circle";
    radius: number;
};

type Shape = Square | Rectangle | Circle;

const area = (shape: Shape): number => {
    if (shape.kind === "square") return shape.size * shape.size;
    if (shape.kind === "rectangle") return shape.with * shape.height;
    // if (shape.kind === "circle") return shape.radius * 2 * Math.PI;

    const _exhaustiveCheck: never = shape; // Type 'Circle' is not assignable to type 'never'.
    return _exhaustiveCheck;
};

In this example, you can see how the “area” method detects the kind of the shape and it calculates the relative area. I leave the circle type comment voluntarily, so I can show you the power of the never type. At the end of the area method, you can see how the code assigns the shape to the field “_exhaustiveCheck” of type never. In this case, the typescript language detects that if you pass a circle shape at the area method, the line “const _exhaustiveCheck: never = shape;” will be executed, so it notifies you raising an error. The typescript language detects that the never type could be executed at runtime so it tries to prevent this problem. To fix this problem the previous method can be reviewed in this way

type Square = {
    kind: "square";
    size: number;
};

type Rectangle = {
    kind: "rectangle";
    with: number;
    height: number;
};

type Circle = {
    kind: "circle";
    radius: number;
};

type Shape = Square | Rectangle | Circle;

const area = (shape: Shape): number => {
    if (shape.kind === "square") return shape.size * shape.size;
    if (shape.kind === "rectangle") return shape.with * shape.height;
    if (shape.kind === "circle") return shape.radius * 2 * Math.PI;

    const _exhaustiveCheck: never = shape;
    return _exhaustiveCheck;
};

Now the code is compiled successfully and the never type is assigned correctly.

From the never type it’s all. See you soon guys

Luca Del Puppo

Written by Luca Del Puppo

Run, Code & Learn

AI Native Engineer at Nearform based in Povegliano (TV), Italy. Google Developer Expert in Web Technologies, GitKraken Ambassador, and Codemotion Ambassador.