Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'always false' field now narrowed in 'if' true-branch #39139

Closed
SQReder opened this issue Jun 18, 2020 · 4 comments
Closed

'always false' field now narrowed in 'if' true-branch #39139

SQReder opened this issue Jun 18, 2020 · 4 comments
Labels
Duplicate An existing issue was already created

Comments

@SQReder
Copy link

SQReder commented Jun 18, 2020

TypeScript Version: 3.9.2, Nightly

Search Terms:
true|false boolean controlled flow
boolean type narrow

Code

function absurd(_: never) { throw new Error("Must not be called"); }

interface Foo {
    bar: false;
}

function fooled(foo: Foo) {
    if (foo.bar) {
        // foo expected to be narrowed to 'never' type
        absurd(foo);
    } else {
        const bar: false = foo.bar; 
    }
}

Expected behavior:
foo type in the 'true' branch narrowed to never

Actual behavior:
foo type is Foo, which is nonsense

Playground Link: https://www.typescriptlang.org/play/?ts=4.0.0-dev.20200615#code/GYVwdgxgLglg9mABAQwEYGcQCcAmAKAfQC5EwBTANzKwEpEBvRKACyzgHdSzOBRLNrHgBEAWRDoopOJNRlEEZABtFZHEJoBuRAF8AULphgo1YMghyAYnDgNdie4lTIsJU4vRkNuvbtCRYCIjA1ir4wXAkVnB09HYOMMCIeOEAdE60tg5ZiAD0OUHWiGQAHgAOZNCqTDaypM5s7FVQNgDk5FRYLUwAnuVx2SgY2GHWmv06Re5ysQP2EAgSjs6uSh6IALwFcGnOWuN6ekA

Related Issues:
No

@ShuiRuTian
Copy link
Contributor

Not pretty sure, but I think this is similar to #39110 and #39114

@fatcerberus
Copy link

Foo is not a union, it's just a single object type. Therefore you don't get discriminated union behavior, and TS won't narrow arbitrary objects based on their properties. It works the way you expect if you use a proper discriminated union:

function absurd(_: never) { throw new Error("Must not be called"); }

interface Foo {
    bar: false;
}

interface Bar {
    bar: true;
}

function fooled(foo: Foo | Bar) {
    if (foo.bar) {
    } else if (!foo.bar) {
    } else {
        absurd(foo);
    }
}

@fatcerberus
Copy link

See also #29827

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Jun 18, 2020
@SQReder
Copy link
Author

SQReder commented Jun 19, 2020

The problem described in detail in #38963. I wanted to avoid complete union discriminator, however, there are not possible for now.
Thanks, guys 😉

@SQReder SQReder closed this as completed Jun 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants