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

继承Common类并设属性为必填:Required工具类型报错求助

问题原因

Required<T>是TypeScript的类型工具,仅作用于类型层面,而类的extends关键字后面需要的是一个类的构造函数(即“值”层面的实体),不是类型,所以直接写extends Required<Common>会报错“Required未定义”。

简便实现方案

方案一:手动定义必填版基类(最直观)

如果Common的属性不多,直接创建一个继承自Common的子类,将所有可选属性显式声明为必填,同时复用Common的构造逻辑:

class Common {
  id?: number;
  name?: string;

  constructor(props?: Partial<Common>) {
    Object.assign(this, props);
  }

  // Common的其他方法
  commonMethod() {
    console.log("这是Common的通用方法");
  }
}

// 定义必填版基类
class RequiredCommon extends Common {
  id: number;
  name: string;

  constructor(props: Required<Common>) {
    super(props);
    // 显式赋值确保类型合规
    this.id = props.id;
    this.name = props.name;
  }
}

class A extends Common {
  // A的自定义属性/方法
  extraPropA?: boolean;
}

class B extends RequiredCommon {
  // B的自定义属性/方法
  extraPropB: string;

  constructor(props: Required<Common> & { extraPropB: string }) {
    super(props);
    this.extraPropB = props.extraPropB;
  }
}

// 使用示例
const a = new A({ id: 1 }); // 允许只传部分属性
const b = new B({ id: 2, name: "测试", extraPropB: "自定义" }); // 必须传全所有必填属性

方案二:用装饰器自动生成必填基类(适合属性较多的场景)

如果Common的属性很多,手动写RequiredCommon太繁琐,可以用类装饰器封装逻辑,同时通过类型约束确保编译时校验:

// 装饰器:将基类的可选属性转为必填(编译时+运行时校验)
function MakeRequired<T extends new (...args: any[]) => any>(Base: T) {
  return class extends Base {
    constructor(...args: ConstructorParameters<typeof Base>) {
      super(...args);
      // 运行时校验所有Common的属性是否已赋值
      const requiredKeys = Object.keys(new Base()) as Array<keyof InstanceType<T>>;
      for (const key of requiredKeys) {
        if (this[key] === undefined) {
          throw new Error(`属性 ${String(key)} 为必填项`);
        }
      }
    }
  } as new (props: Required<InstanceType<T>>) => InstanceType<T>;
}

class Common {
  id?: number;
  name?: string;
  desc?: string;

  constructor(props?: Partial<Common>) {
    Object.assign(this, props);
  }
}

// 生成必填版基类
const RequiredCommon = MakeRequired(Common);

class A extends Common {
  // ...
}

class B extends RequiredCommon {
  // ...
}

// 编译时会报错,运行时也会抛出异常
// const b = new B({ id: 1 });
// 正确用法
const b = new B({ id: 1, name: "测试", desc: "描述" });

方案三:类型约束+组合(无需继承的场景)

如果不需要完全继承Common的方法,只是复用属性类型,可以直接在B类中用Required<Common>做类型约束,通过组合复用Common的逻辑:

// 先定义接口复用属性类型
interface ICommon {
  id?: number;
  name?: string;
}

class Common implements ICommon {
  id?: number;
  name?: string;

  constructor(props?: Partial<ICommon>) {
    Object.assign(this, props);
  }

  commonMethod() {
    return "通用方法返回值";
  }
}

class A extends Common {
  // ...
}

class B implements Required<ICommon> {
  id: number;
  name: string;
  // 组合Common实例复用方法
  private commonInstance = new Common();

  constructor(props: Required<ICommon>) {
    this.id = props.id;
    this.name = props.name;
  }

  // 复用Common的方法
  useCommonMethod() {
    return this.commonInstance.commonMethod();
  }
}

内容的提问来源于stack exchange,提问作者user19024399

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 13:05:25