GregRos..
79
此答案适用于TypeScript 1.8+.这类问题有很多其他答案,但它们似乎都涵盖旧版本.
在TypeScript中扩展原型有两个部分.
第1部分 - 声明
声明新成员,以便它可以传递类型检查.您需要声明一个与要修改的构造函数/类同名的接口,并将其放在正确的声明的命名空间/模块下.这称为范围扩充.
以这种方式扩展模块只能在特殊的声明.d.ts文件*中完成.
//in a .d.ts file:
declare global {
interface String {
padZero(length : number) : string;
}
}
外部模块中的类型具有包含引号的名称,例如"bluebird".
全球类型,如模块名称Array和String是global,没有任何报价.但是,在许多版本的TypeScript中,您可以完全放弃模块声明并直接声明接口,具有以下内容:
declare interface String {
padZero(length : number) : string;
}
在1.8之前的某些版本中也是这种情况,在2.0之后的某些版本中也是如此,例如最新版本2.5.
请注意,除了文件中的declare语句之外,您不能拥有任何内容.d.ts,否则它将无效.
这些声明被添加到包的环境范围中,因此它们将应用于所有TypeScript文件,即使您从不直接import或///
*从技术上讲,你可以通过这个限制并将声明放在常规.ts文件中,但这会导致编译器出现一些挑剔的行为,并且不建议这样做.
第2部分 - 实施
第2部分实际上是实现成员并将其添加到它应该存在的对象中,就像在JavaScript中一样.
String.prototype.padZero = function (this : string, length: number) {
var s = this;
while (s.length < length) {
s = '0' + s;
}
return s;
};
请注意以下几点:
String.prototype而不仅仅是String,它是String构造函数,而不是它的原型.
我使用显式function而不是箭头函数,因为a function将正确地this从调用它的位置接收参数.箭头函数将始终使用this与其声明的位置相同的内容.有一次我们不希望发生这种情况是在扩展原型时.
显式this,所以编译器知道this我们期望的类型.此部分仅适用于TS 2.0+.this如果您正在编译1.8-,请删除注释.没有注释,this可以隐式输入any.
导入JavaScript
在TypeScript中,declare构造将成员添加到环境范围,这意味着它们出现在所有文件中.为了确保第2部分的实现已连接,import文件就在应用程序的开头.
您导入文件如下:
import '/path/to/implementation/file';
没有任何进口.您也可以从文件中导入某些内容,但不需要导入在原型上定义的函数.
此外,如果您尝试将其放在2.5.1中的`.d.ts`文件中,则会出现以下错误:`全局范围的扩充只能直接嵌套在外部模块或环境模块声明中. (5认同)