Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding the never type in TypeScript 2

While taking a look at what's new in TypeScript 2.0, I've found the never type. According to the docs, it seems like it's a clever way of setting the type of functions that never return.

Now, if I read everything correctly, then never can be assignable to every type, but only never can be assigned to never. So, while writing a small test in VS Code, I've ended up with the following:

function generateError(){
    throw new Error("oops");
}
function do(option: "opt1" | "opt2"){
    if(option === "opt1") return true;
    if(option === "opt2 ) return false;
    generateError();
}
let res = do("blah");

Well, what's the expected type of res? According to the compiler, it's string | undefined (which makes sense, though I must say I expected string). I guess I'm not seeing the point of having a new type just to represent functions that never return. Do we really need this concept? IS this just a compiler thing that helps it have better flow analysis?

like image 716
Luis Abreu Avatar asked Dec 19 '22 12:12

Luis Abreu


2 Answers

Never is information that this particular part shouldn't be reachable. For example in this code

function do(): never {
    while (true) {}
}

you have an infinite loop and we don't want to iterate infinite loop. Simply as that.

But a real question is how can it be useful for us? It might be helpful for instance while creating more advanced types to point what they are not

for example, let's declare our own NonNullable type:

type NonNullable<T> = T extends null | undefined ? never : T;

Here we are checking if T is null or undefined. If it is then we are pointing that it should never happen. Then while using this type:

let value: NonNullable<string>;
value = "Test";
value = null; // error
like image 50
Przemek Struciński Avatar answered Dec 25 '22 20:12

Przemek Struciński


You can use never to ensure that you won't miss a function contract.

function forever(): never {
    while (true) {
        break; // Error because you can't leave the function.
    }
}

enum Values {
    A,
    B
}

function choose(value: Values) {
    switch (value) {
        case Values.A: return "A";
    }

    let x: never = value; // Error because B is not a case in switch.
}
like image 44
Rodris Avatar answered Dec 25 '22 20:12

Rodris