bindNew
错误地推断了构造函数类型,仅识别多个重载版本之一。
如何解决?
function bindNew<C extends { new(...args: A): T }, A extends any[], T>(
klass: C & { new(...args: A): T }
): C & ((...args: A) => T) {
return new Proxy(klass, {
apply(target, _self, args) { return new (target as any)(...args) }
}) as any
}
class AClass {
constructor(a: number)
constructor(a: number, b: number)
constructor(a: number, b?: number) {}
}
const A = bindNew(AClass)
A(0) // => Error: expects 2 arguments
A(0, 0)
// This works, but requires explicit type declaration
// interface A extends AClass {}
// const A = bindNew(AClass) as typeof AClass & {
// (a: number): A
// (a: number, b: number): A
// }
似乎不可能,TS推断出最后一个重载签名。但是你有一个非常简单的情况,你可以将构造函数参数作为元组的并集。我已将第二个签名更改为
a: string
,因此很明显该签名在第二个测试用例中处于活动状态:
function bindNew<C extends { new(...args: A): T }, A extends any[], T>(
klass: C & { new(...args: A): T }
): C & ((...args: A) => T) {
return new Proxy(klass, {
apply(target, _self, args) { return new (target as any)(...args) }
}) as any
}
class AClass {
constructor(...args: [a: number] | [a: string, b: number]){
}
}
type t = ConstructorParameters<typeof AClass>
const A = bindNew(AClass)
A(0)
A('string', 0)