TypeScript 2.8+扩展内置String类原型报错问题咨询
问题出在箭头函数和(可能的)模块作用域!
你遇到的这个报错,核心原因有两个,咱们一个个说清楚:
1. 箭头函数的this绑定完全不对
你用箭头函数给String.prototype.contains赋值,可箭头函数没有自己的this上下文——它会直接捕获外层作用域的this,在这里要么是全局对象(如果是纯脚本文件),要么是模块的this(如果在模块环境里),完全不是调用contains时的String实例。
TypeScript的类型检查器能敏锐察觉到这一点:你声明的接口里,contains方法的this应该是String类型,但箭头函数的this根本不符合这个要求,所以它就不认这个实现,依然报错说contains不存在于String类型上。
把箭头函数换成普通函数就解决了:普通函数作为原型方法调用时,this会自动绑定到调用它的String实例,类型完全匹配。
2. 模块环境下的全局接口合并问题
如果你的代码是在模块里(比如有import/export语句),那直接声明的interface String会被当成模块私有的接口,不会和全局的String接口合并。这时候需要把接口声明包裹在declare global块里,明确告诉TypeScript你要扩展全局的String类型。
修正后的代码示例
情况一:非模块环境(纯脚本文件,无import/export)
interface String { contains(s: string): boolean; } // 换成普通函数,this指向调用它的String实例 String.prototype.contains = function(s: string): boolean { return this.indexOf(s) !== -1; };
情况二:模块环境(有import/export)
// 用declare global包裹,明确扩展全局String接口 declare global { interface String { contains(s: string): boolean; } } String.prototype.contains = function(s: string): boolean { return this.indexOf(s) !== -1; }; export {}; // 标记当前文件为模块(如果没有其他export内容的话)
另外提一句:其实ES6已经内置了String.prototype.includes方法,功能和你写的contains完全一样,如果你不是为了学习原型扩展的逻辑,直接用includes更省心~
内容的提问来源于stack exchange,提问作者Peter Wone
相关产品推荐
相关产品推荐

