How can keep generic type inference when I assign one type with multiple generics with default value?

Viewed 152

I define a function with multiple generics, and give them default types. For example:

function fun<A = any, B = any>(a: A, b: B) {
  return [a, b] as const;
}

If I don't assign any types to them, the generics will be infered correctly.

let a: number;
let b: string;
const res = fun(a, b);  // [number, string]

But if I assign a certain type to part of them, the rest generics will be infered by their default types.

let a: number;
let b: string;
const res = fun<number>(a, b);  // [number, any]

How can I assign some generics as well as keeping the rest generics inferring themselves?

Playground link

1 Answers

I wouldn't think this would come up much, typically a will have the desired type so there's no reason for explicitly providing a type argument. But in the cases where you want the result to be a different type from a (probably a supertype), the solution that comes to mind is to use as instead of a type argument.

Here's an example:

type NumList = 42 | 67;

declare let a: NumList;
declare let b: string;
const res1 = fun(a, b);  // [NumList, string]

const res2 = fun(a as number, b);  // [number, string]
//                ^^^^^^^^^^

Playground link

In general I try to avoid type assertions, but that's effectively what providing the type argument would be anyway, and at least if the type assertion is wildly invalid it'll fail, for instance:

declare let a2: string;
const res3 = fun(a2 as number, b);
//               ^^^^^^^^^^^^−−−−−−− error

Playground link

Related