Skip to content

Instantly share code, notes, and snippets.

@ryangoree
Created June 4, 2024 18:14
Show Gist options
  • Save ryangoree/e816db56e5fc12aab14e64cea415436c to your computer and use it in GitHub Desktop.
Save ryangoree/e816db56e5fc12aab14e64cea415436c to your computer and use it in GitHub Desktop.
Convert members of a union to an intersection.
/**
* Convert members of a union to an intersection.
*
* @example
* ```ts
* type Union = { a: number } | { b: string };
* type Intersection = UnionToIntersection<Union>;
* // { a: number } & { b: string }
* ```
*
* @privateRemarks
* This works by taking advantage of [distributive conditional
* types](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types),
* which allows conditional types to be applied to each member of a union type
* individually, and [contravarience in function argument
* types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html#strict-function-types).
*
* The conditional type `T extends any ? (x: T) => any : never` is used to
* create a function type for each member of the union that takes the member as
* an argument.
*
* Then, the union of function types is checked to see if it can be assigned to
* a single function type with an inferred argument type. TypeScript infers the
* argument type as the intersection of the union members since it's the only
* argument type that satisfies all members of the function type union.
*/
type UnionToIntersection<T> = (
T extends any ? (member: T) => any : never
) extends (member: infer R) => any
? R
: never;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment