I had originally created a method to combine objects, but upon revisiting it, I noticed it was no longer functioning as expected (only displaying never
- although still functional on the TS playground for some reason).
This is how it currently looks:
//https://github.com/microsoft/TypeScript/issues/13298#issuecomment-707364842
type UnionToArray<T> = (
(
(
T extends any
? (t: T) => T
: never
) extends infer U
? (U extends any
? (u: U) => any
: never
) extends (v: infer V) => any
? V
: never
: never
) extends (_: any) => infer W
? [...UnionToArray<Exclude<T, W>>, W]
: []
);
type IntersectObjectArray<A extends any> = A extends [infer T, ...infer R] ? T & IntersectObjectArray<R> : unknown
type ExpandTopKeys<A extends any> = A extends { [key: string]: infer X } ? { [K in keyof X]: X[K] } : unknown
type Expand<A extends any> = IntersectObjectArray<UnionToArray<ExpandTopKeys<A>>>;
type MergedClasses<C extends object[]> = Expand<IntersectObjectArray<C>>;
What this script does is, given:
X = {
foo: {
a: "green",
},
bar: {
b: "blue",
}
}
Y = {
extra: {
c: "orange",
},
}
MergedClasses<[X, Y]>
will output:
{
a: "green",
b: "blue",
c: "orange",
}
This function combines objects, expands their keys, and merges them into a single object.
The current steps involved are:
- Intersecting all objects in the array i.e.
[X, Y]
becomesX & Y
- Expanding the "top keys" i.e. expanding
foo
,bar
, andextra
resulting in a union like:
{
a: "green",
b: "blue",
} | {
c: "orange",
}
- Converting the union into an array of objects i.e.
[{ a: "green", b: "blue" }, { c: "orange" }]
- Finally, intersecting all those objects together once again. After following these steps, the desired result is achieved. However, this approach seems fragile and prone to breaking (as it already has).
Is there a simpler way to merge any number of objects and expand their keys?