2

I have a union of Parameters:

type Params = [{ name: string }] | [{ x: number, y: number } | ...];

I want to concat every tuple in the union (independently from the number of tuples in the union) and get a result like the following:

type ParamsJoined = [{ name: string, x: number, y: number, ... }];

I can't use tricks like const since the type Params is created dynamically using Parameters and distributive conditional types on a union of functions.

How can I do it?

pietrovismara
  • 6,102
  • 5
  • 33
  • 45

1 Answers1

4

Well, you need 3 things to achieve:

  1. Extract the underlying type from the array type.
  2. Split the union type
  3. And merge the split type into one.

The first one is an easy one which includes mapped types and infer keyword:

type UnderlyingType<T> = T extends Array<infer R> ? R : T;

For the second one, you must refer to this question.

And the third one is a little bit advanced and you should refer to this question.

And finally, you will have something like below :


type U1 = UnderlyingType<Params>

type SplitTyped = SplitType<U1>

type FinalType = Spread<SplitTyped[0],SplitTyped[1]>

Playground Link

Edit: For unknown numbers of type arguments (which is limited up to somewhere) you can utilize a SpreadTuple type map to achieve

type SpreadTuple<T extends any[], L extends number = T['length']> = L extends 0 ? never 
: L extends 1 ? T[0] 
: L extends 2 ? Spread<T[0], T[1]> 
: L extends 3 ? Spread<T[0], Spread<T[1], T[2]>> 
: L extends 4 ? Spread<T[0], Spread<T[1],Spread<T[2],T[3]>>> 
: never; // continiue to somewhere

And then you can use it as you require:

type FinalType = SpreadTuple<SplitTyped>

Playground Link

Eldar
  • 9,781
  • 2
  • 10
  • 35
  • Nice solution. The problem is that `Spread` seems to work only with a fixed amount of parameters, but since the union is generated dynamically I can't do that. I would need something like `Spread`. – pietrovismara Sep 27 '20 at 12:20