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

时间:2016-07-12 20:07:59

标签: typescript

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

该库创建了一个函数,该函数具有其他属性,允许您检查调用。

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

这是无效的,但类似于:

function check(hay, needle, from) {
  var i = 1;
  while (i < needle.length) {
    if (hay[from] != needle[i])
      return false;
    i++;
    from++;
  }
  return true;
}

function myFindWordIndex(str, findme) {
  var indices = [];
  var needle = findme.split(" ");
  var hay = str.split(" ");

  for (var i = 0; i < hay.length - needle.length; i++) {
    if (hay[i] == needle[0] && (needle.length==1||check(hay, needle, i)))
      indices.push(i);
  }
  return indices;
}
var str = 'Hello this is my this is world';

console.log(myFindWordIndex(str, 'this is')); // ==> [1, 4]

这将允许我将间谍传递给具有此签名的函数:

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

2 个答案:

答案 0 :(得分:29)

是的,the TypeScript handbook calls this a "hybrid type",因为它是功能类型和常规界面的组合。

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

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

答案 1 :(得分:0)

我也想用一个函数扩展一个类,并制定出一个仅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
    }
}

这个想法是创建一个函数和Spy的实例,然后将原型和属性都分配给该函数。从静态方法返回实例。奖励是toString()方法。

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

按预期工作。

我认为new Spy()不起作用,因为我们需要分配给函数而不是相反的方法。而且因为我们无法替换this,所以我们无法使this成为可调用对象。我看到的一种假设方法是使用某种实际上是函数构造函数的类来扩展类,例如:class Spy2 extends function() {} {},但我没有找到使该类起作用的方法。