TypeScript: Boolean Comparisons Not Working As Expected
🔎 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
export class testClass1
{
testmethod1a()
{
let x:boolean = true;
// Gives compiler error:
// This comparison appears to be unintentional because the types 'false' and 'true' have no overlap.
if(x === false)
return;
}
testmethod1b()
{
let x:boolean = true;
if((x as boolean) === false)
return;
}
testmethod2()
{
let x:boolean = true;
if(x === true)
return;
}
}
export class TestClass2
{
testmethod3()
{
let x:boolean = false;
if(x === false)
return;
}
testmethod4a()
{
let x:boolean = false;
// Gives compiler error:
// This comparison appears to be unintentional because the types 'false' and 'true' have no overlap.
if(x === true)
return;
}
testmethod4b()
{
let x:boolean = false;
if((x as boolean) === true)
return;
}
}
🙁 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:
- Typescript is strongly-typed
- Each variable is type-asserted at declaration
- Each variable is assigned a boolean literal at declaration
- Each comparison is to a boolean literal
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
About this issue
- Original URL
- State: closed
- Created 6 months ago
- Comments: 15 (2 by maintainers)
This is intentional. TypeScript is telling that it knows the value is
true(orfalse) at that point and the always-falseifconditional is thus likely indicative of an error in the code.This is, in effect, what the compiler is telling you. The condition can never be true because the literal type
truehas no overlap with the literal typefalse(i.e. they have no values in common); but the fact that you wrote a conditional statement indicates that you think it can be true.let x: boolean = trueis not a type assertion. It’s a type annotation. The variable still gets narrowed on assignment, the same as if you wroteThese 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:
booleantype is actually a unionNone of these is a bug, but unfortunately they act in concert to give you this undesirable behavior.
@jcalz Apologies. I did not include a ‘playground’ example of the code, as the compiler will not execute it. So, there’s not really a way to achieve a runnable example. This issue is for a compile-time problem.