7

I have a situation, where I call a function with some arguments, which are resolved using another function.

This is how the code looks.

function getArgs (): [string, number] {
  return ['hello world', 22]
}

function callFnWithArgs (callback) {
  callback(...getArgs())
}

callFnWithArgs(function (/* typehint here */) {
})
  1. The function callFnWithArgs takes a callback and then execute it by passing some arguments.
  2. Those arguments are given by another function called getArgs().

So, is there any way to type hint, the arguments of the callback, which is the return value of another function?

3 Answers 3

5

In TypeScript 3.0 or newer, you can use the ReturnType type alias from the standard library to determine the return type of getArgs and then use a rest parameter to tie that to the callback of callFnWithArgs:

function getArgs (): [string, number] {
  return ['hello world', 22]
}

function callFnWithArgs (callback: (...args: ReturnType<typeof getArgs>) => void) {
  callback(...getArgs())
}

callFnWithArgs(function (a, b) {
  // a is string, b is number
})
Sign up to request clarification or add additional context in comments.

Comments

3

You can either define the type of callback:

function callFnWithArgs (callback: (a: string, b: number) => void) {
  callback(...getArgs())
}

Or if it's an option to pass the arguments from outside the function callFnWithArgs, you can use Generic rest parameters:

function getArgs (): [string, number] {
  return ['hello world', 22]
}

function callFnWithArgs<T extends any[]>(args: T, callback: (...args: T) => void) {
  callback(...args);
}

callFnWithArgs(getArgs(), (str, nr) => {
})

Yet another approach would be to create overloads with generic types for the parameters:

function getArgs(): [string, number] {
  return ['hello world', 22]
}
function callFnWithArgs<T>(callback: (a: T) => void);
function callFnWithArgs<T1, T2>(callback: (a: T1, b: T2) => void);
function callFnWithArgs(callback: (...args: any[]) => void) {
  callback(...getArgs());
}

callFnWithArgs<string, number>((str, nr) => {
})

3 Comments

I do like this approach, but if I have to call getArgs() when using callFnWithArgs, then it kills the purpose of the entire code.
Also there is an error 'A rest parameter must be of an array type.' in (...args: T) => void
@sherlock.92 You're probably not using TypeScript 3
0

Does it solve your task?

function getArgs(): [string, number] {
  return ['hello world', 22]
}

function callFnWithArgs (callback: (a: string, b: number) => void) {
  const [a, b] = getArgs();
  callback(a, b);
}

callFnWithArgs(function (a: string, b: number) {
})

1 Comment

Nope! The getArgs function can be defined by the user of my code and they cannot change the signature of callFnWithArgs.

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.