-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Boolean Comparisons Not Working As Expected #56862
Comments
This is intentional. TypeScript is telling that it knows the value is
This is, in effect, what the compiler is telling you. The condition can never be true because the literal type
declare let x: boolean;
console.log(x);
// ^? let x: boolean
x = true;
console.log(x);
// ^? let x: true |
These are supposed to be the words you used in your search, like "boolean comparison" and "narrowing", which also serves to help future searchers find your issue.
This is supposed to be a link to the TS Playground with your example code inside This looks like #31734 to me, mostly. Each of these features is behaving as intended:
None of these is a bug, but unfortunately they act in concert to give you this undesirable behavior. |
tl;dr: it's an "unreachable code" error with extra steps
I'd argue this isn't really undesirable, except if #9998 comes into play of course. |
Thank you for the replies. This example has no chance for compile-time realization of non-reachable code. And, like my previous example (showing the possible variants (RH true, RH false, and LH type-asserted)) was indicating, the compiler error does NOT occur, if I modify the comparison to either:
Of which, the former should not be an opinion of the compiler for a strongly typed language, unless a boolean is not really a boolean (But, that seems more an existential crisis of booleans that if not 'false', and not 'true', then what?). export class testClass
{
checkforproblems(entries:IEntry[]):boolean
{
let problemoccurred:boolean = false;
entries.forEach(n=>
{
if(!n)
{
problemoccurred = true;
}
if(n.checkforproblem() === true)
{
problemoccurred = true;
}
});
// Compiler error, again, here:
// This comparison appears to be unintentional because the types 'false' and 'true' have no overlap.ts(2367
if(problemoccurred === true)
{
return true;
}
return false;
}
}
export interface IEntry
{
prop1:number;
prop2:string;
checkforproblem:()=>boolean;
} |
@jcalz Apologies. I did not include a 'playground' example of the code, as the compiler will not execute it. |
@fatcerberus Yes. You're right about the unreachable code. I created a revised test class, above, that still creates the same compiler error scenario, without the unreachable code (caused by my exploration of scenarios). |
You seem to be misunderstanding. Maybe if you review other issues in this repository, you’ll see playground links and how they are used to demonstrate compile-time problems. |
@LeeWhite187 Thanks, this is why real-world examples are helpful (I understand you wanted to reduce the repro, but you cut out too much). The incorrect narrowing in the case of
Fun fact: You can execute Playground code even in the presence of compiler errors, as long as it’s still legal JS. This is what the |
@fatcerberus Sorry for my misunderstanding of the terminology in Typescript... |
@LeeWhite187 Yes, TypeScript has literal types, so besides the primitive types like |
@fatcerberus I looked at the two issues you cited.... Reading across issues, I found this one 9757, stating that "reachability and control flow analysis is done before typechecking". So, this may be a compiler limitation, since the reference eludes to exhaustive flow-traversed typing, requiring "a massive architectural change". |
9998 is in fact the relevant issue; the issue is specifically about type narrowing not always being accurate in the presence of callbacks/closures (due to design limitations that aren’t easily solved), which is what’s happening with your The order that CFA and typechecking is done is not relevant here. |
@fatcerberus That makes it a curious problem, then.... From what I read so far, this error might be a side-effect of some greater design choice that's attempting to solve 'more painful' compilation problems. And, the apparent 'state myopia', here, is a satisfactory penalty. It is interesting to come across a compiler that attempts to give errors for the utility of my logic... in addition to actual problems in it. I've employed a wrapper and workaround for the immediate problem I was having. Have a good week. |
That's also discussed in #9998, but basically, in JS it's possible for pretty much anything to have arbitrary side effects (including a simple property access!), those effects are not always statically analyzable even theoretically, and being completely pessimistic about it would severely neuter CFA-based type narrowing (which is very useful most of the time).
I would argue it is trying to warn you about an actual problem - namely that you wrote a guard against a value that can't occur (or so the compiler thinks). The error is less about "please remove this dead code" and more "this is probably a mistake, you might want to double-check it". In most compilers such message would be a warning, not an error--but TS doesn't have warnings.
I'm going to assume you mean the "comparison appears unintentional" error specifically because I don't imagine you would want to disable all type-related errors. 😉 Unfortunately, the answer to that is "no", but you can put a Footnotes
|
This issue has been marked as "Duplicate" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
🔎 Search Terms
Searched google, Reddit, stackoverflow, and the issues, here.
As well, went through this with ChatGPT, and asked for a proxy search.
No helpful results.
🕗 Version & Regression Information
I'm using Typescript v5.2.2 (under Angular 17 and React 18.1).
Have not explicitly tried older versions.
⏯ Playground Link
No response
💻 Code
🙁 Actual behavior
The compiler is giving errors, for the two commented statements in the sample code, above:
"This comparison appears to be unintentional because the types 'true' and 'false' have no overlap.ts(2367)"
This same behavior occurs when using '===' and '=='.
It as well, gives the same behavior, if I replace the right-hand boolean literal (in the comparison) with strongly-typed variable of the same value.
🙂 Expected behavior
Since the following are true in the above sample methods:
I expect the compiler to have no ambiguity of type, nor control flow concerns, at the comparison statements of testmethod1a and testmethod4a, and to compile them (or transpile, in this case), into runnable code.
And taking the given error message literally, I would expect the compiler, to regard "the types 'true' and 'false' have no overlap" as them being NOT equal, and allow the evaluation to derive a boolean false result for the containing 'if' statement.
Only when I cast the variable with a type-assertion, does the compiler error go away.
But, this should not be necessary, since the variable is type-asserted in the immediately prior statement (at declaration) AND is assigned a boolean literal value.
So, the necessity to wrap a type-declared boolean variable inside a type assertion, for the compiler to regard a comparison of boleans as valid (and finish a build), creates a definite risk for bugs, if this edge case is not remembered wherever booleans are compared.
Additional information about the issue
No response
The text was updated successfully, but these errors were encountered: