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

如何实现可覆写类型属性的通用服务类以支持继承复用?

解决方案:创建可继承的泛型实体服务类

核心思路

将EntityService改造为泛型类,通过泛型参数绑定实体类(如Class_A)和对应的接口类型(如Entity_A),同时通过构造函数注入实体类的构造函数,实现父类逻辑复用,子类仅需指定类型即可自动获得匹配的方法签名。

修改后的完整代码

declare class Observable<T> { x: T }

declare class Actor {
    doStuff<T>(anything: T): T[];
    getData<I>(): I;
    getObservable<U, I>(data: I): Observable<U[]>;
}

interface Entity {
    param_1: number,
    param_2: number,
}

class EntityObj {
    id: string;
    param_1: number;
    param_2: number;

    constructor(id: string, param_1: number, param_2: number) {
        this.id = id;
        this.param_1 = param_1;
        this.param_2 = param_2;
    }
}

// 定义构造函数类型约束,确保实体类具备fromInterface静态方法
type EntityObjConstructor<EntityType extends Entity, EntityObjType extends EntityObj> = {
  new(id: string, param_1: number, param_2: number, ...args: any[]): EntityObjType;
  fromInterface(entity: EntityType, id: string): EntityObjType;
};

export class EntityService<EntityObjType extends EntityObj, EntityType extends Entity> {
  private readonly entityCtor: EntityObjConstructor<EntityType, EntityObjType>;

  constructor(
    private readonly actor: Actor,
    entityCtor: EntityObjConstructor<EntityType, EntityObjType>
  ) {
    this.entityCtor = entityCtor;
  }

  getEntityObjs(): Observable<EntityObjType[]> | null {
    const data = this.actor.getData<EntityType>();
    return this.actor.getObservable<EntityObjType, EntityType>(data);
  }

  getObjFromInterface(): EntityObjType {
    const entity = this.actor.getData<EntityType>();
    return this.entityCtor.fromInterface(entity, "foo");
  }

  update(entity: EntityObjType): void {
    // 类型断言:EntityObjType包含EntityType的所有属性,转换安全
    const entityDoc = this.actor.doStuff<EntityType>(entity as unknown as EntityType);
  }
}

// ------------------------------
// 示例子类:Service_A 与 Class_A
// ------------------------------
interface Entity_A extends Entity {
  param_3: string;
}

class Class_A extends EntityObj {
  param_3: string;

  constructor(id: string, param_1: number, param_2: number, param_3: string) {
    super(id, param_1, param_2);
    this.param_3 = param_3;
  }

  static fromInterface(entity: Entity_A, id: string): Class_A {
    return new this(id, entity.param_1, entity.param_2, entity.param_3);
  }
}

export class Service_A extends EntityService<Class_A, Entity_A> {
  constructor(actor: Actor) {
    super(actor, Class_A);
  }
}

// ------------------------------
// 示例子类:Service_B 与 Class_B
// ------------------------------
interface Entity_B extends Entity {
  param_4: boolean;
}

class Class_B extends EntityObj {
  param_4: boolean;

  constructor(id: string, param_1: number, param_2: number, param_4: boolean) {
    super(id, param_1, param_2);
    this.param_4 = param_4;
  }

  static fromInterface(entity: Entity_B, id: string): Class_B {
    return new this(id, entity.param_1, entity.param_2, entity.param_4);
  }
}

export class Service_B extends EntityService<Class_B, Entity_B> {
  constructor(actor: Actor) {
    super(actor, Class_B);
  }
}

关键细节说明

  1. 泛型约束:

    • EntityObjType extends EntityObj:确保实体类必须继承基础EntityObj
    • EntityType extends Entity:确保接口必须继承基础Entity
  2. 构造函数注入:
    父类通过构造函数接收实体类的构造函数引用,这样可以调用子类实体的fromInterface静态方法,避免硬编码基础类。

  3. 自动类型匹配:
    子类继承时指定泛型类型后,所有方法的参数和返回值会自动绑定到对应类型:

    • Service_A.update() 自动接收Class_A类型参数
    • Service_A.getEntityObjs() 自动返回Observable<Class_A[]>类型
  4. 类型转换安全:
    update方法中的类型断言entity as unknown as EntityType是安全的,因为EntityObjType继承自EntityObj(包含Entity的所有属性),且EntityType是对应实体类的接口,属性完全匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 00:47:49