TypeScript:如何将typeof类类型转为实例类型并返回子类实例?
问题
给定类型typeof MyClass,如何将其转换为MyClass类型?
场景
在TypeScript中,你可以直接将类传入函数,并在函数内部创建该类的实例。
class MyClass {} const init = (constructor: typeof MyClass): MyClass => { return new constructor() } // `myInstance` 的类型为 `MyClass` const myInstance = init(MyClass)
但如果存在继承自父类的子类,该如何处理?
class Parent {} class ChildA extends Parent {} class ChildB extends Parent {} const init2 = <T extends typeof Parent>(constructor: T) => { return new constructor() } // `childA` 和 `childB` 的类型为 `Parent` // 期望 `childA` 的类型为 `ChildA` // 期望 `childB` 的类型为 `ChildB` const childA = init2(ChildA) const childB = init2(ChildB)
如何设置init2的返回类型为所实例化的具体类类型?
解决方案
使用TypeScript内置的InstanceType<T>工具类型,它可以直接从构造函数类型T中提取对应的实例类型。修改init2的返回类型为InstanceType<T>即可:
class Parent {} class ChildA extends Parent {} class ChildB extends Parent {} const init2 = <T extends typeof Parent>(constructor: T): InstanceType<T> => { return new constructor() } // 现在 `childA` 类型自动推导为 `ChildA`,`childB` 类型为 `ChildB` const childA = init2(ChildA) const childB = init2(ChildB)
原理说明
InstanceType<T>是TypeScript提供的工具类型,专门用于处理构造函数类型与实例类型的转换。当泛型T传入typeof ChildA时,InstanceType<T>会解析为ChildA类型,完全符合期望的具体子类类型。
扩展:处理带参数的构造函数
如果构造函数需要传入参数,可以结合ConstructorParameters<T>工具类型来确保参数类型匹配:
class Parent {} class ChildA extends Parent { constructor(public name: string) { super() } } const initWithArgs = <T extends new (...args: any[]) => Parent>( constructor: T, ...args: ConstructorParameters<T> ): InstanceType<T> => { return new constructor(...args) } // 参数类型会自动校验,返回类型为ChildA const childA = initWithArgs(ChildA, "Alice")
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

