You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Nullish coalescing and conditional type narrowingΒ #48536
Conditional type narrowing through the || operator + the use of the nullish coalescing operator should understand each other to reify the type correctly.
π Motivating Example
declare function foo(): string | undefined
const a = foo()
const b = foo()
if (a != undefined || b != undefined) {
const c = a ?? b
}
c should have type string but instead it has type string | undefined because TS hasn't reasoned that the only way into the block is if a ?? b must be non-null.
π» Use Cases
Came up in my code where I had two strings and each could be string | undefined and I wanted to nullish coalesce but only if one of them was not undefined. Had to use ! as a workaround
Type narrowing is done only at the level of individual variables, not entire expressions. As such, combining type guards via disjunction || generally won't narrow anything; TS has no way to track "at least one of a or b is non-null but I don't know which". See for example #31603.
Ed Langley (@fiddlerwoaroof) No, that's not the same thing. a ?? '' === '' doesn't even count as a type guard. TS only recognizes a handful of common patterns as type guards, more complex checks like that won't produce any narrowing at all. This issue is about expressions which do count as type guards, e.g. x != undefined or typeof x === 'string', that when these are combined with || it creates uncertainty about which case applies that prevents the compiler from doing any narrowing.
Ran into this today as well, in a way that Typescript certainly seems like it should handle.
declare function foo(): string | undefined
const a = foo()
const b = foo()
if (a ?? b) {
const c = a ?? b
// or the actual place I've been seeing it
console.log(`${a ?? b}`) // eslint warning for non-string in template literal
Bummer this can't be handled yet but figured I'd add +1 / another use case here.
The bulk "Close" action I applied to Design Limitation issues doesn't let you pick what kind of "Close" you're doing, so don't read too much into any issue's particular bit on that. I wish GitHub didn't make this distinction without a way to specify it in many UI actions!
The correct state for Design Limitation issues is closed since we don't have any plausible way of fixing them, and "Open" issues are for representing "work left to be done".
Activity
fatcerberus commentedon Apr 3, 2022
Type narrowing is done only at the level of individual variables, not entire expressions. As such, combining type guards via disjunction
||generally won't narrow anything; TS has no way to track "at least one ofaorbis non-null but I don't know which". See for example #31603.RyanCavanaugh commentedon Apr 4, 2022
What Bruce Pascoe (@fatcerberus) said β¬οΈ
fiddlerwoaroof commentedon Apr 8, 2022
Bruce Pascoe (@fatcerberus) does that also apply to something like:
fatcerberus commentedon Apr 8, 2022
Ed Langley (@fiddlerwoaroof) No, that's not the same thing.
a ?? '' === ''doesn't even count as a type guard. TS only recognizes a handful of common patterns as type guards, more complex checks like that won't produce any narrowing at all. This issue is about expressions which do count as type guards, e.g.x != undefinedortypeof x === 'string', that when these are combined with||it creates uncertainty about which case applies that prevents the compiler from doing any narrowing.cheruvian commentedon Aug 16, 2023
Ran into this today as well, in a way that Typescript certainly seems like it should handle.
Bummer this can't be handled yet but figured I'd add +1 / another use case here.
cheruvian commentedon Mar 3, 2024
Was this closed as completed because it has been implemented?
RyanCavanaugh commentedon Mar 4, 2024
The bulk "Close" action I applied to Design Limitation issues doesn't let you pick what kind of "Close" you're doing, so don't read too much into any issue's particular bit on that. I wish GitHub didn't make this distinction without a way to specify it in many UI actions!
The correct state for Design Limitation issues is closed since we don't have any plausible way of fixing them, and "Open" issues are for representing "work left to be done".
cheruvian commentedon Mar 4, 2024
sadge. Thanks