-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Closed
Labels
BugA bug in TypeScriptA bug in TypeScriptFix AvailableA PR has been opened for this issueA PR has been opened for this issue
Milestone
Description
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 TypeScriptA bug in TypeScriptFix AvailableA PR has been opened for this issueA PR has been opened for this issue