Home > Net >  Is there a way to infer the return type of a function parameter of a generic function type definitio
Is there a way to infer the return type of a function parameter of a generic function type definitio

Time:12-12

Say I have a type definition for a "Middleman" function like this:

type Middleman = (
    callback: () => any
) => any

This function does "some task", then calls "callback" and returns its value. Right now both Middleman and the callback are typed to return any, but I would like to strongly type this.

I have tried introducing a type parameter like so:

type Middleman<T> = (
    callback: () => T
) => T

But this causes issue when trying to create an implementation of this function:

const middlemanImpl: Middleman<T> = cb => cb(); // Error, no way to get T here

As Middleman expects a "T" and can't seem to infer it from each call site.

Is there a way to achieve what I am trying to accomplish here? That is: a type definition for a generic function that returns the type of the return value of a function passed as an argument?

CodePudding user response:

You don't want Middleman to really be a generic type that refers to a specific function:

type BadMiddleman<T> = (callback: () => T) => T;

In this version, you cannot mention the type BadMiddleman without specifying the type parameter T. And once you do that, any call to the function has to use that specified type T:

const numMiddleman: BadMiddleman<number> = cb => cb();
numMiddleman(() => 12); // okay
numMiddleman(() => "abc"); // error

Instead, you want Middleman to be a specific type that refers to a generic function. The difference is in the scope of the generic type parameter:

type Middleman = <T>(callback: () => T) => T;
const middlemanImpl: Middleman = cb => cb(); // okay

Now it is the call to a function of type Middleman which decides what type T is:

const num = middlemanImpl(() => 12); // okay
num.toFixed();

const str = middlemanImpl(() => "abc"); // okay
str.toUpperCase();

Playground link to code

  • Related