我想为继承创建一个非常通用的类,但我遇到了一些问题。
到目前为止,我有两个服务类(称为Service_A和Service_B),它们用于相同的目的,除了 Service_A 与 Class_A 一起工作,Service_B 与 Class_B 一起工作。这些类非常相似,现在,只有提到的类型(Class_A和Class_B)在它们之间有所不同。
我想做的是在一个更通用的类(EntityService)中编写一次代码,Service_A和Service_B将从这个类继承。
然而,我还没有设法找到一种方法,让Entity的方法使用Service_A和Service_B将覆盖的“泛型”类/类型,以便所有代码都可以转移,而不必覆盖所有方法或在每个方法调用时指定类型。
例如,EntityService看起来是这样的:
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;
}
static fromInterface(entity: Entity, id: string): EntityObj {
return new this(id, entity.param_1, entity.param_2);
}
}
export class EntityService {
/* What I'd like to be able to use:
* static classTypeAlias: EntityObj;
* static interfaceTypeAlias: Entity;
*/
constructor(private readonly actor: Actor) { }
getEntityObjs(): Observable<EntityObj[]> | null {
let data: Entity = this.actor.getData()
let entityObjs: Observable<EntityObj[]> = this.actor.getObservable<EntityObj, Entity>(data);
return entityObjs;
}
getObjFromInterface(): EntityObj {
let entityObj: EntityObj = EntityObj.fromInterface(this.actor.getData(), "foo");
return entityObj;
}
update(entity: EntityObj): void { let entityDoc = this.actor.doStuff<Entity>(entity); }
}
让Service_A能够调用update()之类的方法,其参数隐式地为“Class_A”或getEntityObjs()类型,并且隐式地返回“Observable〈Class_A[]〉”类型的内容|空”
我试着查看泛型类型,但在尝试访问属性时,如果不从EntityObj扩展它们,就无法使用它们,或者使用与类关联的泛型类型的值(如class EntityService<classType, interfaceType> {...}
)来指定args / returns的类型。
任何指向任何一种解决方案/适当的技术将是非常受欢迎的
1条答案
按热度按时间tsm1rwdh1#
如果您希望能够参数化
EntityService
的子类,以便它们具有不同的类型,您将调用classTypeAlias
和interfaceTypeAlias
,最直接的方法是在对应于这些类型的类型参数中创建EntityClass
generic;我们分别将它们命名为C
和I
:因此,首先要做的是将
EntityObj
的每个示例都替换为C
,并将Entity
替换为I
:除了两个错误之外,这基本上是可行的。
下面的错误发生是因为我们调用
doStuff<I>(entity)
,但是传递了一个C
类型的entity
而不是I
。这可以通过约束C
扩展I
来解决,但是如果你不想这样做,我们可以改变它,这样我们就可以调用doStuff<C>(entity)
:最上面的错误发生是因为我们用
C
替换了EntityObj
* 类构造函数 *,C
只是一个 * 类型 *。糟糕,这意味着EntityService
需要访问适当类型的类构造函数值。由于代码使用了fromInterface(data, str)
,其中data
的类型为I
,并且它返回了C
类型的值,然后我们需要访问一个{fromInterface(data: I, str: string): C}
类型的值。我们怎么才能得到它呢?好吧,一个合理的地方是,当你构造EntityService
的示例时,需要传递这样一个对象。这导致我们得到这个版本:现在可以编译了。那么我们怎么用它呢?
好吧,我们可以用特定的
C
和I
类型参数来子类化它,并在子类构造函数中传递ctor
。像这样:所以
C
被指定为EntityObj
,I
被指定为Entity
,而ctor
对象只是EntityObj
构造函数。我们可以使用它:看起来不错。如果有关系,这里有一个不同的子类:
看起来也不错。
毫无疑问,还有其他方法可以实现这一点,例如子类不需要显式指定
C
和I
,或者EntityService
是一个类工厂函数,您只需编写class MainEntityService extends EntityService(EntityObj) {}
,等等,但这种方法有效,所以我不会离题,以包括每一种可能的方法。Playground链接到代码