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
I have a type DistributeOverTupleElementTypes that is intended to operate on a tuple type and to distribute over the component union elements. Example:
DistributeOverTupleElementTypes<[number | boolean, string | 5]> is expected to evaluate to [number, string] | [number, 5] | [boolean, string] | [boolean, 5] and it works as expected (see t1 below). However, when replacing type "5" with type "[5]", the expected evaluation result misses the components [boolean, string] and [boolean, [5]] (see t2, t3, t4 and t5). Why? Is the behavioral difference intended?
"use strict";constt1=true;constt2=true;//!! errorconstt3=true;// !!errorconstt4=true;// !!errorconstt5=true;// Thus, the evaluation result of DistributeOverTupleElementTypes<[number | boolean, string | [5]]> misses the union components [boolean, string] and [boolean, [5]]. Why?constt6=true;// !!error
Assignments to variables t2, t3 and t4 are flagged as faulty (Type 'true' is not assignable to type 'false'.(2322)).
🙂 Expected behavior
Assignments to variables t2, t3 and t4 are OK because the respectively declared types should evaluate to "true".
Additional information about the issue
No response
The text was updated successfully, but these errors were encountered:
MMF2
changed the title
Unexpected differences in distribution over union types: type string | 5 is treated differently than type string | [5]
Unexpected differences in distribution over union types: type string | 5 behaves differently than type string | [5]
May 22, 2025
Is this really the simplest code that demonstrates your issue?
You might not be aware that boolean is not a primitive TS type, but an alias of the union true | false. So you are comparing things like [boolean, X] to [true, X] | [false, X]. Indeed you can use IntelliSense to inspect what DistributeOverTupleElementTypes produces directly (as opposed to doing individual extends tests):
typeZ=DistributeOverTupleElementTypes<[boolean,string]>;// type Z = [false, string] | [true, string]
So what's interesting is that [boolean, X] | [boolean, Y] is apparently seen as assignable to [false, X] | [true, X] | [false, Y] | [true, Y]depending on what X and Y are. I'm guessing this is some edge case around the behavior of #30779. Something like: If you always deal with literal types (like 5 or true or "abc" or null) then TS is happy to try to expand out the unions to match because of #30779... but if you are also involving non-literal types (like number or string or object or any[] or [any]) then it doesn't. This doesn't look like a bug to me, but if it is one, there will be a simpler repro than DistributeOverTupleElementTypes.
Yes, you are right. Indeed, I have forgotten that boolean is not a primitive TS type but an abbreviation for true | false. Taking this into consideration I revise the assignment of variable t2 to
const t2: [number, string] | [number, [5]] | [true, string] | [false, string] | [true, [5]] | [false, [5]] extends DistributeOverTupleElementTypes<[number | boolean, string | [5]]> ? true : false = true
and this time it works as expected, i.e., no error.
My fault, sorry!
Still, I don't understand why the type string | 5 behaves differently than string | [5] but that's probably not a bug. Thanks for clarification.
🔎 Search Terms
"distribution union"
I have a type DistributeOverTupleElementTypes that is intended to operate on a tuple type and to distribute over the component union elements. Example:
DistributeOverTupleElementTypes<[number | boolean, string | 5]> is expected to evaluate to [number, string] | [number, 5] | [boolean, string] | [boolean, 5] and it works as expected (see t1 below). However, when replacing type "5" with type "[5]", the expected evaluation result misses the components [boolean, string] and [boolean, [5]] (see t2, t3, t4 and t5). Why? Is the behavioral difference intended?
Output
Compiler Options
Playground Link: Provided
🕗 Version & Regression Information
⏯ Playground Link
https://www.typescriptlang.org/play/?#code/C4TwDgpgBAIglgZ2AJzgIwK7AgeQG4TIAqGYANhAKIUC2EAdsEeBAgDxEB8UAvAFBRBUIlAgAPbPQAmCKAG049AGaEoAZUUBzCgGEA9jTB76DYAF0BQoQH4oACg31tEfYeOnREhjKgZ6Aa3o9AHd6KAB6cNFlPWQAY2gpRBR0LDhjSysrWzlHZ1cjE0YLLKyALigTAmQASkyrCrsRcUkfBWVVADE4ZCQAGigAOmHFFWQoACVWc3rS2ztu3uBPVtk-QJCwyOilWISoJKRUTGB0+lnSwXn4I9TsfEIScipaU2ZIdimkbhbvWVHVJQ8ABDMgYYHYKRfYAAVQulxs9iBoPBkOhMJWfygAPG3TEECkyLBEIJ0KeFAiUQYu3iiWSxzSGQRzKu9jxBKJqNJ03J0F+0jWASCoTkJRZ4pyi36Q2G7MJIOJaJ5pAoYvFzIqVUIdXVl01EGqOt1gn1hvhpVN2vNJsqBu1AG4+HFjEgoMAAIwVOT0DA0NCEAa3JxmKAAH3kPr9AagAFYQ+G5Gg9HoKMD6IGUsGw-IkymIGmBnHMQLBDcUidcNVedQIHRGO9WGxvb7-eNw7nU+moEHNNm49xbCgMNAKkpQQhoDw3chh47nfRXcAAExeyOtjOoLMJtfRuRx+M55OdjdaA+Jo-5rt7swh-k+WD0u6Vx4ql61t4sdjNqNtqAdy8nk42bXmYA7TsOUCjuOk7gRA9qCJEACEiGiMgyCxE6LrLMAADMq4ttGPZnjuyADCBwH-gW3aZpoZ6UVe+7FveZYMvcVavjWdZMJ+TYkdm9GAb2Cb7twCYCdRm60VAg4ziOUBjmQE68LB8HbMhhDocgmELthAAs+E-oJxEEaR8iMWJF5UURFGWQxN5MbID63BWDzEBxrz1jx36tvxtmCcBIk2XmVHkTJEFQYpMFDnBlJQOpaEYfOi4xgZ64SaewEkWR5mHsFXbWRZeXZfZd6OSxT6udWHncR8vEmb5RXpUBwk3qJuXHk1UmFR1oWwZB8nQcp0WOtsRAABYYAgAzAGNfIKqiZxQMgrAYGQyx6EoTnllgz5uc8nEfrV3mqO2fmdQFrVQDQiATrIM3QH4i3Om4RTALI56NdZaZSO1AFmTegxQAA6mNIDWHw2mLgAbKlhE0RddFnT2CMOaWj4uex+3VQ2X58adn3w+G-bSX1EVKVOw2xfFml8EAA
💻 Code
🙁 Actual behavior
Assignments to variables t2, t3 and t4 are flagged as faulty (Type 'true' is not assignable to type 'false'.(2322)).
🙂 Expected behavior
Assignments to variables t2, t3 and t4 are OK because the respectively declared types should evaluate to "true".
Additional information about the issue
No response
The text was updated successfully, but these errors were encountered: