Last active
March 31, 2026 21:53
-
-
Save ryangoree/d007ac8e77774fec309eac099f56e875 to your computer and use it in GitHub Desktop.
Notes on when TypeScript conditional types become distributive
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // A conditional type only distributes over unions that are: | |
| // - On the left side of `extends` (the checked type). | |
| // - Generic type variables (introduced via `infer` or generic type parameters). | |
| // - Naked (not wrapped in another type). | |
| // | |
| // See: | |
| // - https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types | |
| // - https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#inferring-within-conditional-types | |
| type U = 1 | "a"; | |
| // Not distributed - `U` is a concrete type alias, not a generic type variable, | |
| // so the entire union `U` is evaluated as a single unit. | |
| type T1 = U extends number ? { Number: U } : { NaN: U }; // => | |
| // Distributed - `infer T` introduces a generic type variable which is inferred | |
| // as each member of the union `U` in the inner conditional, so each value is | |
| // checked individually, resulting in a new union type. | |
| type T2 = U extends infer T // => | |
| ? T extends number | |
| ? { Number: T } | |
| : { NaN: T } | |
| : never; | |
| // Distributed - The type parameter `T` is evaluated for each member of the | |
| // union `U`, resulting in a new union type. | |
| type Generic<T> = T extends number ? { Number: T } : { NaN: T }; | |
| type T3 = Generic<U>; // => | |
| // Not distributed - The checked type is wrapped in a tuple, so it's not a naked | |
| // type parameter. | |
| type Generic2<T> = [T] extends [number] ? { Number: T } : { NaN: T }; | |
| type T4 = Generic2<U>; // => |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment