如何在 TypeScript 泛型中动态指定类型?
How to dynamically specify type in TypeScript generics?
我应该如何修改 WithArea
函数的 areaCalculator
参数的泛型类型参数 U
以扩展当前 MixinFactory
实例的基础 class ?
type Constructor<T> = new (...args: any[]) => T;
interface IArea {
readonly area: number;
}
class MixinFactory<T extends Constructor<Shape>> {
constructor(public Superclass: T) {}
WithArea(areaCalculator: <U extends Shape & IArea>(ctx: U) => number) {
return new MixinFactory<T & Constructor<IArea>>(class extends this.Superclass implements IArea {
get area(): number {
return areaCalculator(this);
}
})
}
}
class Shape {}
class RectRaw extends Shape {
constructor(
public x: number,
public y: number,
public w: number,
public h: number) {
super();
}
}
const Rect = new MixinFactory(RectRaw).WithArea(ctx => {
return ctx.w * ctx.h;
}).Superclass;
const rect = new Rect(10, 10, 20, 20);
console.log(rect.area);
您的 areaCalculator
函数不需要是通用的;不需要额外的类型参数 U
,并且此类型参数不会由方法 get area(): number
.
公开
areaCalculator
函数只需要定义为接受构造函数类型 T
returns 的任何对象,因此使用 InstanceType
帮助器,我们可以提取它并直接在类型注解中使用:
class MixinFactory<T extends Constructor<Shape>> {
constructor(public Superclass: T) {}
WithArea(areaCalculator: (ctx: InstanceType<T> & IArea) => number) {
return new MixinFactory<T & Constructor<IArea>>(class extends this.Superclass implements IArea {
get area(): number {
return areaCalculator(this as InstanceType<T> & IArea);
}
})
}
}
请注意,类型断言 this as InstanceType<T> & IArea
是必需的,因为 Typescript 无法确定如果 class 扩展 this.Superclass
类型 T
那么它的实例必须具有类型 InstanceType<T>
.
我应该如何修改 WithArea
函数的 areaCalculator
参数的泛型类型参数 U
以扩展当前 MixinFactory
实例的基础 class ?
type Constructor<T> = new (...args: any[]) => T;
interface IArea {
readonly area: number;
}
class MixinFactory<T extends Constructor<Shape>> {
constructor(public Superclass: T) {}
WithArea(areaCalculator: <U extends Shape & IArea>(ctx: U) => number) {
return new MixinFactory<T & Constructor<IArea>>(class extends this.Superclass implements IArea {
get area(): number {
return areaCalculator(this);
}
})
}
}
class Shape {}
class RectRaw extends Shape {
constructor(
public x: number,
public y: number,
public w: number,
public h: number) {
super();
}
}
const Rect = new MixinFactory(RectRaw).WithArea(ctx => {
return ctx.w * ctx.h;
}).Superclass;
const rect = new Rect(10, 10, 20, 20);
console.log(rect.area);
您的 areaCalculator
函数不需要是通用的;不需要额外的类型参数 U
,并且此类型参数不会由方法 get area(): number
.
areaCalculator
函数只需要定义为接受构造函数类型 T
returns 的任何对象,因此使用 InstanceType
帮助器,我们可以提取它并直接在类型注解中使用:
class MixinFactory<T extends Constructor<Shape>> {
constructor(public Superclass: T) {}
WithArea(areaCalculator: (ctx: InstanceType<T> & IArea) => number) {
return new MixinFactory<T & Constructor<IArea>>(class extends this.Superclass implements IArea {
get area(): number {
return areaCalculator(this as InstanceType<T> & IArea);
}
})
}
}
请注意,类型断言 this as InstanceType<T> & IArea
是必需的,因为 Typescript 无法确定如果 class 扩展 this.Superclass
类型 T
那么它的实例必须具有类型 InstanceType<T>
.