我目前正在努力的挑战如下:
一些伪代码:
const result = api.call("get a model") // can be of model type: "One" "Two" ... "Ten" which all extends 'BaseModel'
// value can be one of these: "One" "Two" ... "Ten"
// will be a corresponding class for each 'modelType' which all extend a 'BaseClass'
const type:string = route.params.modelType
// createClass(type) - returns a class based on 'type' and 'result' is passed to its constructor
const newClass = new createClass(type)(result);
因此,我尝试根据字符串值动态创建类的新实例,使用构造函数中传递的模型来水合该类的属性,并将相同的模型传递给超类以水合类链上的属性。
问题是,当创建类并尝试在其构造函数中传递模型时,在将该对象传递给构造函数时出现可以理解的错误:
类型参数不可分配给类型参数。
我只是不确定如何解决它,或者是否可能?
这就是我目前所处的位置..
interface BaseModel {
name: string;
age: number
}
interface SubModel extends BaseModel {
color: string;
speed: number
}
interface SubModel2 extends BaseModel {
shoeSize: number;
height: number
}
class Base {
name = '';
age = 1;
constructor(model: BaseModel) {
this.name = model.name;
this.age = model.age;
}
}
class Sub extends Base {
color = ''
speed = 0;
constructor(model: SubModel) {
super(model);
this.color = model.color;
this.speed = model.speed;
}
}
class Sub2 extends Base {
shoeSize = 0;
height= 0;
constructor(model: SubModel2) {
super(model);
this.shoeSize = model.shoeSize;
this.height = model.height;
}
}
// ok:
// const baseClass = new Base({ name: 'John', age: 39 });
// const subClass = new Sub({ color: 'green', speed: 100, ...baseClass });
// const sub2Class = new Sub2({ shoeSize: 10.5, height: 69, ...baseClass });
const Store = {
['Base']: Base,
['Sub']: Sub,
['Sub2']: Sub2,
};
class DynamicMenuElement {
static instance: DynamicMenuElement;
public static get() {
if (!DynamicMenuElement.instance) {
DynamicMenuElement.instance = new DynamicMenuElement();
}
return DynamicMenuElement.instance;
}
// *Something* should be in place of 'K' ...
public createMenuElement<T extends keyof typeof Store, K extends BaseModel>(
type: T, model: K
) {
const Class = Store[type];
if (!Class) {
throw new Error(`Cannot find the class type of ${type}`);
}
return new Class(model); // error
}
}
const base = { name: 'John', age: 39 };
const sub = { color: 'green', speed: 100, ...base };
const sub2 = { shoeSize: 10.5, height: 69, ...base };
// implementation
const element1 = DynamicMenuElement.get().createMenuElement('Base', base);
const element2 = DynamicMenuElement.get().createMenuElement('Sub', sub);
const element3 = DynamicMenuElement.get().createMenuElement('Sub', sub2); // should error
像这个这样的东西怎么样?我觉得有点笨重,但我认为它可以满足您的要求。
type ModelMap = {
Base: BaseModel;
Sub: SubModel;
Sub2: SubModel2;
};
type ConstructorMap = {
Base: typeof Base;
Sub: typeof Sub;
Sub2: typeof Sub2;
};
const Store: { [K in keyof ConstructorMap]: new (model: ModelMap[K]) => InstanceType<ConstructorMap[K]> } = {
Base: Base,
Sub: Sub,
Sub2: Sub2,
};
class DynamicMenuElement {
...
public createMenuElement<K extends keyof ConstructorMap>(
type: K,
model: ModelMap[K]
): InstanceType<ConstructorMap[K]> {
const Class = Store[type];
if (!Class) {
throw new Error(`Cannot find the class type of ${type}`);
}
return new Class(model);
}
}