You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
someBool || true gets the literal type true when assigned to a let variable at initialization (unlike true getting the type boolean) #61799
Very unexpected and confusing behavior, I highly doubt it is intended. Couldn't find anything explaining the change in the release notes for TypeScript 4.2, so pretty sure it's an unwanted regression. Please correct me if I'm wrong.
changed the title [-]The expression `someBool || true` is of type `true` while the expression `true` is of type `boolean`[/-][+]`someBool || true` gets the literal type `true` when assigned to a re-assignable variable (unlike `true` getting the type `boolean`)[/+]on Jun 1, 2025
changed the title [-]`someBool || true` gets the literal type `true` when assigned to a re-assignable variable (unlike `true` getting the type `boolean`)[/-][+]`someBool || true` gets the literal type `true` when assigned to a `let` variable at initialization (unlike `true` getting the type `boolean`)[/+]on Jun 1, 2025
I'm pretty sure this has changed in #42353 . checkBinaryExpressionWorker calls getUnionTypehere on the left and right type and after the change, it eliminates the fresh true type in favor of its regular type.
I don't really know what's confusing or unexpected about a value that we know has the value true having the type true. Absent a more principled reason to change this, let's not break something else in the process.
I don't really know what's confusing or unexpected about a value that we know has the value true having the type true.
The confusing part is the fact that it's different from how an even simpler true expression results in a wider type in the end.
With let x = true it couldn't be more clear that the value will be true, yet the variable ends up having the boolean type assigned to it rather than true. That, of course, happens for a good reason. Why should someBool || true behave any different then?
By the applied reasoning, this should be string | true but it's not:
declareconststr: stringletexample3=str||true// ^? let example3: string | boolean
We could say though that the right operand is contextually-typed by the left one:
declareconstmaybeFn: ((arg: number)=>void)|null;letexample4=maybeFn||((arg)=>{});// ^? let example4: (arg: number) => void
But that principle doesn't fully apply to primitives (albeit maybe for some other reasons, widening behavior of strings/numbers was always confusing to me):
declareconstmaybeString: ""|nullletexample5=maybeString||""// ^? let example5: string
It's also worth noting boolean has some history of being special-cased so it doesn't always get typed contextually, for example in #48380
Activity
[-]The expression `someBool || true` is of type `true` while the expression `true` is of type `boolean`[/-][+]`someBool || true` gets the literal type `true` when assigned to a re-assignable variable (unlike `true` getting the type `boolean`)[/+][-]`someBool || true` gets the literal type `true` when assigned to a re-assignable variable (unlike `true` getting the type `boolean`)[/-][+]`someBool || true` gets the literal type `true` when assigned to a `let` variable at initialization (unlike `true` getting the type `boolean`)[/+]Andarist commentedon Jun 2, 2025
I'm pretty sure this has changed in #42353 .
checkBinaryExpressionWorkercallsgetUnionTypehere on the left and right type and after the change, it eliminates the freshtruetype in favor of its regular type.RyanCavanaugh commentedon Jun 3, 2025
I don't really know what's confusing or unexpected about a value that we know has the value
truehaving the typetrue. Absent a more principled reason to change this, let's not break something else in the process.snarbles2 commentedon Jun 3, 2025
I don't necessarily think it warrants a change, but I think it's fair to characterize the inconsistent behavior as confusing or unexpected.
aweebit commentedon Jun 3, 2025
The confusing part is the fact that it's different from how an even simpler
trueexpression results in a wider type in the end.With
let x = trueit couldn't be more clear that the value will betrue, yet the variable ends up having thebooleantype assigned to it rather thantrue. That, of course, happens for a good reason. Why shouldsomeBool || truebehave any different then?Andarist commentedon Jun 3, 2025
By the applied reasoning, this should be
string | truebut it's not:We could say though that the right operand is contextually-typed by the left one:
But that principle doesn't fully apply to primitives (albeit maybe for some other reasons, widening behavior of strings/numbers was always confusing to me):
It's also worth noting
booleanhas some history of being special-cased so it doesn't always get typed contextually, for example in #48380typescript-bot commentedon Jun 6, 2025
This issue has been marked as "Not a Defect" and has seen no recent activity. It has been automatically closed for house-keeping purposes.