Skip to content

Intersection type (T & never) should reduce to never, not T #16038

@jcalz

Description

@jcalz

TypeScript Version: 2.3.3 / master up to and including e2cc27b / since 424074b

Code

interface SomeType {
    name: string,
    size: number
}
var someObject:SomeType = { name: 'thing', size: 42 };

// the type (never & T) should reduce to never, but instead reduces to T:
var badIntersection: never & SomeType = someObject;

// but since (o ∈ A∩B) implies (o ∈ A) 
function upcast<A, B>(o: A & B): A {
    return o;
}

// then you can convert any value to type never
function toNever<T>(o: T): never {
    return upcast<never, T>(o);
}

// which seems like a problem
var seemsLikeAProblem: never = toNever('weirdness');

Expected behavior:
The type never is a bottom type; its set of possible values is empty. The intersection of any type with never should reduce to never.

Actual behavior:
The type checker reduces never & T to T. One bizarre consequence is the ability to cast any value to never.


This behavior was introduced in 424074b as a reduction rule appropriate for union types (as never | T should indeed reduce to T), and has been preserved ever since, most recently in b673d5f. It looks like an oversight and a bug to me, but maybe people rely on this behavior somewhere?

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFixedA PR has been merged for this issue

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions