以下是一些设置代码:
// This is from lib.d.ts
type ConstructorParameters<T extends new (...args: any[]) => any>
= T extends new (...args: infer P) => any ? P : never
// Represents a type with a constructor function
type Newable<TType> = {
new(...params: any[]): TType;
};
// A sample class
class Foo {
constructor(
options: { bar: string }
) {
}
public bar() { }
}
这是我想输入的通用类工厂,但目前我失败了:
// Error: 'T' refers only to a type, but is being used as a value here
declare function create<T>(kind: Newable<T>, options?:
ConstructorParameters<typeof T>[0]): T;
我想这样使用它:
var x = create(Foo, { bar2: 'ss' }); // This should fail because the constructor option is wrong
x.bar();
我理解错误,但是有人知道如何使它正常工作吗?
答案 0 :(得分:1)
您的代码中有几个问题,最大的问题是您无法执行typeof T
,您将需要type参数来重发该类而不是该类的实例。如果T
是类,则可以使用InstanceType
获取该类的实例类型。您还可以使用条件类型来提取构造函数的第一个参数。另外,由于您希望构造函数始终具有一个参数,因此,我不会更好地使用通用的new(...params: any[]): TType;
创建一个自定义类型来仅使用一个参数type CtorWithOptions<TOpt extends object, T> = new (o: TOpt)=> T
来代表构造函数。
将它们放在一起:
// A sample class
class Foo {
constructor(
options: { bar: string }
) {
}
public bar() { }
}
type CtorWithOptions<TOpt extends object, T> = new (o: TOpt)=> T
type OptionsFromConstructor<T> = T extends CtorWithOptions<infer TOpt, any> ? TOpt : never;
declare function create<T extends CtorWithOptions<any, any>>(kind: T, options: OptionsFromConstructor<T>): InstanceType<T> {
return new kind(options);
}
var x = create(Foo, { bar2: 'ss' }); // Fails
var x = create(Foo, { bar: 'ss' }); // OK
x.bar();
答案 1 :(得分:0)
替代解决方案,更接近原始代码段:
type Newable<TType extends new(...args:any[]) => InstanceType<TType>> = {
new(...params: any[]): InstanceType<TType>;
};
// A sample class
class Foo {
constructor(
options: { bar: string }
) {
}
public bar() { }
}
declare function create<T extends Newable<T>>(kind: T, options?:
ConstructorParameters<T>[0]): InstanceType<T>;
var x = create(Foo, { bar2: 'ss' }); // Error as expected
x.bar();