Typescript Never Type

The Typescript Never type represents the type that never happens or the values that never occur. Never type represent a state which shouldn’t exist. A function returning ‘never’ cannot have a reachable end.

Never Type

The following are some of the scenarios where the Typescript infers the type as never.

  1. The return type of function that never returns (infinite loop or function that always throws an error)
  2. Variables when narrowed by a Type guard that can never be true

Functions that never return

There are a few scenarios where functions might not return. The following examples show two such scenarios. The first example is an infinite Loop and the second example throws an error. In both examples, the function never returns

//Infinite loop
// Inferred return type: never
var x = function infiniteLoop() {
   while (true) {
   }
}

// Always throws an error
// Inferred return type: never
var y=function throwError() {
 throw new Error("Some errors occurred");
}

TypeScript in both the above cases infers the type as never.

Type guard that can never be true

We use Type Guards to narrow down the type of an variable within a conditional block. The Typescript infers the type as never if the conditional block is impossible to happen

For Example in the code below the variable padding can be either a string or number. Hence the last else branch will never happen. The TypeScript infers the type of padding variable inside the last else branch as never

function padLeft(value: string, padding: string | number) {
  if (typeof padding === "number") {
    //Type of paddig is number
  }
  else if (typeof padding === "string") {
    //Type of paddig is string
  } else {
    //This part of the else loop never executes 
    //Type of paddig is never 
  }
}

Never Type in Function Declaration

In the example below, all functions throw errors. The function f & g are function expressions. TypeScript correctly infers the type as never. But the last function h is a function declaration where the type is inferred as void.

//inferred as never
let f = () => {
    throw new Error("Should never get here");
}

//inferred as never
let g = function() { 
    throw new Error("Should never get here");
}

//inferred as void
function h() { 
    throw new Error("Should never get here");
}

This is because of backward compatibility which you can read here

Characteristics of Never

You can assign Never to every other type.

let neverVar:never;

let v1:any
let v2:number
let v3:string
let v4:boolean
let v5:{}

v1=neverVar;
v2=neverVar;
v3=neverVar;
v4=neverVar;
v5=neverVar;

But you cannot assign any other type to never (except never itself).

let neverVar:never;

let v1:any
let v2:number
let v3:string
let v4:boolean
let v5:{}

//The following results in an error
neverVar=v1;       
neverVar=v2;
neverVar=v3;
neverVar=v4;
neverVar=v5;

The Typescript infers the return type as never if a function expression or arrow function.

  1. has no return type annotation
  2. has no return statement
  3. Or has a return statement which returns never
  4. does not have an endpoint

(for function declarations void is the default return type)

In the following examples, TypeScript infers the return type as never.

//function expression

let x = function (message) { 
  throw new (message);
};

//arrow function

let y = (message) => {
  throw new (message);
}

Not here as we specifically annotate the return type as void

let x1 = function (message):void { 
  throw new (message);
};

If a function has its return type annotated with never.

  1. All of its return statements (if any) must return never 
  2. The endpoint of the function must not be reachable.

The TypeScript compiler throws errors in the following examples as both the functions are annotated with never type. Because the first example returns a string and the second one has an endpoint.

//Both of the following results in an error

function x1(message):never { 
  return message;
};

function x2(message):never { 
  let y= message;
};

Void Vs Never

The never type looks very similar to void.

We use void when the function does return but does not return a value. The typescript infers the return value as void.

In the following example, the arrow function does not return anything. But it does finish and return the control to back to the main program. The Typescript infers the return type as void.

let z = (a:number, b:number) => {
  let c=a+b;
}

The never return type when the function does not return at all. In the following example, Typescript infers the return type as never as the program enters into an infinite loop.

let z = function infiniteLoop() {
 while (true) {
 }
}

The void type can have undefined or null as a value whereas never cannot have any value.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top