-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
TypeGuarding not applied with explicit instanceof comparison to true/false #32819
Comments
Narrowing forms have to be identified syntactically, so we pay a perf penalty for every possible form that's checked for. Since there's no real reason to write it this way, we don't consider |
I feel like the code example in my original ticket was completely reasonable and the current behavior very counter-intuitive. I understand that changing the behavior is undesireable if it implies a performance penalty, but it would really help me out if someone could point out my mistake or what I should be doing differently to work around the issue. Thanks in advance |
@oliversalzburg You can write: if( !(target instanceof HTMLElement) ) {
return;
} |
@ahejlsberg said the similar thing when he implemented this type guard. |
What about cases like this one? function foo(target: Number | String) {
const targetIsString = target instanceof String;
if (targetIsString) {
target.toLowerCase();
}
} We are currently writing TS definitions for parts of our code base and it's not uncommon that a parameter to a JS function can be of several types, especially if some arguments are optional. This causes us to write code that checks the type of the argument and branches accordingly. This often leads to TS reporting errors as discussed in this issue, even though the code is perfectly valid. This is confusing developers and forces them to write code to adapt to limitations of TS, which is unfortunate. Regardless, thanks for the explanations. The cleanest solution appears to be to write multiple functions that are stricter in their expected argument types. |
@oliversalzburg That's a different thing - TS doesn't track dependencies between variables like that, it can only narrow variables directly included in the conditional expression. There are many, many tickets about that exact pattern; but it's actually a very big can of worms to make it work in general ("What does the (narrowed) type of this variable imply for all the other ones in scope?"), so it's largely considered a design limitation that that doesn't work. |
I think have a good reason for writing Related: #32956 |
For future reference, here's a better example: declare const isNonNullable: <T>(t: T) => t is NonNullable<T>;
declare const t: string | undefined;
if (!isNonNullable(t)) {
} else {
t.toUpperCase(); // ✅ no error, good
}
if (isNonNullable(t) === false) {
} else {
t.toUpperCase(); // ❌ unexpected error
}
if (isNonNullable(t)) {
t.toUpperCase(); // ✅ no error, good
}
if (isNonNullable(t) === true) {
t.toUpperCase(); // ❌ unexpected error
} |
From microsoft/vscode#77921
TypeScript Version: 3.6.0-dev.20190810
Search Terms:
Code
Expected behavior:
No compile error.
Type of
target
in the conditional statement should beString
Actual behavior:
Error:
Property 'toLowerCase' does not exist on type 'String | Number'. Property 'toLowerCase' does not exist on type 'Number'.
The guarding works properly if you omit the explicit
=== true
:Playground Link:
Related Issues:
The text was updated successfully, but these errors were encountered: