Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Is there a way to infer the return type of a function parameter of a generic function type definition?

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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?

>Solution :

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

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading