TypeScript如何实现子类未调用父类被重写方法时抛出错误
实现方案
可以通过父类内置私有调用标记+构造函数拦截目标方法的方式实现运行时校验,只要子类重写方法时未调用父类对应方法就会自动抛出错误,完整实现代码如下:
class AAA { // JS原生私有属性,仅父类内部可访问,无法被子类修改 #isSuperCreateCalled = false; create() { this.#isSuperCreateCalled = true; // 父类create的原有业务逻辑写在这里 } constructor() { // 保存子类重写后的create方法 const originalCreate = this.create.bind(this); // 拦截实例的create方法,注入校验逻辑 this.create = () => { // 调用前先重置标记位 this.#isSuperCreateCalled = false; // 执行子类重写的create逻辑 originalCreate(); // 校验父类方法是否被调用 if (!this.#isSuperCreateCalled) { throw new Error('子类重写create方法时必须调用super.create()'); } } } } class BB extends AAA { // TS 4.3+ 支持override关键字明确标记重写父类方法 override create() { // 取消下面这行的注释即可避免报错 // super.create() console.log('子类的create逻辑'); } } // 测试代码 const b = new BB(); b.create(); // 未调用super.create时直接抛出错误
扩展优化
如果需要对多个父类方法实现同类校验,可以把上述逻辑抽成通用的方法装饰器,避免重复写校验代码:
// 通用装饰器,修饰需要强制子类调用super的父类方法 function RequireSuperCall() { return function (target: any, methodName: string, descriptor: PropertyDescriptor) { const originalParentMethod = descriptor.value; // 用Symbol生成唯一标记,避免属性名冲突 const callFlag = Symbol(`super_called_${methodName}`); // 包装父类方法,调用时设置标记 descriptor.value = function (...args: any[]) { // @ts-ignore this[callFlag] = true; return originalParentMethod.apply(this, args); }; // 包装父类构造函数,自动拦截子类重写的方法 const originalConstructor = target.constructor; target.constructor = function (...constructorArgs: any[]) { originalConstructor.apply(this, constructorArgs); // @ts-ignore const originalChildMethod = this[methodName].bind(this); // @ts-ignore this[methodName] = (...methodArgs: any[]) => { // @ts-ignore this[callFlag] = false; originalChildMethod.apply(this, methodArgs); // @ts-ignore if (!this[callFlag]) { throw new Error(`重写${methodName}方法时必须调用super.${methodName}()`); } } } } } // 使用示例 class AAA { @RequireSuperCall() create() { console.log('父类create逻辑'); } @RequireSuperCall() destroy() { console.log('父类destroy逻辑'); } }
补充说明
上述方案均为运行时检测,TypeScript本身没有原生的编译期校验能力,如果你需要在开发阶段就收到提示,可以配置ESLint的@typescript-eslint/no-missing-super-call规则(需要安装对应插件),配合运行时检测实现双重保障。
内容的提问来源于stack exchange,提问作者cchorseless
相关产品推荐
相关产品推荐

