Skip to content

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

Closed

Description

@Arnavion

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).

Activity

  1. mhegazy commented on Sep 21, 2016

    @mhegazy
    Contributor

    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

  2. locked and limited conversation to collaborators on Jun 19, 2018
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

    BugA bug in TypeScriptDuplicateAn 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