-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Type guard affects type of variable in surprising wayΒ #50916
Copy link
Copy link
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
π Search Terms
type guard / fall through / narrow / change / lazy / evaluate
π Version & Regression Information
- This changed between versions v4.7.4 and v4.8.2
β― Playground Link
Playground link with relevant code
π» Code
type Identity<T> = {[K in keyof T]: T[K]};
type Self<T> = T extends unknown ? Identity<T> : never;
function is<T>(value: T): value is Self<T> {
return true;
}
type Union = {a: number} | {b: number} | {c: number};
function example(x: Union) {
if (is(x)) {}
if (is(x)) {}
if (is(x)) {}
if (is(x)) {}
if (is(x)) {}
if (is(x)) {}
if (is(x)) {}
if (is(x)) {}
return x;
// ^?
}π Actual behavior
The type of x is "narrowed" to Identity<Identity<Identity<Identity<Identity<Identity<Identity<Identity<{a: number;}>>>>>>>> | Identity<Identity<Identity<Identity<Identity<Identity<Identity<Identity<{b: number;}>>>>>>>> | Identity<Identity<Identity<Identity<Identity<Identity<Identity<Identity<{c: number;}>>>>>>>>
It's as if a variable gets narrowed to the union of the types of both sides of the type predicate, e.g.
if (isA(aOrB)) {
// `aOrB` gets narrowed to `A`
} else {
// `aOrB` gets narrowed to `Exclude<typeof aOrB, A>`
}
// `aOrB` gets narrowed to `A | Exclude<typeof aOrB, A>` but it should just be left aloneπ Expected behavior
The type of x doesn't change.
Reactions are currently unavailable
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