如何在打字稿中使用泛型返回值注释函数



给定一个返回工厂的函数,如何注释函数/工厂以使其包含正确的类型定义?

这是我的例子:

class item<T> {
constructor(a: T) {
this.a = a;
}
a: T
}
function generate(c) {
return function a(a) {
return new c(a);
}
}
const factory = generate(item); // I want this to always be annotated as <T> (a: T) => item<T>
const instance = factory('string'); // instance should now be of type item<string>

这在打字稿中是否可行,或者我应该建议将其作为新功能?

对于非泛型类,我们可以在 3.0 中使用 rest 参数中的元组,并展开表达式和InstanceType将构造函数映射到类似的函数。

不幸的是,对于泛型类,映射时无法保留类型参数。唯一的解决方案是向类添加一个字段,该字段将告诉generate结果类型应该是什么。这可以使用接口类合并来完成,因此原始类不知道 generate。

使用这两种方法(尽可能自动,必要时手动(的可能解决方案可能如下所示:

class item<T> {
constructor(a: T) {
this.a = a;
}
a: T
}
const generateResult = Symbol.for("generate")
interface item<T> {
[generateResult] : <T>(a: T) => item<T>    
}
type d = item<any>[typeof generateResult]
type SupportsGeneration<R> =  { [generateResult] : R }
type ConstructorArguments<T> = T extends new (...a:infer A ) => any ? A : [];

function generate<T extends { new (...a:any[]) : SupportsGeneration<any> }>(c:T) :  InstanceType<T> extends SupportsGeneration<infer R> ? R: never
function generate<T extends new (...a:any[]) => any>(c:T) :  (a: ConstructorArguments<T>) => InstanceType<T>
function generate(c: new (...a: any[]) => any) : any {
return function a(...a: any[]) {
return new c(...a);
}
}
const factory = generate(item); 
const instance = factory('string');

从 v3.4 开始似乎可以达到预期的效果:

class item<T> {
constructor(a: T) {
this.a = a;
}
a: T
}
function generate<Arg, Result>(c: new (arg: Arg) => Result) {
return function a(a: Arg) {
return new c(a);
}
}
const factory = generate(item); // I want this to always be annotated as <T> (a: T) => item<T>
const instance = factory('string'); // instance should now be of type item<string>

操场

最新更新