Concept Flow - Non-distributive conditional types
Start with type T
Check if T extends U?
Return X
Wrap with [T
Result
This flow shows how wrapping a type in a tuple [T] prevents conditional types from distributing over unions.
type NonDist<T> = [T] extends [string] ? true : false; type A = NonDist<string | number>; // A is false, not true | false
| Step | Type T | Condition [T] extends [string]? | Branch Taken | Result |
|---|---|---|---|---|
| 1 | string | number | Is [string | number] assignable to [string]? | No | false |
| Exit | string | number | Condition false, no distribution | Return false | false |
| Variable | Start | After Step 1 | Final |
|---|---|---|---|
| T | string | number | string | number | string | number |
| Condition Result | N/A | false | false |
| Result | N/A | false | false |
Non-distributive conditional types: Use [T] extends [U] to prevent distribution over unions. Without wrapping, conditional types distribute over each union member. Example: type ND<T> = [T] extends [string] ? true : false; ND<string | number> is false, not true | false. This helps control type behavior precisely.
type Test<T> = T extends string ? 'yes' : 'no'; type Result = Test<'a' | number>;
Result?T is a union 'a' | number, the condition distributes over each member.type NonDist<T> = T extends [string] ? true : false;
T extends [string], a tuple type, not wrapping T.T itself must be wrapped in a tuple: [T] extends [string]. This code does not do that, so distribution is not prevented.T is exactly string | number (no more, no less)?T in a tuple [T] prevents distribution over unions.[T] extends [string | number] and [string | number] extends [T] to ensure exact match, no extra or missing types.Pass the test and this pattern moves unknown