22

I'm trying to preserve the type information of arguments to a callback, where the callback is a generic:

function Foo<Template>(argument: Template) {
  // Do something with argument
}

function Bar(callback: Function) {
  callback('something')
}

let x = Bar( Foo<String> )

This does not look like valid typescript syntax. Any way to do this?

2
  • You can just do let x = Bar(Foo), but I'm not exactly sure what you're trying to accomplish. The function Foo takes a generic type parameter but it doesn't have to, since it's not doing anything special with it. And Bar doesn't seem to care what kind of function it takes. Maybe you could flesh out the example with some more motivating use cases? Commented Aug 17, 2017 at 17:49
  • @jcalz can we also not pass specific type as a parameter? In below example, when we pass doSomothing as a param, can we also pass the type along with it? thisFirst(doSomething<string>) Commented Dec 9, 2022 at 15:52

4 Answers 4

16

Expanding on the answer of Rodrigo here. If you have a function with a generic:

function doSomething<T>(t: T): void {
    console.log("oh " + t);
}

You can define the type of the function as follows:

type Handler = <T>(t: T) => void;

Then you can use the type Handler as a function parameter:

function thisFirst(callback: Handler) {
  callback<string>('boink');
}

thisFirst(doSomething)
Sign up to request clarification or add additional context in comments.

1 Comment

can we also not pass specific type as a parameter? In above example, when we pass doSomothing as a param, can we also pass the type along with it? thisFirst(doSomething<string>)
8

You can define a generic function for callback with a generic argument like this:

const handleSomething =
  <T extends (...args: Parameters<T>) => ReturnType<T>>(callback: T) =>
  (...args: Parameters<T>) =>
    callback(...args)
   

3 Comments

Thanks! Saved my time for passing dynamic arguments.
I'm getting such an error on the generic: TS2589: Type instantiation is excessively deep and possibly infinite.
The type for the whole function could be written as: <T extends (...args: Parameters<T>) => ReturnType<T>>( callback: T ) => (...args: Parameters<T>) => ReturnType<T>
2

Function is any function. Try to specify the callback.

function Foo<Template>(argument: Template) {
  // Do something with argument
}

function Bar(callback: { (argument: string) }) {
  callback('something')
}

let x = Bar(Foo);

Comments

0

The other answers are useful if the function with the callback parameters is defined in your code. Here is the more generic solution that will always work:

    
    
function Foo<Template>(argument: Template) {
  // Do something with argument
}

function Bar(callback: Function) {
  callback('something')
}

let x = Bar( (argument: String) => Foo<String>(argument) ) // using arrow functions
let x1 = Bar(function(argument: String) {
   return Foo<String>(argument)
}

In the above code, we create a new anonymous function that has the same arguments as the callback function, calls the function Foo specifying the type and returns whatever Foo will return.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.