是否可以输入 "spreadCall" 方法?有条件类型和推断的谜题
is it possible to type the "spreadCall" method? a puzzle with conditional type and infer
我在工作中遇到一个问题,我可以用这个例子来总结:是否可以完全键入以下函数?
function spreadCall(f1, f2) {
const args = f1();
f2(...args);
}
所以我们需要 f2 接受与 f1 的结果完全相同数量的参数(即元组),类型顺序相同。我想不出办法 - 我能想到的部分解决方案是枚举几个参数,即
type Output<F> =
F extends ()=>[infer A0] ? (a0:A0)=>void :
F extends ()=>[infer A0, infer A1] ? (a0:A0, a1:A1)=>void :
F extends ()=>[infer A0, infer A1, infer A2] ? (a0:A0, a1:A1, a2:A2)=>void :
never;
// enumerate as many number of arguments as desired ^^
function spreadCall<InputF>(f1:InputF, f2:Output<InputF>) {
// ...
}
有没有办法处理任意数量的参数?
我认为你可以使用 generic rest parameter type 来做你想做的事情:
function spreadCall<A extends any[]>(f1: () => A, f2: (...args: A) => any) {
const args = f1();
f2(...args);
}
f1
的 return 必须是与 f2
函数的参数类型匹配的 tuple:
declare function input(): [number, string]
declare function output(a: number, b: string): void;
spreadCall(input, output);
我在工作中遇到一个问题,我可以用这个例子来总结:是否可以完全键入以下函数?
function spreadCall(f1, f2) {
const args = f1();
f2(...args);
}
所以我们需要 f2 接受与 f1 的结果完全相同数量的参数(即元组),类型顺序相同。我想不出办法 - 我能想到的部分解决方案是枚举几个参数,即
type Output<F> =
F extends ()=>[infer A0] ? (a0:A0)=>void :
F extends ()=>[infer A0, infer A1] ? (a0:A0, a1:A1)=>void :
F extends ()=>[infer A0, infer A1, infer A2] ? (a0:A0, a1:A1, a2:A2)=>void :
never;
// enumerate as many number of arguments as desired ^^
function spreadCall<InputF>(f1:InputF, f2:Output<InputF>) {
// ...
}
有没有办法处理任意数量的参数?
我认为你可以使用 generic rest parameter type 来做你想做的事情:
function spreadCall<A extends any[]>(f1: () => A, f2: (...args: A) => any) {
const args = f1();
f2(...args);
}
f1
的 return 必须是与 f2
函数的参数类型匹配的 tuple:
declare function input(): [number, string]
declare function output(a: number, b: string): void;
spreadCall(input, output);