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

Destructuring assignment doesn't narrow undefined, inconsistent with regular property access #10846

Closed
Arnavion opened this issue Sep 10, 2016 · 1 comment
Labels
Bug A bug in TypeScript Duplicate An existing issue was already created

Comments

@Arnavion
Copy link
Contributor

Arnavion commented Sep 10, 2016

TypeScript Version: 2.1.0-dev.20160910

Code

declare const foo: { bar: string | undefined };

if (foo.bar !== undefined) {
    foo.bar.length; // Property access (1)
}

if (foo.bar !== undefined) {
    const bar = foo.bar; // Property access
    bar.length; // (2)
}

if (foo.bar !== undefined) {
    const { bar } = foo; // Destructuring assignment
    bar.length; // (3)
}

tsc -t es5 -m amd --strictNullChecks ./foo.ts

Expected behavior:

All three compile, or all three complain that .length is being invoked on string | undefined

Actual behavior:

Only (3) complains that error TS2532: Object is possibly 'undefined'. In (1) foo.bar is inferred as string, and thus in (2) bar is also inferred as string. But in (3) bar is string | undefined


I'm actually surprised that a check on foo.bar narrows it down within the if blocks at all, since I remember this only used to narrow bindings. I guess this changed at some point to support narrowing properties, but then it should also narrow (3) identically to (2).

@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Sep 12, 2016
@mhegazy
Copy link
Contributor

mhegazy commented Sep 21, 2016

This is essentially the same as #10065. control flow analysis only narrows the type of the right most symbol. in this case foo.bar; it does not narrow the type of foo to {bar: string}. the first two cases you check on foo.bar and you use foo.bar so no issues, in the third you are looking at the type of foo. since it was not narrowed, you get the original type, and thus bar is still string | undefined.

closing as a duplicate of #10065

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug A bug in TypeScript Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants