Skip to content

Object literal types with only optional properties break control flow narrowing #48858

@DaviDevMod

Description

@DaviDevMod

Bug Report

If an object literal type with only optional properties is part of a union, the union can't be narrowed.

I expected the bug to be common enough to have been already discussed somewhere, but the most relevant issue I could find was #31156. I apologise in advance if I'm opening a dupe.

🔎 Search Terms

narrowing union

🕗 Version & Regression Information

The bug can be found in any version of the TypeScript Playground (currently from v3.3.3333 to 4.6.2, including the Nightly v4.7.0-dev.20220427).

⏯ Playground Link

Playground link with relevant code

💻 Code

// Base case. It works as expected.
type CaseOne = 'A' | { optional: false }

const f = (arg: CaseOne) => {
    // `arg` is narrowed to `A` as expected.
    if (arg === 'A') arg;
}

// Any object literal in the union has only optional properties.
type CaseTwo = 'A' | { optional?: true } | { anotherOne?: 2 }

const g = (arg: CaseTwo) => {
    // No narrowing occurs.
    if (arg === 'A') arg;
}

// The union has at least one object literal with at least one required property
// and at least one object literal with only optional properties.
type CaseThree = 'A' | { optional?: true } | { anotherOne?: 2 } | { dizzy: 'eh' }

const h = (arg: CaseThree) => {
    // Unreliable narrowing that depends on how you play with the question marks.
    if (arg === 'A') arg;
}

🙁 Actual behavior

Object literal types with only optional properties break control flow narrowing.

🙂 Expected behavior

It should be possible to narrow unions containing an object literal type with only optional properties.

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions