Issue
How can I write a generic type alias, Combine<A, B>
, that combines any two interfaces, A and B, while keeping matching properties from both but merging the property types using union?
For example, take these two interfaces:
interface Interface1 {
type: string;
another: bool;
}
interface Interface2 {
type: number;
}
Then Combine<Interface1, Interface2>
should evaluate to the type:
type Result = {
type: string | number;
another: bool;
}
Solution
first take all the keys in A that are not in B, as well as keys of B not in A, and for the intersection of keys explicitly define the union:
type Combine<A, B> =
Omit<A, keyof B> // items in A that aren't in B
& Omit<B, keyof A> // items in B that aren't in A
& { [K in keyof A & keyof B]: A[K] | B[K] }; // union of both.
Note that it may be helpful to indicate that the keys that are present in one but not the other may not exist so you would use Partial
on the Omit
ones:
type Combine<A, B> =
Partial<Omit<A, keyof B>> // possibly items in A that aren't in B
& Partial<Omit<B, keyof A>> // possibly items in B that aren't in A
& { [K in keyof A & keyof B]: A[K] | B[K] }; // union of both.
Edit: Aaronium asking about using unions has lead me to an even better way of doing this, since T extends any ? X : never
will operate over every element of a union you can actually expand all the keys present in any element of the union and then make a union of the values corresponding to all the interfaces, so it boils down to just this:
// gets all viable keys from all interfaces in a union.
type AllKeysOf<T> = T extends any ? keyof T : never
// basically does T[K] but when T is a union it only gives T[K] for the members of the union for which it is a valid key.
type Get<T, K extends keyof any> = T extends Record<K, any> ? T[K] : never
// takes a union of interfaces and merges them so that any common key is a union of possibilities.
type Combine<T> = {[K in AllKeysOf<T>]: Get<T,K>}
type TEST = Combine<{a:1} | {a:2, b:10} | {b: 11}>
// TEST = {a: 1|2, b: 10|11}
Answered By - Tadhg McDonald-Jensen
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.