Can you extend a function in TypeScript?

I support the JavaScript library that creates spy functions that let you check how the transfer function was called (mainly for use in unit testing).

The library creates a function on which there are additional properties that allow you to check calls.

Is it possible to create a TypeScript definition that allows you to pass a function to methods that require a function AND have additional properties?

This is not true, but something like:

class Spy extends function { wasCalled: () => boolean; ... } 

So that I can pass the spy into a function with this signature:

 function subjectUnderTest(callback:() => void) { ... } 
+10
source share
2 answers

Yes, the TypeScript reference calls it a โ€œhybrid typeโ€ because it is a combination of a function type and a normal interface.

 interface Spy { (foo: string, bar: number) : boolean; // Just an example wasCalled() : boolean; } var spy : Spy = createASpySomehow(); var result = spy("foo", 123); if (spy.wasCalled()) { // ... } 
+29
source

I also wanted to extend the class with a function and developed a solution only for TypeScript. I'm not quite sure if this is a good idea, because smart decisions are not always good decisions. YMMV.

Thanks to Matthias Buleans for the partial answer! I build on that.

 // same as in the answer of Mattias interface Spy { (foo: string, bar: number): boolean // Just an example wasCalled(): boolean } // and now for the real solution! class Spy { _wasCalled: boolean _baz: boolean // Just an example private constructor(baz: boolean) { this._wasCalled = false this._baz = baz } wasCalled(): boolean { return this._wasCalled } toString() { return '[object Spy]' } static create(baz: boolean) { const f = <Spy>function(this: Spy, foo: string, bar: number): boolean { // Do your thing here. Use f instead of this! console.log('wasCalled', f.wasCalled()) f._wasCalled = true } const spy = new Spy(baz) Object.assign(f, spy) Object.setPrototypeOf(f, Spy.prototype) return f } } 

The idea is to create a function and an instance of Spy , and then assign a function to the prototype and properties. Return an instance from a static method. The bonus is the toString() method.

 const spy = Spy.create(true) console.log('calling spy', spy('foo', 42)) console.log('instanceof', spy instanceof Spy) 

works as expected.

I don't think new Spy() will work because we need to assign a function, not the other way around. And since we cannot replace this we cannot make this callable. The hypothetical way that I see is to extend the class with a truly constructor function, something like this: class Spy2 extends function() {} {} , but I did not find a way to make this work.

0
source

All Articles