I have a function with the following signature:
test<T>(...args: T[]): T
if I call the function like this:
const a = test(1, 2, 3)
everything works as expected (and a is of type number), but if I call it that way:
const a = test(1, 2, "asd")
I get any error:
[EDIT] The 2 is red underlined: Argument of type '2' is not assignable to parameter of type '1'., witch might be a bit misleading because the arguments are constants, but if I call it that way:
let arg1 = 1;
let arg2 = "asd";
const a = test(arg1, arg2);
I get the error: Argument of type 'string' is not assignable to parameter of type 'number'.
How can I make it so that the function would (in the second case) has a return type of number | string without explicitly specifying it in the generic parameter.
It is intentional that T is not inferred as a union; see Why isn't the type argument inferred as a union type?, as well as microsoft/TypeScript#19596 and microsoft/TypeScript#26746 for reasons why.
Probably the easiest way around this is to allow args to be any array type T whatsoever, and then get its element type by indexing into it with the key type number:
declare function test<T extends any[]>(...args: T): T[number];
const a = test(1, 2, 3) // number
const b = test(1, 2, "asd") // number | string
Playground link to code
I think this is the call signature you are looking for:
<T extends Array<unknown>>(...args: T): T[number]
TypeScript Playground
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With