示例代码:
interface ValueGenerator {
next(): any;
}
class NumberGenerator {
next(): number {
return 1;
}
}
class ArrayGenerator<T extends ValueGenerator> {
private generator: T;
constructor(valueGenerator: T) {
this.generator = valueGenerator;
}
next(): Array<ReturnType<T['next']>> {
return [this.generator.next()];
}
}
const numGenerator = new NumberGenerator();
const fn1 = <T extends ValueGenerator>(t: T) => new ArrayGenerator(t);
const fn2 = (...args: ConstructorParameters<typeof ArrayGenerator>) => new ArrayGenerator(...args)
const generator1 = fn1(numGenerator);
const generator2 = fn2(numGenerator);
// number[]
const a = generator1.next();
// any[]
const b = generator2.next();
有没有一种方法可以为ArrayGenerator
创建工厂函数而无需像我对fn1
那样手动编写正确的签名?理想情况下,我想做类似fn2
的操作,但是它不能按预期工作。 fn2
将正确推断构造函数参数,但不会推断generator2.next
返回类型。
答案 0 :(得分:1)
如果您手动编写一个函数,我认为编译器将不会为您推断出通用函数。但是,TypeScript 3.4引入了support for higher order type inference in generic functions,TypeScript 3.5之后是the corresponding support for generic constructor functions。这使您可以编写一个通用的高阶函数,该函数接受一个函数并返回一个函数,并且如果输入是通用的,则编译器将尝试自动使输出通用。推理算法并不完美,但是对于我在这里想要做的事情来说已经足够了,这就是创建一个通用的“从构造函数到工厂”的功能:
function ctorToFactory<A extends any[], R>(ctor: new (...args: A) => R): (...args: A) => R {
return (...args) => new ctor(...args);
}
如果您在ArrayGenerator
上调用它,则会自动获得一个通用的fn2
,而无需自己输入:
const fn2 = ctorToFactory(ArrayGenerator);
// const fn2: <T extends ValueGenerator>(valueGenerator: T) => ArrayGenerator<T>
const generator2 = fn2(numGenerator);
const b = generator2.next(); // number[]
好的,希望能有所帮助;祝你好运!