Skip to content

Add 'never' type - #8652

Merged
Anders Hejlsberg (ahejlsberg) merged 6 commits into
masterfrom
neverType
May 18, 2016
Merged

Add 'never' type#8652
Anders Hejlsberg (ahejlsberg) merged 6 commits into
masterfrom
neverType

Conversation

@ahejlsberg

@ahejlsberg Anders Hejlsberg (ahejlsberg) commented May 17, 2016

Copy link
Copy Markdown
Member

This PR introduces a never type that represents the type of values that never occur. Specifically, never is the return type for functions that never return and never is the type of variables under type guards that are never true. The never type has the following characteristics:

  • never is a subtype of and assignable to every type.
  • No type is a subtype of or assignable to never (except never itself).
  • In a function expression or arrow function with no return type annotation, if the function has no return statements, or only return statements with expressions of type never, and if the end point of the function is not reachable (as determined by control flow analysis), the inferred return type for the function is never.
  • In a function with an explicit never return type annotation, all return statements (if any) must have expressions of type never and the end point of the function must not be reachable.

Because never is a subtype of every type, it is always omitted from union types and it is ignored in function return type inference as long as there are other types being returned.

The never type replaces the nothing type introduced in #8340 and it is effectively the same as the bottom type proposed in #3076.

Some examples of functions returning never:

// Function returning never must have unreachable end point
function error(message: string): never {
    throw new Error(message);
}

// Inferred return type is never
function fail() {
    return error("Something failed");
}

// Function returning never must have unreachable end point
function infiniteLoop(): never {
    while (true) {
    }
}

Some examples of use of functions returning never:

// Inferred return type is number
function move1(direction: "up" | "down") {
    switch (direction) {
        case "up":
            return 1;
        case "down":
            return -1; 
    }
    return error("Should never get here");
}

// Inferred return type is number
function move2(direction: "up" | "down") {
    return direction === "up" ? 1 :
        direction === "down" ? -1 :
        error("Should never get here");
}

// Inferred return type is T
function check<T>(x: T | undefined) {
    return x || error("Undefined value");
}

Because never is assignable to every type, a function returning never can be used when a callback returning a more specific type is required:

function test(cb: () => string) {
    let s = cb();
    return s;
}

test(() => "hello");
test(() => fail());
test(() => { throw new Error(); })

Fixes #3076.
Fixes #8602.

@DanielRosenwasser

Copy link
Copy Markdown
Member

I really don't think this name is good for the general user experience. My feeling is that it seems to model several different things which the name doesn't reflect very well on. At least nothing reflected the domain of values a little bit better.

@ahejlsberg Anders Hejlsberg (ahejlsberg) changed the title Add 'never type Add 'never' type May 17, 2016
@ahejlsberg

Anders Hejlsberg (ahejlsberg) commented May 17, 2016

Copy link
Copy Markdown
Member Author

Daniel Rosenwasser (@DanielRosenwasser) The primary use for never is as the return type of functions that never return. I'm hard pressed to come up with a more concise and descriptive name. Certainly nothing isn't in my mind.