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

如何在TypeScript中设置子类属性不同的继承类?

用泛型基类解决子类属性差异化的类型约束问题

核心解决方案:泛型基类绑定子类属性类型

将BaseClass定义为泛型类,让它与子类的属性类型关联,这样create和update方法就能自动适配不同子类的属性结构,实现严格的类型校验。

第一步:重构泛型基类

class BaseClass<T> {
  // 静态create方法:约束props为子类属性类型,返回子类实例
  static create<T>(this: new () => BaseClass<T>, props: T): BaseClass<T> {
    const instance = new this();
    Object.assign(instance, props);
    return instance;
  }

  // 实例update方法:接收部分属性参数(Partial<T>自动生成可选属性)
  update(props: Partial<T>): void {
    Object.assign(this, props);
  }
}

这里的this: new () => BaseClass<T>是构造函数类型约束,确保create方法被子类调用时,this指向子类的构造函数,从而返回正确的子类实例类型,避免出现基类实例的类型偏差。

第二步:子类继承时绑定属性类型

子类继承BaseClass时,传入对应的属性类型作为泛型参数,同时保持类自身的属性定义:

type SubClassOneProps = {
  firstName: string
  lastName: string
}
class SubClassOne extends BaseClass<SubClassOneProps> {
  firstName!: string
  lastName!: string
}

type SubClassTwoProps = {
  streetName: string
  streetNumber: number
}
class SubClassTwo extends BaseClass<SubClassTwoProps> {
  streetName!: string
  streetNumber!: number
}

第三步:验证类型支持

现在调用create和update时,TypeScript会自动校验参数的类型和结构:

// ✅ 类型正确,自动提示属性字段
const obj1 = SubClassOne.create({firstName: "Bob", lastName: "Doe"});
// ✅ 支持部分更新,只传入需要修改的属性
obj1.update({lastName: "Smith"});

// ✅ 自动适配SubClassTwo的属性结构
const obj2 = SubClassTwo.create({streetName: "Sunset Blvd", streetNumber: 100});
obj2.update({streetNumber: 200});

// ❌ 类型错误:缺少必填的streetNumber参数
SubClassTwo.create({streetName: "Sunset Blvd"});
// ❌ 类型错误:传入了子类不存在的属性
obj1.update({age: 30});

后续元数据需求的提前准备

如果要给属性添加「是否公开」的元数据,可以用TypeScript装饰器实现:

  1. 定义一个装饰器标记属性的公开状态
  2. 在基类中实现toJSON()方法,根据元数据筛选公开属性返回

示例思路(核心逻辑):

// 定义装饰器标记公开属性
function Public() {
  return (target: any, propertyKey: string) => {
    Reflect.defineMetadata('public', true, target, propertyKey);
  };
}

class BaseClass<T> {
  // ... 原有create、update方法

  toJSON(): Partial<T> {
    const result: Record<string, any> = {};
    // 遍历实例属性,筛选标记为公开的字段
    for (const key of Object.keys(this)) {
      if (Reflect.getMetadata('public', this, key)) {
        result[key] = this[key];
      }
    }
    return result as Partial<T>;
  }
}

// 子类中使用装饰器标记公开属性
class SubClassOne extends BaseClass<SubClassOneProps> {
  @Public()
  firstName!: string;
  lastName!: string; // 未标记则视为非公开字段
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 00:31:02