不使用class时如何让Object.create()古典继承在TypeScript中正常运行
问题原因
你遇到的'this' implicitly has type 'any' because it does not have a type annotation报错,本质是开启noImplicitThis编译选项时,TypeScript 无法自动推导普通构造函数、原型方法中this的类型,你之前用this: any的写法虽然能绕过校验,但完全丢失了类型安全,不是推荐解法。
正确实现方式
不用class实现ES5风格的原型继承,只需要给实例对象定义明确的类型接口,给构造函数、原型方法显式标注this类型,再对原型继承的部分做符合运行时实际结构的类型断言即可,全程不需要用到any。
完整可运行的TS代码如下:
// 定义父类Shape的实例类型 interface Shape { x: number; y: number; move(x: number, y: number): void; } // 定义子类Rectangle的实例类型,继承Shape所有属性/方法 interface Rectangle extends Shape { // 可在此处扩展Rectangle独有的属性、方法,比如width、height、resize()等 } // 父类构造函数 function Shape(this: Shape) { this.x = 0; this.y = 0; } // 父类原型方法 Shape.prototype.move = function (this: Shape, x: number, y: number) { this.x += x; this.y += y; console.info('Shape moved.'); }; // 子类构造函数 function Rectangle(this: Rectangle) { // 调用父类构造函数,this类型兼容,无报错 Shape.call(this); } // 子类继承父类原型,做类型断言匹配TS对原型的类型校验 Rectangle.prototype = Object.create(Shape.prototype) as Rectangle; // 将构造函数指回子类,避免原型链上constructor指向错误 Rectangle.prototype.constructor = Rectangle; const rect = new Rectangle(); console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle); // true console.log('Is rect an instance of Shape?', rect instanceof Shape); // true rect.move(1, 1); // 正常输出'Shape moved.',同时有完整类型提示
关键点说明
- 接口定义完全匹配运行时的对象结构:
Shape接口明确了实例上的x、y属性和move方法,TS可以基于这个类型做所有类型检查。 - 所有函数的
this都显式标注为对应实例类型,既解决了隐式any的报错,又保留了完整的类型提示:比如给move传非数字参数、访问实例上不存在的属性时,TS会直接抛出类型错误。 Object.create后的类型断言是安全的:因为运行时Rectangle.prototype确实是继承自Shape.prototype的对象,和我们定义的Rectangle实例类型结构一致,不会出现类型和实际运行时不匹配的问题。- 如果需要给子类扩展独有属性/方法,直接在
Rectangle接口中补充类型定义,再在构造函数、原型上实现即可,TS会自动做类型校验。
内容的提问来源于stack exchange,提问作者user2747609
相关产品推荐
相关产品推荐

