我知道它太通用了,但是我希望创建一个这样的类,该类将具有如下所示的通用类型的所有道具和原型:
class GenericExtend<T> extends T {
constructor(data: T) {
// here is a workaround to make these 2 classes unique
const proto = { ...GenericExtend.prototype };
Object.assign(proto, Object.getPrototypeOf(data));
Object.setPrototypeOf(this, proto);
Object.assign(this, data);
}
GenericMethod() { }
}
现在,我可以实例化GenericExtend
类,然后获得两个类的类型,如下所示:
const obj = new GenericExtend<Model>(data);
obj.GenericMethod(); // ok
obj.ModelMethod(); // good!
我的解决方案之一是使用交集,如下所示:
const obj: GenericExtend & Model = new GenericExtend(data) as any;
它奏效了,但我不太喜欢。我能做些更好的事情吗?
答案 0 :(得分:2)
我认为您必须使用交集来实现此行为...但是您可以根据需要将类型断言限制在构造函数中,这样以后的使用将不需要它。让我们重命名GenericExtend
:
class _GenericExtend<T> {
constructor(data: T) {
const proto = { ..._GenericExtend.prototype };
Object.assign(proto, Object.getPrototypeOf(data));
Object.setPrototypeOf(this, proto);
Object.assign(this, data);
}
GenericMethod() { }
}
然后使用所需的交集行为将GenericExtend
重新定义为类型和构造函数:
type GenericExtend<T> = _GenericExtend<T> & T;
const GenericExtend: new <T>(data: T) => GenericExtend<T> = _GenericExtend as any;
最后一个as any
是我们需要的类型断言。现在您应该能够获得想要的行为:
interface Model {
ModelMethod(): void;
}
declare const data: Model;
const obj = new GenericExtend(data);
obj.GenericMethod(); // ok
obj.ModelMethod(); // ok
希望有帮助。祝你好运!
答案 1 :(得分:0)
我遇到了类似的需求,最终按照以下方式实现,严格不需要交集(您可以定义专用类型进行类型检查),希望对您有所帮助。
class A {
a() {
...
}
}
class B {
b() {
...
}
}
type Constructor = new (...args: any[]) => any
function genericExtend<T extends Constructor>(target: T) {
return class GenericExtended extends target {
constructor(...args: any[]) {
super(...args)
}
genericMethod() {
...
}
}
}
const instanceOfA: GenericExtended & A = new (genericExtend(A))()
const instanceOfB = new (genericExtend(B))()
instanceOfA.a() // ok with type checking
instanceOfA.genericMethod() // ok with type checking
instanceOfB.b() // ok without type checking
instanceOfB.genericMethod() // ok without type checking