在Typescript 2.8+中扩展内置类的原型 [英] Extending the prototype of a built-in class in Typescript 2.8+

查看:94
本文介绍了在Typescript 2.8+中扩展内置类的原型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这不起作用

interface String {
    contains(s:string):boolean;
}
String.prototype.contains=(s:string):boolean=>this.indexOf(s)!==-1;

因为Property 'contains' does not exist on type 'String'

这有点令人惊讶,因为添加它是接口声明的全部要点. http://www.typescriptlang.org/docs/handbook/declaration-merging. html 表示上述代码是合法的.据我通过检查lib.es2015.wellknown.d.ts可以知道,String在全局名称空间中.

This is a bit of a surprise since adding it was the entire point of the interface declaration. http://www.typescriptlang.org/docs/handbook/declaration-merging.html suggests that the above code is legal. String is in the global namespace as far as I can tell by examining lib.es2015.wellknown.d.ts.

解决这个问题的正确方法是什么?阅读Aluan Haddad的扩展在全球范围内公开的第三方模块我这样改写

What's the right way to go about this? After reading Aluan Haddad's Extending third party module that is globally exposed I rewrote like this

declare global {
    interface String {
        contains(s: string): boolean;
    }
}
String.prototype.contains=(s:string):boolean=>this.indexOf(s)!==-1;

,并且界面更改现在是正确的.但是现在'this' implicitly has type 'any' because it does not have a type annotation.

and the interface change is now correct. But now 'this' implicitly has type 'any' because it does not have a type annotation.

进一步的注释this可以使用函数语法明确输入.

Per further comments this can be explicitly typed using function syntax.

String.prototype.contains = function (this: string, s:string):boolean { 
    return this.indexOf(s)!==-1; 
};

还应注意,在调查过程中,我发现contains是用名称includes实现的,并在lib.es2015.core.d.ts

It should also be noted that in the course of this investigation I discovered that contains is implemented with the name includes and is declared in lib.es2015.core.d.ts

推荐答案

如果要在模块内部定义扩展,即包含顶级importexport的文件,则需要使用declare global块以扩大全局范围.否则,您声明的接口将不会合并到全局数组接口中,因为它像其他任何声明一样在模块本地.声明全局语法专门用于覆盖此用例.

If you're defining the augmentation inside of a module, that is a file containing a top-level import or export then you need to use a declare global block in order to augment the global scope. Otherwise, the interface that you declare will not be merged into the global array interface because it's local to the module like any other declaration would be. The declare global syntax is specifically to cover this use case.

此外,在定义实际方法时,如果方法本身是根据this定义的,则不能使用arrow函数,因为Arrow函数具有静态作用域this,而动态this则需要方法.

Furthermore, when you define the actual method you can't use an arrow function if the method itself is defined in terms of this because Arrow functions have a statically scope this while a dynamic this is needed for methods.

放在一起

//  this is a module
export {}

declare global {
  interface String {
    contains(other: string): boolean;
  }
} 

String.prototype.contains = function (other) {
  return this.indexOf(other) and !== -1;
};

请注意,无论要扩充的类型是类还是接口,都需要在上述接口中声明成员,因为接口可以与类合并,接口可以与接口合并,但类不能合并.

Note that whether the type being augmented is a class or an interface, the member needs to be declared in an interface as above because interfaces can merge with classes and interfaces can merge with interfaces but classes do not merge.

这篇关于在Typescript 2.8+中扩展内置类的原型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆