2

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?

Aluan Haddad
  • 29,886
  • 8
  • 72
  • 84
Josh Hansen
  • 917
  • 1
  • 9
  • 20
  • It may be a dublicate of https://stackoverflow.com/questions/13407036/how-does-interfaces-with-construct-signatures-work – captain-yossarian from Ukraine Feb 25 '21 at 20:30
  • Are you trying to be able to call a class as a function without the `new` keyword `B()`? Or call an instance as function `const b = new B(); b()`? – Alex Wayne Feb 25 '21 at 20:30
  • No, not like that. I want to be able to call class instances: `const b = new B(); const answer = b(10);` – Josh Hansen Feb 25 '21 at 20:33
  • 4
    An actual class - no. You can hack something together using old style constructor functions. With that said, this sounds like [an XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – VLAZ Feb 25 '21 at 20:39
  • why not `const answer = new B().b(10)`? –  Feb 25 '21 at 20:55
  • 1
    You can make your `constructor()` method return a function, but TS won't follow the typings. The typings are the easy thing to fix, though. The hard part is getting the thing you return from `constructor()` to act enough like a class instance to be useful. I'd hate to imagine the the edge and corner cases that would come up at runtime if you went this route. – jcalz Feb 25 '21 at 21:00
  • It's not clear why you would want to use a class to implement a function. Functions are first class in JavaScript and your situation is easily covered by a function factory function, a function that returns a function. The `interface` isn't relevant as the implements clause is an optional `formality`. – Aluan Haddad Feb 25 '21 at 21:34
  • I don't think you can do this in JS. You can make a class instance be callable in other languages like PHP but I just don't think that sort of functionality exists in JS. – Linda Paiste Feb 25 '21 at 22:51
  • 1
    @LindaPaiste it's doable but not really "the intended way". You have to return a *function instance* with all the class properties and methods you'd expect from the class declaration. However, I can't really think of any use case for this. The cases where I can think of a function with any extra properties are *extremely* rare and very narrow to begin with. – VLAZ Feb 25 '21 at 23:30
  • @VLAZ that makes sense seeing as ES6 classes are functions behind the scenes. In PHP it is straightforward and easy, you just need an `__invoke` method in the class: https://www.php.net/manual/en/language.oop5.magic.php#object.invoke – Linda Paiste Feb 25 '21 at 23:34
  • 1
    In Python I would use `__call__`. The actual use case is that I have canonicalization functions that I would like to be composable. Things like `lowercase` and `removeWhitespace` for strings. I'd like the canonicalizers to act like functions, but also have a `then` method for composition. But in the worst case I guess I can put the function on the class as a field, but it's annoying that way. – Josh Hansen Feb 26 '21 at 07:06

0 Answers0