How to define type for a function callback (as any function type, not universal any) used in a method parameter
Solution 1:
The global type Function
serves this purpose.
Additionally, if you intend to invoke this callback with 0 arguments and will ignore its return value, the type () => void
matches all functions taking no arguments.
Solution 2:
Typescript from v1.4 has the type
keyword which declares a type alias (analogous to a typedef
in C/C++). You can declare your callback type thus:
type CallbackFunction = () => void;
which declares a function that takes no arguments and returns nothing. A function that takes zero or more arguments of any type and returns nothing would be:
type CallbackFunctionVariadic = (...args: any[]) => void;
Then you can say, for example,
let callback: CallbackFunctionVariadic = function(...args: any[]) {
// do some stuff
};
If you want a function that takes an arbitrary number of arguments and returns anything (including void):
type CallbackFunctionVariadicAnyReturn = (...args: any[]) => any;
You can specify some mandatory arguments and then a set of additional arguments (say a string, a number and then a set of extra args) thus:
type CallbackFunctionSomeVariadic =
(arg1: string, arg2: number, ...args: any[]) => void;
This can be useful for things like EventEmitter handlers.
Functions can be typed as strongly as you like in this fashion, although you can get carried away and run into combinatoric problems if you try to nail everything down with a type alias.
Solution 3:
Following from Ryan's answer, I think that the interface you are looking for is defined as follows:
interface Param {
title: string;
callback: () => void;
}
Solution 4:
You can define a function type in interface in various ways,
- general way:
export interface IParam {
title: string;
callback(arg1: number, arg2: number): number;
}
- If you would like to use property syntax then,
export interface IParam {
title: string;
callback: (arg1: number, arg2: number) => number;
}
- If you declare the function type first then,
type MyFnType = (arg1: number, arg2: number) => number;
export interface IParam {
title: string;
callback: MyFnType;
}
Using is very straight forward,
function callingFn(paramInfo: IParam):number {
let needToCall = true;
let result = 0;
if(needToCall){
result = paramInfo.callback(1,2);
}
return result;
}
- You can declare a function type literal also , which mean a function can accept another function as it's parameter. parameterize function can be called as callback also.
export interface IParam{
title: string;
callback(lateCallFn?:
(arg1:number,arg2:number)=>number):number;
}
Solution 5:
Here's an example of a function that accepts a callback
const sqk = (x: number, callback: ((_: number) => number)): number => {
// callback will receive a number and expected to return a number
return callback (x * x);
}
// here our callback will receive a number
sqk(5, function(x) {
console.log(x); // 25
return x; // we must return a number here
});
If you don't care about the return values of callbacks (most people don't know how to utilize them in any effective way), you can use void
const sqk = (x: number, callback: ((_: number) => void)): void => {
// callback will receive a number, we don't care what it returns
callback (x * x);
}
// here our callback will receive a number
sqk(5, function(x) {
console.log(x); // 25
// void
});
Note, the signature I used for the callback
parameter ...
const sqk = (x: number, callback: ((_: number) => number)): number
I would say this is a TypeScript deficiency because we are expected to provide a name for the callback parameters. In this case I used _
because it's not usable inside the sqk
function.
However, if you do this
// danger!! don't do this
const sqk = (x: number, callback: ((number) => number)): number
It's valid TypeScript, but it will interpreted as ...
// watch out! typescript will think it means ...
const sqk = (x: number, callback: ((number: any) => number)): number
Ie, TypeScript will think the parameter name is number
and the implied type is any
. This is obviously not what we intended, but alas, that is how TypeScript works.
So don't forget to provide the parameter names when typing your function parameters... stupid as it might seem.