Typescript:类扩展了泛型类型
我知道它太泛型了,但我希望创建一个类,该类包含所有来自泛型类型的道具和原型,如下所示:Typescript:类扩展了泛型类型,typescript,Typescript,我知道它太泛型了,但我希望创建一个类,该类包含所有来自泛型类型的道具和原型,如下所示: class GenericExtend<T> extends T { constructor(data: T) { // here is a workaround to make these 2 classes unique const proto = { ...GenericExtend.prototype }; Object.assign
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() { }
}
const obj = new GenericExtend<Model>(data);
obj.GenericMethod(); // ok
obj.ModelMethod(); // good!
const obj: GenericExtend & Model = new GenericExtend(data) as any;
我的解决方案之一是使用交叉点,类似这样:
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() { }
}
const obj = new GenericExtend<Model>(data);
obj.GenericMethod(); // ok
obj.ModelMethod(); // good!
const obj: GenericExtend & Model = new GenericExtend(data) as any;
它奏效了,但我不太喜欢。有更好的方法吗?TypeScript不会让您实现或扩展另一种类型
T
,除非T
的所有键在编译时都是静态已知的。这可以防止类GenericExtend实现T{…}
成为您可以编写的东西
相反,您必须使用交叉点来获得此行为。。。但是,如果需要,可以将类型断言限制在构造函数中,以便后续使用不需要它。让我们把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() { }
}
最后的和任何一样是我们需要的类型断言。现在,您应该能够获得所需的行为:
type GenericExtend<T> = _GenericExtend<T> & T;
const GenericExtend: new <T>(data: T) => GenericExtend<T> = _GenericExtend as any;
interface Model {
ModelMethod(): void;
}
declare const data: Model;
const obj = new GenericExtend(data);
obj.GenericMethod(); // ok
obj.ModelMethod(); // ok
我遇到了类似的需求,并最终通过以下方式实现了它,通过这种方式,不需要严格的交叉点(您可以为类型检查定义专用类型),希望它能有所帮助
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
A类{
(){
...
}
}
B类{
b(){
...
}
}
类型构造函数=新建(…参数:any[])=>any
函数genericExtend(目标:T){
返回类GenericExtended扩展目标{
构造函数(…参数:任意[]){
超级(…args)
}
genericMethod(){
...
}
}
}
const instanceOfA:GenericExtended&A=new(genericExtend(A))()
const instanceOfB=new(genericExtend(B))()
instanceOfA.a()//类型检查正常
instanceOfA.genericMethod()//通过类型检查确定
instanceOfB.b()//不进行类型检查即可
instanceOfB.genericMethod()//不进行类型检查即可
太棒了!如果模型是一个类而不是一个接口,它会工作吗?它应该在语法上工作,结果对象应该在结构上与类类型匹配,但它可能不适用于instanceof
或类原型属性。这些东西需要在GenericExtend
构造函数的实现中解决。。。我不相信自己会写那封信。听起来,如果您的用例是扩展一个类,那么您可能正在寻找它。您是对的!我想mixins会解决我的问题。谢谢@jcalz的这个解决方案。我进一步简化了它,以避免额外的类型和强制转换:const GenericExtend=\u GenericExtend as new(data:T)=>\u GenericExtend&T代码>