Reputation: 2370
I have this
Type T = Params<[Tuple1, Tuple2]> // eg [[string], [number]]
How to make of it (flatten)
Type Flatten<T> = Params<[string, number]>
Upvotes: 6
Views: 2015
Reputation: 406
You can now define recursive types:
type Flatten<T> = (
T extends [] ? [] :
T extends [infer T0] ? [...Flatten<T0>] :
T extends [infer T0, ...infer Ts] ? [...Flatten<T0>, ...Flatten<Ts>] : [T]
)
type T = Flatten<[[number, number, []], string, [[]], [string, [number, string]]]>
// T is [number, number, string, string, number, string]
Upvotes: 3
Reputation: 20132
We can do that by mapped types. Consider the code:
type T = Params<[Tuple1, Tuple2]>
// utility type
type Flatten<T extends any[]> = {
[K in keyof T]: T[K] extends any[] ? T[K][0] : T[K]
}
type Result = Flatten<T>
// evaluates into [string, number]
const a: Result = ['a', 1] // correct value of the type
Pay attention how Flatten
works:
[K in keyof T]
- means we want to have all keys, so in tuple say elementsT[K] extends any[] ? T[K][0] : T[K]
- we say if the value of the element on the given key is an array then give me a type of an first element of this array (index 0), if not leave it as is, as there is nothing to be flattenIf your tuples consider more then one type of the element, then above solution will take the first only. So for tuple [string, number]
it will produce the string
. If we want to gather all possible types inside the tuple we can create more sophisticated type. Consider:
type Flatten<T extends any[]> = {
[K in keyof T]: T[K] extends any[] ? T[K][Exclude<keyof T[K], keyof any[]>] : T[K]
}
T[K] extends any[] ? T[K][Exclude<keyof T[K], keyof any[]>] : T[K]
means that if our element is an array then get me types of all elements, but remove types of values in array prototype.In the result Flatten<Params<[string, number]>>
will produce [string | number]
. So it depends what is your goal.
The last proposition is, if you don't consider other types and only nested array/tuples, we can avoid conditional types. Consider last solution:
type Flatten<T extends E[], E extends any[] = any[]> = {
[K in keyof T]: T[K][Exclude<keyof T[K], keyof any[]>]
}
Above type is more restrict as it works with only [[]]
but is more concise and specific.
Upvotes: 4