使用TypeScript扩展Object.prototype

时间:2013-05-29 11:51:23

标签: javascript object interface prototype 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();
}

您可能希望直接在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

要么这只是一个TypeScript错误(我知道它仍处于开发阶段,因此很多错误需要解决,我已经在CodePlex上说明了其中的一些),或者,我遗漏了一些东西。 / p>

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

如果它不是TypeScript错误,我该如何解决?

3 个答案:

答案 0 :(得分:16)

我曾经有过:

// 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;
}

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

interface Array {
    contains(obj: Object): boolean;
}

谢谢basarat

答案 1 :(得分:10)

此错误已在TS 0.9.0 alpha中修复,如下所示: no error in Ts 0.9.0 alpha

游乐场仍在运行0.8.3。

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

如果你运行它。第一次加载时您将看不到该错误。 Try It

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

答案 2 :(得分:2)

我以相同的方式扩展了阵列,当派对使用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]; } }); 循环时,我遇到了一个大问题。现在你无法控制每个第三方代码,这些错误可能真的很烦人,所以我建议一个更好的aprocach:

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; } }); 您的新属性将不会被枚举,并且是安全的。上面的代码几乎给出了数组中的随机元素。我做了另一个,它从数组中弹出一个随机元素:

Object.defineProperty

fs.readFile("test.txt", function(err, data) { console.log( data ); }); 您可以更好地控制此创建,也可以添加其他限制。