-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Fix instanceof narrowing #10194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix instanceof narrowing #10194
Conversation
Does this mean that the comments in this example are accurate? class Animal { /* ... */ }
class Dog extends Animal { /* ... */ }
class Cat extends Animal { /* ... */ }
declare var x: Animal;
if (x instanceof Dog) {
// 'x' has type 'Dog'
}
else {
// 'x' has type 'never'
} |
@DanielRosenwasser Actually, no. I missed the part in italics in the wording:
|
Right, it didn't look like that's what was happening in the implementation, so I just wanted to clarify. |
// Otherwise, if the current type is assignable to the candidate, keep the current type. | ||
// Otherwise, the types are completely unrelated, so narrow to the empty type. | ||
// If the candidate type is a subtype of the target type, narrow to the candidate type. | ||
// Otherwise, narrow to whichever of the target type or the candidate type that is assignable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there's a little more precision than the wording lends to here. If the candidate isn't a subtype, but is assignable, we keep the original type in place. (e.g. with Array.isArray
, you preserve the original type instead of giving back Array<any>
).
👍 |
This PR fixes three issues related to narrowing of types with the instanceof operator and user defined type guards:
x instanceof T
where x is of a non-union type, we now narrow the type ofx
tonever
in the false branch if the type of x is not a subtype of T. Previously we didn't change the type ofx
in the false branch.x instanceof T
where the types of x and T are both assignable to each other, we now pick T only if it is a subtype of the type of x. Previously we would always pick T.These fixes also affect similar scenarios with user defined type predicates (since the narrowing logic is shared).
Fixes #10145, #10167.