使用TypeScript扩展Object.prototype

ser*_*0ne 28 javascript prototype interface object typescript

我目前正在开发TypeScript API,它需要一些绑定到Object原型(Object.prototype)的附加功能.

请考虑以下代码:

class Foo {

}

interface Object {
    GetFoo(): Foo;
    GetFooAsString(): string;
}

//This is problematic...
Object.prototype.GetFoo = function() {
    return new Foo();
    // Note, this line is just for testing...I don't want my function to just return a blank instance of Foo!
}

//This is ok.
Object.prototype.GetFooAsString = function () {
    return this.GetFoo().toString();
}
Run Code Online (Sandbox Code Playgroud)

您可能想直接在Playground尝试这个.

如你所见,我有一个叫做的类Foo(不是我将要使用的实际对象名).我还扩展了Object界面以包含两个新功能.最后我实现了针对prototype这些功能(这些工作在纯JavaScript中,它只是抱怨的TypeScript).

我在其中注释" //这是有问题的...... "TypeScript用红色波浪形突出显示,并显示以下错误:

Cannot convert '() => Foo' to '{ (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; }': Call signatures of types '() => Foo' and '{ (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; }' are incompatible
() => Foo
Run Code Online (Sandbox Code Playgroud)

要么这只是一个TypeScript错误(我知道它仍处于开发阶段,所以很多错误需要解决,我已经在CodePlex上说明了一些),或者,我遗漏了一些东西.

为什么我会遇到这个问题?

如果它不是TypeScript错误,我该如何解决这个问题?

Ton*_*Nam 18

我曾经有过:

// See if an array contains an object
Array.prototype.contains = function (obj) {
    var i = this.length;
    while (i--) {
        if (this[i] === obj) {
            return true;
        }
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

为了使用typescript编译代码,我添加了以下行:

interface Array {
    contains(obj: Object): boolean;
}
Run Code Online (Sandbox Code Playgroud)

谢谢basarat!

  • 不包含(obj:any):boolean; 在这里更合适吗? (3认同)
  • 注意:我必须在这里使用`interface Array <T>`否则我会得到"错误TS2428:接口的所有声明必须具有相同的类型参数." (2认同)
  • 如何使用`import`? (2认同)

bas*_*rat 11

这个错误在TS 0.9.0 alpha中修复,如下所示: Ts 0.9.0 alpha中没有错误

操场仍在运行0.8.3.

这基本上是因为某些关键接口(Object,Number,String)等上的方法被缓存为性能优化.

如果你运行这个.第一次加载时您将看不到该错误.试试吧.

只要对该代码进行编辑,解析器就会再次遍历代码,并且由于它缓存了旧的接口定义,因此会看到重复的函数定义,然后会有效地破坏.您对该文件所做的编辑越多,错误语句就越复杂.


Ari*_*oon 6

我以同样的方式扩展了 Array 并在 sa 派对使用for i in ...它循环时遇到了一个大问题。现在您无法控制所有第三方代码,这些错误可能会变得非常烦人,所以我建议使用更好的 aprocach:

interface Array<T> {
   crandom(): T;
}

/** Retrieve a random element from the list */
 Object.defineProperty(Array.prototype, 'crandom', { value: function() {

    let index = Math.floor(Math.random() * this.length);

    return this[index];
}
});
Run Code Online (Sandbox Code Playgroud)

现在通过使用Object.defineProperty您的新属性不会被枚举并且是安全的。上面的代码几乎从数组中给出了一个随机元素。我也做了另一个从数组中弹出一个随机元素:

Object.defineProperty(Array.prototype, 'popRandom', { value: function() {

    let index = Math.floor(Math.random() * this.length);

    let result = this[index];
    this.splice(index, 1);

    return result;
}
});
Run Code Online (Sandbox Code Playgroud)

Object.defineProperty您获得更多的控制此创作,你也可以添加额外的限制。