Skip to content

Instantly share code, notes, and snippets.

@ryangoree
Last active March 31, 2026 21:53
Show Gist options
  • Select an option

  • Save ryangoree/d007ac8e77774fec309eac099f56e875 to your computer and use it in GitHub Desktop.

Select an option

Save ryangoree/d007ac8e77774fec309eac099f56e875 to your computer and use it in GitHub Desktop.
Notes on when TypeScript conditional types become distributive
// 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