Consider the following:
type Properties = {
foo: { n: number };
bar: { s: string };
baz: { b: boolean };
};
declare function retrieveValues
Using conditional types and type inference in conditional types it is possible to transform { n: number } | { s: string }
directly into { n: number } & { s: string }
.
type GetKeys = U extends Record ? K : never
type UnionToIntersection = {
[K in GetKeys]: U extends Record ? T : never
}
type Transformed = UnionToIntersection<{ a: string } | { b: number }>
// Transformed has type {a: string, b: number}
Playground Link
The reason this works is basically because conditional types are distributed over union types. From the conditional types pull request:
Conditional types in which the checked type is a naked type parameter are called distributive conditional types. Distributive conditional types are automatically distributed over union types during instantiation. For example, an instantiation of
T extends U ? X : Y
with the type argumentA | B | C
forT
is resolved as(A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y)
.