使用 TypeScript 扩展 Object.prototype

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16813118/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 01:04:59  来源:igfitidea点击:

Extending Object.prototype with TypeScript

javascriptobjectinterfaceprototypetypescript

提问by Matthew Layton

I am currently working on a TypeScript API, which requires some additional features binding to the Object prototype (Object.prototype).

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

Consider the following code:

考虑以下代码:

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();
}

You might want to try this directly at the Playground.

您可能想直接在Playground尝试此操作。

As you can see, I have a class called Foo(not the actual object name I will be using). I have also extended the Objectinterface to include two new functions. Finally I have implemented the functions against the prototype(these work in pure JavaScript, it's just TypeScript that complains).

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

Where I have annotated "//this is problematic..." TypeScript highlights this with a red squiggly, and shows the following error:

在我注释“ //这是有问题的...”的地方,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

Either this is just a TypeScript bug (I know it's still in development phase, so a lot of the bugs need ironing out, and I have illustrated some of these on CodePlex already), or, I'm missing something.

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

Why am I getting this issue?

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

If it's not a TypeScript bug, how can I fix this?

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

采纳答案by basarat

This bug is fixed in TS 0.9.0 alpha as you can see below: no error in Ts 0.9.0 alpha

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

The playground is still running 0.8.3.

Playground 仍在运行 0.8.3。

This basically happens because methods on some key interfaces ( Object, Number, String ) etc get cached as a performance optimization.

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

If you run this. The first time it loads you will not see that error. Try It.

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

As soon as you make an edit to that code, the parser goes through the code again, and since it cached the old interface definition sees a duplicate function definition and then effectively blows up. The more edits you make to that file the more complicated the error statement will get.

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

回答by Tono Nam

I used to have:

我曾经有过:

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

in order to make that code compile with typescript I added the line:

为了使用打字稿编译该代码,我添加了以下行:

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

Thanks basarat!

谢谢basarat

回答by Arijoon

I have extended the Array the same way and faced a big problem when s a party was using for i in ...to loop over it. Now you can't control every third party code and these bugs could get really annoying so I suggest a better aprocach:

我以同样的方式扩展了 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];
}
});

Now by using Object.definePropertyyour new property won't be enumerated over and it is safe. The above code pretty much gives a random element from the array. I made another one too which pops a random element from array:

现在通过使用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;
}
});

with Object.definePropertyYou get more control over this creation and you can add additional restrictions too.

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