12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
- /**
- Convert a union type to an intersection type using [distributive conditional types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types).
- Inspired by [this Stack Overflow answer](https://stackoverflow.com/a/50375286/2172153).
- @example
- ```
- import {UnionToIntersection} from 'type-fest';
- type Union = {the(): void} | {great(arg: string): void} | {escape: boolean};
- type Intersection = UnionToIntersection<Union>;
- //=> {the(): void; great(arg: string): void; escape: boolean};
- ```
- A more applicable example which could make its way into your library code follows.
- @example
- ```
- import {UnionToIntersection} from 'type-fest';
- class CommandOne {
- commands: {
- a1: () => undefined,
- b1: () => undefined,
- }
- }
- class CommandTwo {
- commands: {
- a2: (argA: string) => undefined,
- b2: (argB: string) => undefined,
- }
- }
- const union = [new CommandOne(), new CommandTwo()].map(instance => instance.commands);
- type Union = typeof union;
- //=> {a1(): void; b1(): void} | {a2(argA: string): void; b2(argB: string): void}
- type Intersection = UnionToIntersection<Union>;
- //=> {a1(): void; b1(): void; a2(argA: string): void; b2(argB: string): void}
- ```
- */
- export type UnionToIntersection<Union> = (
- // `extends unknown` is always going to be the case and is used to convert the
- // `Union` into a [distributive conditional
- // type](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types).
- Union extends unknown
- // The union type is used as the only argument to a function since the union
- // of function arguments is an intersection.
- ? (distributedUnion: Union) => void
- // This won't happen.
- : never
- // Infer the `Intersection` type since TypeScript represents the positional
- // arguments of unions of functions as an intersection of the union.
- ) extends ((mergedIntersection: infer Intersection) => void)
- ? Intersection
- : never;
|