在Typescript 2.8+中扩展内置类的原型 [英] 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
在全局名称空间中.
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
推荐答案
如果要在模块内部定义扩展,即包含顶级import
或export
的文件,则需要使用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屋!