如何使用 T 在泛型函数中创建泛型对象?
How to create a generic Object in a generic function using T?
早上好,
问题
我正在使用 Typescript 创建一个 angular 应用程序。我想创建一个方法,该方法采用类型参数并将其传递给工厂以使用 cTor 创建一个新实例。如果我知道类型,那效果很好,但如果我不知道,则效果不佳。例如,这有效(第 4 行):
list<T extends IMdmObject>(page = 1, pageSize = 50) {
this.http.get<T[]>(this.uri).pipe(tap(
_mdmObject => {
let _ = _mdmObject.map(x => this.createInstance<MdmCountry>(MdmCountry, x));
this.mdmStoreController.dispatch(this.ressource, _mdmObject, StoreAction.MERGE);
}
)).subscribe();
}
createInstance<T extends AbstractMdmStorable>(concrete: new(mdmObject: IMdmObject) => T, init: IMdmObject): T {
return new concrete(init);
}
但是如果我改用 T 它就不起作用了:
list<T extends IMdmObject>(page = 1, pageSize = 50) {
this.http.get<T[]>(this.uri).pipe(tap(
_mdmObject => {
let _ = _mdmObject.map(x => this.createInstance<T>(T, x));
this.mdmStoreController.dispatch(this.ressource, _mdmObject, StoreAction.MERGE);
}
)).subscribe();
}
createInstance<T extends AbstractMdmStorable>(concrete: new(mdmObject: IMdmObject) => T, init: IMdmObject): T {
return new concrete(init);
}
我知道 Typescript 将代码转换为 js,并且 T 在该过程之后不可用。但是有没有办法创建一个扩展 AbstractMdmStorable 的通用实例?
备注
- AbstractMdmStorable 实现 IMdmObject
- MdmCountry 扩展了 AbstractMdmStorable
可以将T
用作类型,但不能将其用作值。所以你不能在此处将 T
作为函数参数传递 this.createInstance<T>(T, x))
.
这可以通过依赖注入来解决。您要做的是传递 class(class 本身,而不是 class 的实例)。但与其将其作为 createInstance
函数的参数传递,我建议将 class 存储为工厂的实例变量。在工厂的构造函数中,传入 class 以创建该对象类型的工厂实例。
我不明白你这里的所有类型,但它看起来像这样:
class MyFactory<T extends IMdmObject> {
constructor(private readonly concrete: new (mdmObject: IMdmObject) => T) {
}
list<T extends IMdmObject>(page = 1, pageSize = 50) {
this.http.get<T[]>(this.uri).pipe(tap(
_mdmObject => {
let _ = _mdmObject.map(x => this.createInstance(x));
this.mdmStoreController.dispatch(this.ressource, _mdmObject, StoreAction.MERGE);
}
)).subscribe();
}
createInstance(init: IMdmObject): T {
return new this.concrete(init);
}
}
早上好,
问题
我正在使用 Typescript 创建一个 angular 应用程序。我想创建一个方法,该方法采用类型参数并将其传递给工厂以使用 cTor 创建一个新实例。如果我知道类型,那效果很好,但如果我不知道,则效果不佳。例如,这有效(第 4 行):
list<T extends IMdmObject>(page = 1, pageSize = 50) {
this.http.get<T[]>(this.uri).pipe(tap(
_mdmObject => {
let _ = _mdmObject.map(x => this.createInstance<MdmCountry>(MdmCountry, x));
this.mdmStoreController.dispatch(this.ressource, _mdmObject, StoreAction.MERGE);
}
)).subscribe();
}
createInstance<T extends AbstractMdmStorable>(concrete: new(mdmObject: IMdmObject) => T, init: IMdmObject): T {
return new concrete(init);
}
但是如果我改用 T 它就不起作用了:
list<T extends IMdmObject>(page = 1, pageSize = 50) {
this.http.get<T[]>(this.uri).pipe(tap(
_mdmObject => {
let _ = _mdmObject.map(x => this.createInstance<T>(T, x));
this.mdmStoreController.dispatch(this.ressource, _mdmObject, StoreAction.MERGE);
}
)).subscribe();
}
createInstance<T extends AbstractMdmStorable>(concrete: new(mdmObject: IMdmObject) => T, init: IMdmObject): T {
return new concrete(init);
}
我知道 Typescript 将代码转换为 js,并且 T 在该过程之后不可用。但是有没有办法创建一个扩展 AbstractMdmStorable 的通用实例?
备注
- AbstractMdmStorable 实现 IMdmObject
- MdmCountry 扩展了 AbstractMdmStorable
可以将T
用作类型,但不能将其用作值。所以你不能在此处将 T
作为函数参数传递 this.createInstance<T>(T, x))
.
这可以通过依赖注入来解决。您要做的是传递 class(class 本身,而不是 class 的实例)。但与其将其作为 createInstance
函数的参数传递,我建议将 class 存储为工厂的实例变量。在工厂的构造函数中,传入 class 以创建该对象类型的工厂实例。
我不明白你这里的所有类型,但它看起来像这样:
class MyFactory<T extends IMdmObject> {
constructor(private readonly concrete: new (mdmObject: IMdmObject) => T) {
}
list<T extends IMdmObject>(page = 1, pageSize = 50) {
this.http.get<T[]>(this.uri).pipe(tap(
_mdmObject => {
let _ = _mdmObject.map(x => this.createInstance(x));
this.mdmStoreController.dispatch(this.ressource, _mdmObject, StoreAction.MERGE);
}
)).subscribe();
}
createInstance(init: IMdmObject): T {
return new this.concrete(init);
}
}