能否从泛型类型元组提取泛型参数为元组?TS函数合并优化
实现fnZip函数的类型优化方案
需求说明
我想要实现一个函数fnZip,它接收一组泛型函数并将其“合并”为一个函数,该函数会接收所有输入函数的参数,并在一次调用中返回所有输入函数的输出。
现有类型安全实现
目前我通过infer推断每个泛型函数的参数和返回类型,实现了类型安全,代码如下:
type Fn<T = any, TReturn = any> = (arg: T) => TReturn; type FnArg<T extends Fn> = T extends Fn<infer TArg> ? TArg : unknown; type FnArgTuple<T extends Fn[]> = { [key in keyof T]: FnArg<T[key]> }; type FnReturn<T extends Fn> = T extends Fn<any, infer TReturn> ? TReturn : unknown; type FnReturnTuple<T extends Fn[]> = { [key in keyof T]: FnReturn<T[key]> }; const fnZip = <T extends ((arg: any) => any)[]>( fns: [...T], ): Fn<FnArgTuple<T>, FnReturnTuple<T>> => ( args, ) => fns.map((fn, idx) => fn(args[idx])) as FnReturnTuple<T>;
优化设想
但我想知道是否有更优雅、更符合惯例的方式,从给定的函数数组中提取函数的参数和返回类型作为元组。以下是我设想的(无法运行的)示例:
type Fn<T = any, TReturn = any> = (arg: T) => TReturn; const fnZip = <T extends any[], TReturn extends any[]>( fns: { [key: number]: Fn<T[key], TReturn[key]> }, ): Fn<T, TReturn> => (args) => fns.map((fn, idx) => fn(args[idx])) as TReturn;
核心逻辑补充
我实际想要实现的逻辑是:
[Type<A1, B1>, Type<A2, B2>, ...etc] => Type<[A1, A2, ..etc], [B1, B2, ...etc]>
@jcalz提出的方案(存在推断问题)
@jcalz提出了一个方案,若TypeScript能正确推断第二个泛型类型,该方案本应完美运行,但出于未知原因无法实现:
type Fn<T = any, TReturn = any> = (arg: T) => TReturn; const fnZip = <T extends any[], TReturn extends { [key in keyof T]: any }>( fns: [...{ [key in keyof T]: Fn<T[key], TReturn[key]> }], ): Fn<T, TReturn> => (args) => fns.map((fn, idx) => fn(args[idx])) as TReturn; const zipped = fnZip([ // ^? const zipped: Fn<[string, number], [any, any]> (x: string) => x.length, (y: number) => y.toFixed(), ]);
内容的提问来源于stack exchange,提问作者Jørgen Tau
相关产品推荐
相关产品推荐

