I tried to define a type definition for recurrent intersection, to achieve such kind of behaviour:
type merged = Merged<[{a: string}, {b: string}, ...]>
to be {a: string} & {b: string} & ...
I defined some type utilities like Head
and Tail
to be able to operate on a variable number of input types and managed to define recurrent union, but failed to achieve the same for intersection :(
type Head<T extends any[]> = T[0]
type Tail<T extends any[]> =
((...args: T) => any) extends ((_arg0: any, ...rest: infer R) => any) ? R : never
type United<T extends any[]> = {
0: Head<T>
1: United<Tail<T>>
}[ T extends ([] | [any])
? 0
: 0 | 1
]
type Merged<T extends any[]> = {
0: Head<T>
1: Merged<Tail<T>>
}[T extends ([] | [any])
? 0
: 0 & 1
]
type a = {a: string}
type b = {b: string}
type c = {c: string}
type head = Head<[a, b, c, d]> // {a: string} OK
type tail = Tail<[a, b, c, d]> // [b, c] OK
type united = United<[a, b, c, d]> // a | b | c OK
type merged = Merged<[a, b, c, d]> // unknown Not good
I must be failing on some base internals of TypeScript, but have no idea why it worked in case of union and did not in case of intersection?
How can I fix it maybe?