代码之家  ›  专栏  ›  技术社区  ›  Peter Wone

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

  •  2
  • Peter Wone  · 技术社区  · 7 年前

    这行不通

    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 表明上述代码是合法的。 String 通过检查 lib.es2015.wellknown.d.ts

    正确的方法是什么?读了Aluan Haddad的 Extending third party module that is globally exposed 我这样重写

    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

    1 回复  |  直到 7 年前
        1
  •  2
  •   Aluan Haddad Vikrant Kashyap    7 年前

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

    此外,当您定义实际方法时,如果方法本身是根据 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;
    };
    

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