I'm writing a utility type for combining two TypeScript lists together:
type TupleIntersect<L extends unknown[], R extends unknown[]> =
L extends [infer LH, ...infer LT]
? R extends [infer RH, ...infer RT]
? [LH & RH, ...TupleIntersect<LT, RT>] // Left & right are tuples w/ 1+ element
: [LH & R[number], ...TupleIntersect<LT, R>] // Left is a tuple w/ 1+ element
: R extends [infer RH, ...infer RT]
? [RH & L[number], ...TupleIntersect<L, RT>] // Right is a tuple w/ 1+ element
: L extends []
? R extends []
? [] // Left & right are empty tuples
: R[number] // Left is an empty tuple
: R extends []
? L[number] // Right is an empty tuple
: (L[number] & R[number])[]; // Left & right are list types
and would like to find a way to generalize it so that I wouldn't have to rewrite the above cases over and over for things like "tuple unions" or other sorts of combinations involving tuple types.
I'd imagine it would have to look something like below:
type TupleZip<L extends unknown[], R extends unknown[], Combinator, Default> =
L extends [infer LH, ...infer LT]
? R extends [infer RH, ...infer RT]
? [Combinator<LH, RH>, ...TupleZip<LT, RT, Combinator, Default>]
: [Combinator<LH, R[number]>, ...TupleZip<LT, R, Combinator, Default>]
: R extends [infer RH, ...infer RT]
? [Combinator<L[number], R>, ...TupleZip<L, RT, Combinator, Default>]
: L extends []
? R extends []
? []
: [Combinator<Default, R[number]>]
: R extends []
? [Combinator<L[number], Default>]
: Combinator<L[number], R[number]>[];
where a Combinator
generic type would be specified like this:
type Intersect<L, R> = L & R;
type TupleIntersect<L extends unknown[], R extends unknown[]> = TupleZip<L, R, Intersect, unknown>;
type Union<L, R> = L | R;
type TupleIntersect<L extends unknown[], R extends unknown[]> = TupleZip<L, R, Union, never>;
but the TypeScript compiler doesn't allow it b/c "type parameters aren't generic types".
Is there some legal way to accomplish what I'm thinking of doing via TypeScript? Or have I gone too far down the dark path in equivocating TypeScript generic types with C++ template metaprogramming and template templates?