【发布时间】:2019-12-18 01:30:07
【问题描述】:
在 TypeScript 中,我定义了一个名为 create 的辅助函数,它接受一个构造函数和构造函数的类型化参数来创建一个类的新实例:
function create<Ctor extends new (...args: any[]) => any, R extends InstanceType<Ctor>>(
ctor: Ctor,
...args: ConstructorParameters<Ctor>
): R {
return new ctor(...args)
}
这适用于像这样的简单类:
class Bar {
constructor(param: number) { }
}
const bar1 = create<typeof Bar, Bar>(Bar, 1);
// Compile error: Argument of type '"string"' is not assignable to parameter of type 'number'.ts(2345)
const bar2 = create<typeof Bar, Bar>(Bar, 'string');
但是,如果我有一个泛型类,我无法让 TypeScript 对 create 执行正确的类型检查:
class Foo<T> {
constructor(param: T) { }
}
// Ok
const foo1 = create<typeof Foo, Foo<number>>(Foo, 1);
// This should be an error but is not
const foo2 = create<typeof Foo, Foo<number>>(Foo, { not: 'a number' })
根本原因是第二种情况下create的签名采用了unknown参数:
主要问题
是否可以在调用create 时显式写出泛型类构造函数的类型,而无需内联类型本身,同时仍保留create 的签名?
尝试
我的第一个想法是:
create<typeof Foo<number>, Foo<number>>(Foo, { not: 'a number' })
但那是无效的代码。
到目前为止,我发现的最佳解决方法是使用临时类来显式捕获构造函数类型:
class Temp extends Foo<number> { }
// This correctly generates an error
create<typeof Temp, Foo<number>>(Foo, { not: 'a number' });
这可以用更优雅的方式完成吗?
【问题讨论】:
-
您能改用this 吗?它使用higher order function inference in TS3.4+,但类型参数不同。
-
如果它满足您的需求,我可以写出来作为答案。
-
感谢您的浏览。我试图避免显式输入构造函数的参数类型。参数列表在实际代码中可能会变得很长,并且在多个位置显式键入它会使重构变得困难
-
我不知道你为什么要在函数调用中指定泛型。如果您希望函数返回
Foo<number>,那么您可以对其进行注释,如果您没有传递正确的内容,则会看到错误,例如 this。 -
还有generic currying,但这可能不如我上一条评论中的注释有用。
标签: typescript