[Typescript Challenges] 147 Medium - MergeAll
Merge variadic number of types into a new type. If the keys overlap, its values should be merged into an union.
For example:
type Foo = { a: 1; b: 2 }
type Bar = { a: 2 }
type Baz = { c: 3 }
type Result = MergeAll<[Foo, Bar, Baz]> // expected to be { a: 1 | 2; b: 2; c: 3 }
Answer:
/* _____________ Your Code Here _____________ */
export type MergeValueAsUnion<
F extends object,
S extends object
> = {
[Key in (keyof F | keyof S)]: Key extends keyof S
? S[Key] | (Key extends keyof F ? F[Key] : never)
: Key extends keyof F
? F[Key]
: never
};
type MergeAll<XS extends object[], ACC extends object = {}> = XS extends [infer A extends object, ...infer REST extends object[]]
? MergeAll<REST, MergeValueAsUnion<ACC, A>>
: ACC;
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<MergeAll<[]>, {} >>,
Expect<Equal<MergeAll<[{ a: 1 }]>, { a: 1 }>>,
Expect<Equal<
MergeAll<[{ a: string }, { a: string }]>,
{ a: string }>
>,
Expect<Equal<
MergeAll<[{ }, { a: string }]>,
{ a: string }>
>,
Expect<Equal<
MergeAll<[{ a: 1 }, { c: 2 }]>,
{ a: 1; c: 2 }>
>,
Expect<Equal<
MergeAll<[{ a: 1; b: 2 }, { a: 2 }, { c: 3 }]>,
{ a: 1 | 2; b: 2; c: 3 }>
>,
Expect<Equal<MergeAll<[{ a: 1 }, { a: number }]>, { a: number }>>,
Expect<Equal<MergeAll<[{ a: number }, { a: 1 }]>, { a: number }>>,
Expect<Equal<MergeAll<[{ a: 1 | 2 }, { a: 1 | 3 }]>, { a: 1 | 2 | 3 }>>,
]