Typescript interfaces allow definition of a function-style call signature thus:
interface A {
(x: number): number;
}
This can be implemented by, e.g. a function:
const a: A = function(x: number): number {
return 1;
}
Is it possible to implement such an interface using a class?
I've attempted it like this:
class B implements A {
(x: number): number {
return 1;
}
}
But I get this error:
Class 'B' incorrectly implements interface 'A'. Type 'B' provides no match for the signature '(x: number): number'.ts(2420)
Is there any way to implement this sort of interface using a class in Typescript?
This is possible. In my projects I implemented a Callable helper class merged with an interface with the same name. The merge with the interface is needed to give TypeScript the correct function signature typings:
export interface Callable<T extends unknown[] = unknown[], R = unknown> {
(...args: T): R;
}
export class Callable<T extends unknown[] = unknown[], R = unknown> extends Function {
public constructor(func: (...args: T) => R) {
super();
return Object.setPrototypeOf(func, new.target.prototype) as typeof this;
}
}
Using this class is pretty straight forward:
class Test extends Callable<[ number, number ], number> {
public multiplier = 2;
public constructor() {
super((a, b) => (a + b) * this.multiplier);
}
}
const test = new Test();
console.log(test(1, 2)); // Prints 6
test.multiplier = 3;
console.log(test(1, 2)); // Prints 9
Some explanations:
[ number, number] in this case means the function expects two numeric parameters.number.Callable super class.Warning! Only use this if you like the functionality and don't care much about performance. Because a callable class instance is a lot slower than a real function! (Node.js and Chrome: 20 times slower, Firefox: 5 times slower).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With