Skip to content

Narrowing fails after User-Defined Type Guard  #31407

Closed
@kube

Description

@kube

TypeScript Version: 3.4.3

Search Terms:
user-defined type guard, condition, inference, narrow, control-flow

Code

type A = {
    type: 'A',
    aProp: 42
}

type B = {
    type: 'B',
    bProp: 42
}

type AorB = A | B

function isAorB(obj: unknown): obj is AorB { 
    return true
}


// Does not work if narrowed with if/else

let x: any

if (isAorB(x)) {
    if (x.type === 'A') {
        x.aProp // ERROR (x still AorB)
    } else {
        x.bProp // ERROR (x still AorB)
    }
}


// Curriously works with switch/case

if (isAorB(x)) {
    switch (x.type) {
        case 'A':
            x.aProp // WORKS (x is A)
            break;

        default:
            x.bProp // WORKS (x is B)
    }
}

Expected behavior:

After passing User-Defined Type Guard, it should be possible to narrow this type using classical control flow.

Actual behavior:

After passing a User-Defined Type Guard, it's not possible to narrow using if/else control flow.

It works with switch/case though.

Playground Link:

https://www.typescriptlang.org/play/#src=type%20A%20%3D%20%7B%0A%20%20%20%20type%3A%20'A'%2C%0A%20%20%20%20aProp%3A%2042%0A%7D%0A%0Atype%20B%20%3D%20%7B%0A%20%20%20%20type%3A%20'B'%2C%0A%20%20%20%20bProp%3A%2042%0A%7D%0A%0Atype%20AorB%20%3D%20A%20%7C%20B%0A%0Afunction%20isAorB(obj%3A%20unknown)%3A%20obj%20is%20AorB%20%7B%20%0A%20%20%20%20return%20true%0A%7D%0A%0A%0A%2F%2F%20Does%20not%20work%20if%20narrowed%20with%20if%2Felse%0A%0Alet%20x%3A%20any%0A%0Aif%20(isAorB(x))%20%7B%0A%20%20%20%20if%20(x.type%20%3D%3D%3D%20'A')%20%7B%0A%20%20%20%20%20%20%20%20x.aProp%20%2F%2F%20ERROR%20(x%20still%20AorB)%0A%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20x.bProp%20%2F%2F%20ERROR%20(x%20still%20AorB)%0A%20%20%20%20%7D%0A%7D%0A%0A%2F%2F%20Curriously%20works%20with%20switch%2Fcase%0A%0Aif%20(isAorB(x))%20%7B%0A%20%20%20%20switch%20(x.type)%20%7B%0A%20%20%20%20%20%20%20%20case%20'A'%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20x.aProp%20%2F%2F%20WORKS%20(x%20is%20A)%0A%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%0A%20%20%20%20%20%20%20%20default%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20x.bProp%20%2F%2F%20WORKS%20(x%20is%20B)%0A%20%20%20%20%7D%0A%7D%0A

Related Issues:

Activity

jack-williams

jack-williams commented on May 15, 2019

@jack-williams
Collaborator

Duplicate of #30557

typescript-bot

typescript-bot commented on May 19, 2019

@typescript-bot
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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

        Participants

        @kube@jack-williams@RyanCavanaugh@typescript-bot

        Issue actions

          Narrowing fails after User-Defined Type Guard · Issue #31407 · microsoft/TypeScript