TypeScript中如何引用具体类避免重复书写构造函数参数
问题原因
你遇到的两个报错本质都是泛型约束的定义问题:
ConstructorParameters<F>报类型不匹配错误:你定义的F extends Foo是类的实例类型,而ConstructorParameters工具类型要求传入的是可被new调用的构造函数类型,实例类型不满足入参约束,因此报错。ConstructorParameters<typeof F>报"F被作为值使用"错误:类型空间中的typeof只能引用实际存在的JavaScript值,F只是泛型类型参数,不是真实值,因此无法通过typeof获取其类型。
解决方案
根据使用场景选以下任意一种写法即可,都不需要重复书写构造函数参数类型,后续修改Foo的构造函数定义时类型会自动同步,没有维护负担。
场景1:函数固定传入基类要求的构造参数
如果你的函数和示例中的bar一样,调用构造函数时固定传入基类Foo要求的参数,不需要关心子类的额外构造参数,直接提取typeof Foo的构造参数类型即可:
abstract class Foo { constructor(a: string, b: number) { } } class SpecificFoo extends Foo {} function bar<F extends Foo>(klass: new (...args: ConstructorParameters<typeof Foo>) => F) { return new klass('hi', 1) } bar(SpecificFoo) // 类型检查正常通过
场景2:需要透传子类自定义的构造参数
如果你需要支持子类重写构造函数、添加额外参数,要求函数能透传任意合法的构造参数,可以把泛型直接约束为构造函数类型,而非实例类型:
abstract class Foo { constructor(a: string, b: number) { } } class SpecificFoo extends Foo {} // 支持带额外构造参数的子类 class CustomFoo extends Foo { constructor(a: string, b: number, public extra: boolean) { super(a, b) } } // 泛型F直接约束为构造函数类型 function bar<F extends new (...args: any[]) => Foo>(klass: F, ...args: ConstructorParameters<F>): InstanceType<F> { return new klass(...args) } bar(SpecificFoo, 'hi', 1) // 正常 bar(CustomFoo, 'hi', 1, true) // 自动识别第三个参数为boolean类型,类型检查正常
内容的提问来源于stack exchange,提问作者rattray
相关产品推荐
相关产品推荐

