Skip to content

type guard with --strictNullChecks is respected, but then not in a callback scope: TS2345 #22120

@psnider

Description

@psnider

TypeScript Version:
When using --strictNullChecks with any of these versions:

  • 2.0
  • 2.7.2
  • 2.8.0-dev.20180222 (typescript@next)

Search Terms:

  • TS2345
  • type guard
  • strictNullChecks

Code

in a file tsc-bug.ts:

function asString(): string | undefined {
    return undefined
}

function g(a: string) {
    return
}

function f() {
    let a = asString()   // intellisense correctly shows a is of type string | undefined
    if (a) {    // more explicit guard also fails: if (typeof a === "string")
        let ar = [1,2,3]
        g(a)   // after the type guard "if (a)", intellisense correctly shows a is of type string
        ar.forEach((x) => {
            // tsc 2.7.2 outputs: error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
            // also tsc 2.0 and 2.8.0-dev.20180222
            g(a)   // ERROR: intellisense incorrectly shows a is of type string | undefined
        })
    }
}

Expected behavior:
When using the compiler option: --strictNullChecks

Expect second call of g(a) to be treated the same as the first call.
Both are in the same scope.

Actual behavior:
Second call to g(a) somehow loses track of the type restriction imposed by the guard.
The compiler issues this error:

tsc-bug.ts(18,15): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'.

Playground Link:
NOTE: this link doesn't include the --strictNullChecks option, so be sure to set if from the Options button:
http://www.typescriptlang.org/play/#src=function%20asString()%3A%20string%20%7C%20undefined%20%7B%0D%0A%20%20%20%20return%20undefined%0D%0A%7D%0D%0A%0D%0Afunction%20g(a%3A%20string)%20%7B%0D%0A%20%20%20%20return%0D%0A%7D%0D%0A%0D%0Afunction%20f()%20%7B%0D%0A%20%20%20%20let%20a%20%3D%20asString()%20%20%20%2F%2F%20intellisense%20correctly%20shows%20a%20is%20of%20type%20string%20%7C%20undefined%0D%0A%20%20%20%20if%20(a)%20%7B%20%20%20%20%2F%2F%20more%20explicit%20guard%20also%20fails%3A%20if%20(typeof%20a%20%3D%3D%3D%20%22string%22)%0D%0A%20%20%20%20%20%20%20%20let%20ar%20%3D%20%5B1%2C2%2C3%5D%0D%0A%20%20%20%20%20%20%20%20g(a)%20%20%20%2F%2F%20after%20the%20type%20guard%20%22if%20(a)%22%2C%20intellisense%20correctly%20shows%20a%20is%20of%20type%20string%0D%0A%20%20%20%20%20%20%20%20ar.forEach((x)%20%3D%3E%20%7B%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20tsc%202.7.2%20outputs%3A%20error%20TS2345%3A%20Argument%20of%20type%20'string%20%7C%20undefined'%20is%20not%20assignable%20to%20parameter%20of%20type%20'string'.%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20also%20tsc%202.0%20and%202.8.0-dev.20180222%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20g(a)%20%20%20%2F%2F%20ERROR%3A%20intellisense%20incorrectly%20shows%20a%20is%20of%20type%20string%20%7C%20undefined%0D%0A%20%20%20%20%20%20%20%20%7D)%0D%0A%20%20%20%20%7D%0D%0A%7D%0D%0A

Related Issues:

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions