你能在TypeScript中扩展一个函数吗?

你能在TypeScript中扩展一个函数吗?,typescript,Typescript,我帮助维护一个JavaScript库,该库生成间谍函数,允许您检查传入函数的调用方式(主要用于单元测试) 该库创建了一个函数,该函数具有允许您检查调用的附加属性 是否可以创建一个TypeScript定义,允许将函数传递给需要函数且具有额外属性的方法 这是无效的,但类似于: class Spy extends function { wasCalled: () => boolean; ... } 这将允许我将间谍传递到具有以下签名的函数: function subjectUn

我帮助维护一个JavaScript库,该库生成间谍函数,允许您检查传入函数的调用方式(主要用于单元测试)

该库创建了一个函数,该函数具有允许您检查调用的附加属性

是否可以创建一个TypeScript定义,允许将函数传递给需要函数且具有额外属性的方法

这是无效的,但类似于:

class Spy extends function {
    wasCalled: () => boolean;
    ...
}
这将允许我将间谍传递到具有以下签名的函数:

function subjectUnderTest(callback:() => void) {
    ...
}
是的,因为它是函数类型和常规接口的组合

interface Spy {
    (foo: string, bar: number) : boolean; // Just an example
    wasCalled() : boolean;
}

var spy : Spy = createASpySomehow();
var result = spy("foo", 123);
if (spy.wasCalled()) {
    // ...
}

我还想用一个函数扩展一个类,并制定了一个只有TypeScript的解决方案。我不确定这是否是一个好主意,因为聪明的解决方案并不总是好的解决方案。YMMV

感谢Mattias Buelens提供了部分答案!我在它的基础上发展

// 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
    }
}
一切正常


我认为
newspy()
不起作用,因为我们需要分配给函数,而不是相反。因为我们不能替换
这个
,所以我们不能使
这个
成为可调用的。我看到的一种假设方法是用函数构造函数来扩展一个类:
classspy2 extends function(){}{}
,但我没有找到一种方法来实现这一点。

不确定为什么会被否决,这正是我想要的。也许因为这是
createASpySomehow()的部分答案
提示。如何通过扩展函数来创建interface Spy的实例?答案中链接的Typescript文档使用了一种不同的方法:将函数强制转换到接口,然后向函数添加属性,有关示例,请参见我的答案。然而,即使是我的回答也没有扩展函数。@nalply最初的问题是关于为现有JavaScript库编写TypeScript类型定义。当然,如果您也在用TypeScript编写库实现,那么在创建函数时需要显式转换。:-)有趣的解决方案,但可能有点太神奇了。例如:由于将函数的原型替换为
Spy.prototype
,因此会丢失
Spy.bind()
Spy.apply()
Spy.call()等方法。我认为直接在函数上添加额外的方法比在函数的原型上添加它们更容易。我同意。。。此解决方案的一个优点是,您可以拥有一个复杂的构造函数,并且在此过程中可以得到TypeScript的类型验证。
const spy = Spy.create(true)
console.log('calling spy', spy('foo', 42))
console.log('instanceof', spy instanceof Spy)