Reputation: 4685
Please see this minimum code below.
function zip<T>(...arrs: T[][]): T[][] {
return arrs
}
zip([1,2,3], ['a', 'b', 'c'])
// Type 'string' is not assignable to type 'number'.ts(2322)
zip<number | string>([1,2,3], ['a', 'b', 'c'])
// Ok, but a little bit bother to me.
I created a function using generics
and rest
properties.
When I directly use zip([1,2,3], ['a', 'b', 'c'])
, I expect that typescript automatically finds out I'm using number | string
type, is there any way to achieve this?
Upvotes: 1
Views: 165
Reputation: 249506
Typescript sees the first parameter is number[]
and this fixes T
and then you get an error for the second. While in theory T
could be inferred to string | number
I would argue the current behavior is usually a good thing, it is more likely infering unions would lead to unexpected errors in other places.
You can get the compiler to accept the call you want if you make the compiler consider all the arguments as a whole, not individually, using tuples in rest parameters:
function zip<T extends any[][]>(...arrs: T): (T[number][number])[][] {
return arrs
}
zip([1,2,3], ['a', 'b', 'c'])
T
will be a tuple type for the sample call ([number[], string[]]
, so to get the item type we use T[number][number]
(which will be string | number
for the sample call), and the get back to the array of arrays using [][]
Upvotes: 1