You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 13:39:03