You could provide an explicit type:
declare function fnA<T>(a: T, b: (T extends T ? T : never)[]): T
fnA<number>(1, [2, 'str'])
// Type 'string' is not assignable to type 'number'.(2322)
Or do something like:
declare function fnB<T>(a: T, b: (T extends T ? T : never)[]): T
fnB(1, [1, 'str']);
// Type 'string' is not assignable to type '1'.(2322)
This forces the compiler to have to examine the type of a
to figure out the type of b
.
But this seems to infer a more specific type than number
, so this doesn't work:
fnB(1, [1, 2]);
// Type '2' is not assignable to type '1'.(2322)
I think this breaks some heuristics Typescript about when a type automatically widens to number
or string
, and when it doesn't. And it is tricky for typescript to know just how tightly to constrain that type.
It will work fine if the first argument is a wider type like number
, though:
const x: number = 1
fnB(x, [1, 2]); // fine
Or you could just, again, provide the type if you don't like how it got inferred:
fnB<number>(1, [1, 2]); // fine
Playground