在 Typescript 2.8+ 中扩展内置 class 的原型

Extending the prototype of a built-in class in 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 在全局命名空间中

解决这个问题的正确方法是什么?看完Aluan Haddad的我改写成这样

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.

根据进一步的评论 this 可以使用函数语法明确键入。

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

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

中声明

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

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

放在一起

//  this is a module
export {}

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

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

请注意,无论被扩充的类型是class还是接口,都需要像上面那样在接口中声明成员,因为接口可以与classes合并,接口可以与class合并接口,但 classes 不合并。