The difference between any, void, unknown and never in TypeScript

The article comes from a personal blog https://knightyun.github.io/2021/04/03/js-ts-type-compare , reprint, please state

TypeScript expands the basic types and language features of JavaScript. In order to cover the scenario of type checking, it derives some additional types. The applicable situations of any, unknown, void and never are easy to be confused. Here are some examples to distinguish them;

any

This should be the type that will be touched at the beginning in typescript. As the name suggests: any type, which is also the default type when the type declaration is not written in ts, that is, no constraints are made, and the type check will be skipped during compilation,

let val1: any;
val1 = 'abc';
val1 = 123;
val1 = true;

const arry: any[] = [123, 'abc', true, null];

void

void indicates that there is no type. On the contrary to any, there is no type. If it is a function, it should have no return value or return undefined. It is similar to the declaration of function without return value in C and other languages:

function voidFn(): void {}
function voidFn1(): void { return undefined; }
function voidFn2(): void { return; }

function voidFn3(): void { return 1; } // Error

Variables can also be declared as void type, but only undefined, null and void values can be assigned to this variable (if "strictNullChecks": false is set in the ts configuration file, an error will also be reported when assigning a value of null type):

let val1: void;
let val2: null = null;
let val3: undefined = undefined;
let val4: void;

val1 = val2; // "strictNullChecks": false reports an error
val1 = val3;
val1 = val4;

unknown

As the name suggests, unknown means unknown type. It is a new type introduced in typescript 3.0, that is, when writing code, it is not clear what kind of data type will be obtained, such as the data returned by the server interface, JSON The result returned by parse(); This type is equivalent to any, which can be understood as the safe version of the alternative any type specified on the official website (because the direct use of any type is not advocated);

It can be assigned to any type, but it cannot be assigned to other types except any and unknown. At the same time, it is not allowed to execute methods of unknown type variables (any can), for example:

let uk: unknown = 'abc';

uk = 123;
uk = true;
uk.toString(); // Error

let valAny: any = 'abc';
valAny.toString(); // 'abc'

let uk1: unknown = uk;
let uk2: any = uk;
let uk2: string = uk; // Error

never

Never, as the name suggests, represents the type of value that will never exist. It is a new type introduced in typescript 2.0. The concept is a little convoluted. Under what circumstances will a variable never have a value? In general, once a variable is declared, it will be assigned a value. Even if it is not specified, it will be initialized to undefined. Similarly, even if a function has a write return value, it will return undefined by default. It is not true that there is no return value:

let foo;
console.log(typeof foo); // 'undefined'

function bar() {};
console.log(typeof bar()); // 'undefined'

In fact, there are some cases where the value will never exist. For example, from the perspective of program operation, if a function throws an exception during execution, the function will never have a value (because throwing an exception will directly interrupt the program operation, so the program will not reach the return value, that is, it will never return if it has an unreachable end point):

function err(msg: string): never {
    throw new Error(msg);
}

// The function that has the chance to reach the end point also has a return value, and the compilation will report an error
function err1(): never { // Error
  if (Math.random() > 0.5) {
     throw new Error('message');
  }
}

Another extreme case is similar, that is, the code executing infinite loop in the function (dead loop), which also makes the program never run to the return value of the function and never return:

function loopForever(): never {
    while (true) {};
}

A variable can also be directly declared as a never type so that it will never have a value. In fact, it means that it can never be assigned a value, otherwise an error will be reported, which can form a protection mechanism;

let ne: never;

ne = 123; // Error

In addition, never is a subtype of all types, which means that it can be assigned to any type (provided that "strictnullchecks" in the configuration is false, otherwise the check fails);

let num: number = 123;
let ne: never;

num = ne;

At the same time, no type is a subtype of never, except never itself, that is, no type other than never can be assigned to variables of never type (if the premise is "strictNullChecks": true, never can also be assigned to never);

let ne1: never;
let ne2: never;

ne1 = ne2;

// any cannot be assigned to never
let any1: any = 123;
ne1 = any1; // Error

Tags: Javascript TypeScript ts

Posted by rcorlew on Fri, 25 Mar 2022 11:42:47 +1030