This function:
const proxy = () => Math.random() < 0.5 ? numbersArray : stringsArray;
has a return type of:
number[] | string[]
This type says that the you either have an array of all numbers, or an array of all strings, but never a mix of both.
So what is the type of the members of that type? You might think it's number | string
, but that's not quite true. If you take string | number
and add the array notation to the end, you get:
(number | string)[]
This type says that it's an array of strings or numbers, and each member could be either. You can now mix both. This is not the same thing. This means that the member type cannot be inferred, because that member type can't be used to construct the original array type.
Now lets look at the generic function:
function func<T>(array: T[]): T[][] {
return [[array[0], array[1]], [array[2], array[3]]];
}
This function tries to find the member type T
for the array T[]
. But as demonstrated above, there is no good member type for string[] | number[]
. So typescript fails to infer T
and throws an error.
So to make your function work, the member type T
needs to be inferable. You can do that by casting the return type of proxy to a compatible array type where only the members of the array are a union.
const proxy: () => (string | number)[] =
() => Math.random() < 0.5 ? numbersArray : stringsArray;
Now T
can become string | number
and everything works like you expect.
const resultUnion = func(proxy()); // type: (string | number)[][]
Playground