Skip to content

Discriminated union narrowed incorrectly by user-defined type predicate #40035

@jamesjuett

Description

@jamesjuett

TypeScript Version: 4.0.0-dev.20200803

Search Terms:
discriminated union
union
type predicate
type guard
narrow

Code

interface A {
    kind: "A";
    foo?: string;
}

interface AA extends A {
    foo: string;
}

interface B {
    kind: "B";
    foo: string;
}

interface BB extends B {
    //blah: string; // comment or uncomment this line
}

function isDefiniteFoo(x: A | B) : x is AA | BB {
    return !!x.foo;
}


let x!: A | B;
if (isDefiniteFoo(x)) {
    // Without line 16, the type of x is narrowed to B
    // If line 16 is present, the type of x is narrowed to AA | BB
    let z = x;

    // Note that BB isn't required to expose the bug. If the return type on
    // isDefiniteFoo is : x is AA | B, x is still narrowed to B rather than AA | B
}

Expected behavior:
The type of x should be narrowed to AA | BB.

Actual behavior:
The type of x is narrowed to B.

Playground Link:
https://www.typescriptlang.org/play?ts=4.0.0-dev.20200803#code/JYOwLgpgTgZghgYwgAgILIN4Chm+Qa1ABMAuZAIlXIG4c8YB7BgfjIGcwpQBzWgXyxZQkWIhSp0EAB6QQRNmkx1cjBu049+g4dHhJkAISV4CxMuQM1lyVeq4heWAUPC6xho9NnzDxvAHp-ACMAGzgACztNZEDkBAYAWwSIcGQGKGQAVxB4pJSwZDBw4AUQ0AgnQRhshDBgBhBkEoARCBhQYEgAMSYACikydAAfQwBKZDIpJoUJZBGDI2wTKAgwTKhGgEJNqQA6VS1BENXkKU3BucNaYBhkXpa2ju6+qVHxpYD-ZAB1TvCGTIFMogFAARgAbAAaQrhFBgACeAAcUAxblMSsgQHAoFAGAB3CBEQoMQzWWIASVuwLB4OmyERKzY+WhRThSJRaLpWJx+MJxLQww81mOBQAXsgALynWhkr4AOQYkBhcAKC2mIAA5AUVgBHTLAFZEsAk6SIhhMmEoIKZbi7ZCUy3IFZrDaFdlpECy6atdogToQHokjGTOmzebQ9EKDjAEIhTHY3EEo0koxQFWwjJFOCNMOkvhAA

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions