Created
June 4, 2024 18:14
-
-
Save ryangoree/e816db56e5fc12aab14e64cea415436c to your computer and use it in GitHub Desktop.
Convert members of a union to an intersection.
This file contains 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
/** | |
* 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