【问题标题】:Extending the prototype of a built-in class in Typescript 2.8+在 Typescript 2.8+ 中扩展内置类的原型
【发布时间】:2018-10-06 13:16:50
【问题描述】:

这行不通

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的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.

进一步的 cmets this 可以使用函数语法显式键入。

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

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

【问题讨论】:

  • 可能不是,也许奥瑞莉亚在干扰。这可能是问题所在。
  • 我在这个答案stackoverflow.com/a/43674912/1915893中详细介绍了这个主题
  • 这不是 Aurelia,而是模块的使用。如果您在模块范围内,则需要包装接口声明以便将其合并到全局数组声明中。否则,您将定义一个名为 Array 的模块范围接口。有关完整的详细信息和示例,请参阅回答链接
  • 我看到了您的编辑,但我不明白这与上课与否有什么关系。随便写吧,和类没有任何关系。
  • 根据理解进行第二次阅读,我看到您确实顺便解释了它,但我认为这个答案要清楚得多。更重要的是,您已经解释了为什么它很重要。

标签: interface typescript2.0


【解决方案1】:

如果您在模块内部定义扩充,即包含顶级importexport 的文件,那么您需要使用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;
};

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-08
    相关资源
    最近更新 更多