Skip to content

Narrowing strangeness with instanceof #10167

Description

@yortus

TypeScript Version: nightly (2.1.0-dev.20160804)

Code

function f(s: Set<string> | Set<number>) {

    // (1)
    s = new Set<number>();
    s // s is Set<number>
    if (s instanceof Set) { } // Clearly no side-effects here. No possible changes to s.
    s // s is Set<number> | Set<any>                                                 <===== (1a)
    s.add(42); // ERROR: Cannot invoke an expression whose type lacks call signature <===== (1b)

    // (2)
    s = new Set<number>();
    s // s is Set<number>
    if (s instanceof Promise) { } // Clearly no side-effects here. No possible changes to s.
    s // s is Set<number> | (Set<number> & Promise<any>)                             <===== (2a)
    s.add(42); // No error this time                                                 <===== (2b)
}

function g(s: Set<string> | Set<number>) {

    // (3)
    s // s is Set<string> | Set<number>
    if (s instanceof Set) {
        s // s is Set<string> | Set<number>
    }
    else {
        s // s is never                                                              <===== (3a)
        s.add(42); // ERROR 'add' does not exist on never                            <===== (3b)
    }

    // (4)
    s = new Set<number>();
    s // s is Set<number>
    if (s instanceof Set) {
        s // s is Set<any>
    }
    else {
        s // s is Set<number>                                                        <===== (4a)
        s.add(42); // no error, but we couldn't possibly have a Set instance here    <===== (4b)
    }
}

Expected behavior:

  • inferred type of s at (1a) is Set<number>
  • inferred type of s at (2a) is Set<number>
  • inferred type of s at (3a) is never
  • inferred type of s at (4a) is never
  • Compiler errors at (3b) and (4b)
  • No compiler errors at (1b) and (2b)

Actual behavior:

  • inferred type of s at (1a) is Set<number> | Set<any>
  • inferred type of s at (2a) is Set<number> | (Set<number> & Promise<any>)
  • inferred type of s at (3a) is never
  • inferred type of s at (4a) is Set<number>
  • Compiler errors at (1b) and (3b)
  • No compiler errors at (2b) and (4b)

Notes:

Brought over from #9862 which is closed. See that issue for the discussion leading to the above examples. Cc: Anders Hejlsberg (@ahejlsberg), Nathan Shively-Sanders (@sandersn)

Metadata

Metadata

Labels

BugA bug in TypeScriptFixedA PR has been merged for this issue

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions