Home > database >  Call a generic function with matching generic arguments
Call a generic function with matching generic arguments

Time:10-08

I'm trying to write a function that takes as arguments another function and it's args, then executes the function with the provided args and return the result while preserving the types.

As long as the provided function has a static return type, it's fine. But when that function's return type depends on the params, I'm not able preserve the return type.

Here is my failed attempt. I hope it will clarify what I'm trying to achieve:

function f<A>(args: A) {
  return args
}
// Calling the fuction directely works as expected:
const result = f('test') // OK: type of result is 'test'

// I tried this to be more explicit about the return type but it does not work
type ReturnTypeWithArgs<
  F extends (args: any) => any,
  A extends Parameters<F>[0],
> = F extends (args: A) => infer R ? R : never

// This is the function I'm trying to build
function callFunction<F extends (args: any) => any, A extends Parameters<F>[0]>(
  f: F,
  args: A,
): ReturnTypeWithArgs<F, A> {
  return f(args)
}

// I'd like to get the same returned type when using callFunction. But it doesn't work:
const result2 = callFunction(f, 'test') // KO: typeof test2 is unknown

CodePudding user response:

There's currently no purely type-level way to take a generic function type like <T>(t: A<T>) => R<T> and an argument type like X and get the compiler to tell you what the return type would be if you called the function with an argument of type X. You can't use conditional type inference like the ReturnType<T> or the Parameters<T> utility types; it ends up just replacing the generic type parameters with their (possibly implicit) constraints, so <T>(t: A<T>) => R<T> becomes just (t: A<unknown>) => R<unknown>).

There's an open suggestion at microsoft/TypeScript#40179 for type operators that answer the above question. It's marked as "Awaiting More Feedback", without much engagement. If you want to see it happen you might go there, give it a

  • Related