TypeScript继承类重写同名方法参数不匹配报错的最佳实践
报错核心原因
TypeScript 要求子类重写父类方法时,方法签名必须和父类兼容,保证所有能调用父类方法的场景,都能正常调用子类的同名方法(符合里氏替换原则)。你当前父类game仅需1个字符串参数,子类的game要求必须传2个参数,就会出现签名不兼容的报错。
最佳处理方案(根据业务场景二选一)
方案1:兼容父类签名(适用需要保持继承关系、允许子类实例当作父类实例使用的场景)
把子类新增的参数改为可选参数,同时在方法内兼容无第二个参数的逻辑:
class A { game(a: string): string{ return a; } } class B extends A { // 第二个参数设为可选,兼容父类签名 game(c: string, b?: number): string{ if (b === undefined) { // 只传一个参数时走父类逻辑 return super.game(c); } return c + ' ' + b.toString(); } } let a = new A(); console.log(a.game('Name')); // 输出 Name let b = new B(); console.log(b.game('Surname', 1986)); // 输出 Surname 1986 // 同时也支持父类的调用方式,符合里氏替换原则 console.log(b.game('Test')); // 输出 Test
方案2:调整方法设计(适用子类方法和父类逻辑差异大、不需要兼容父类调用场景)
如果你确定子类的game方法必须接收两个参数,本质上说明这个方法和父类的game已经不是同一个功能,违反了继承的设计原则,直接给子类的方法换个名字即可,不需要重写父类方法:
class A { game(a: string): string{ return a; } } class B extends A { // 自定义新方法名,不重写父类game gameWithInfo(c: string, b: number): string{ return c + ' ' + b.toString(); } } let a = new A(); console.log(a.game('Name')); let b = new B(); console.log(b.gameWithInfo('Surname', 1986)); // B的实例还能正常调用继承来的game方法 console.log(b.game('Test'));
注意:不建议用类型断言强制跳过TS校验,那样会埋下运行时隐患,比如把B实例赋值给A类型变量后调用game方法只传一个参数,就会出现运行时异常。
内容的提问来源于stack exchange,提问作者Michalis
相关产品推荐
相关产品推荐

