我正在尝试确定一种创建工厂函数的方法,这样我就可以将类传递给它并接收一个将创建该类实例的函数。类似于:
function createClassFactory<T> (MyClass: {new(...):T}) {
return function classFactory(...) {
return new MyClass(...)
}
}
为了维护类型信息,我希望classFactory
具有与MyClass
构造函数相同的签名。现在我正在谈论如何做到这一点。
这种事情是否可能以其他方式出现?
答案 0 :(得分:1)
除非你愿意接受所有构造函数参数作为单个对象,否则我无法想到一种方法来做你想要的(至少不是优雅的)。
如果所有类都希望单个对象作为params,那么你可以在这些props对象上强制使用一个接口,并使用泛型来实现你正在寻找的东西(好吧,差不多):
class Base<T> {
constructor(props: T) {}
}
type BaseConstructor<C extends Base<P>, P> = {
new(props: P): C;
}
interface AProps {}
class A extends Base<AProps> {}
interface BProps {
x: number;
y: number;
}
class B extends Base<BProps> {}
interface CProps {
str: string;
ok?: boolean;
}
class C extends Base<CProps> {}
function createClassFactory<C extends Base<P>, P> (MyClass: BaseConstructor<C, P>) {
return function classFactory(props: P) {
return new MyClass(props);
}
}
// the following are valid:
let a1 = createClassFactory(A)({});
let b1 = createClassFactory(B)({ x: 3, y: 5 });
let c1 = createClassFactory(C)({ str: "stirng" });
let c2 = createClassFactory(C)({ str: "stirng", ok: true });
// these aren't:
let b2 = createClassFactory(B)({ x: 3, y: "5" });
let c3 = createClassFactory(C)({ ok: true });
// but this one is:
let a2 = createClassFactory(A)({ key: "value" });
我说几乎是因为最后一个例子是使用非空对象创建a2
但除此之外,我认为这几乎就是你所要求的。