Skip to content

[5.3] Type narrowing regression with property comparison to boolean falseΒ #56482

Closed
@meyfa

Description

@meyfa

πŸ”Ž Search Terms

narrowing, strict equals, property access, boolean false, undefined

πŸ•— Version & Regression Information

  • This changed between versions 5.2 and 5.3
  • This also happens in the nightly

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.3.1-rc#code/JYOwLgpgTgZghgYwgAgGIHt3IN4ChnIBGcUAXEZgDYRwi4C+uuC6IAzmMgOYRgZYBeZAAoAlOX7IAPsgCuIACYQYoCAuQCAfDnzIovWVBDIAsnDAALAHRRaC9AFsxybQAYrAVmQB+HERLk8JRsKPTI5PJKKiBqDEws7JwwmBrcvPxiuMAwIsno3lbEUBoCQkEhojoECWzo1FaU6FzCeaJxuAD0HcgAAmBsALQQAB4ADhAIYENQUOjFA8h5yMBsyKPobGzAhJQAnnKKyqoKzKy19Y3NeYUkbUA

πŸ’» Code

interface Foo {
  bar: boolean
}

const getFoo = (): Foo | undefined => {
  return Math.random() > 0.5 ? { bar: false } : undefined
}

const foo = getFoo()
if (foo?.bar === false) {
  console.log(foo)
}

// @ts-expect-error - foo is possibly undefined
console.log(foo.bar)

πŸ™ Actual behavior

In line 13 and following, foo is incorrectly narrowed to just Foo (whereas it was previously Foo | undefined), although we learned nothing about it from the preceding if as that did not influence control flow.

Unused '@ts-expect-error' directive.(2578)

πŸ™‚ Expected behavior

TS should report an error when accessing foo.bar as foo can potentially be undefined.

Additional information about the issue

I originally discovered this issue in JSX with a snippet similar to:

function Component () {
  const foo = getFoo()
  return (
    <div>
      {foo?.bar === false && 'foo'}
      {foo.bar ? 'true' : 'false'}
    </div>
  )
}

There as well, the access foo.bar is allowed due to the preceding check, although they are completely separate.

Note that changing it to === true or removing the checks entirely fixes the problem.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptFix AvailableA PR has been opened for this issueRecent RegressionThis is a new regression just found in the last major/minor version of TypeScript.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions