Skip to content

Narrowing strangeness with instanceof #10167

Closed
@yortus

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: @ahejlsberg, @sandersn

Metadata

Metadata

Assignees

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