TypeScript中根据参数数组返回对应泛型类型数组的实现问询
解决方案:基于元组映射的精准类型推断
要实现返回函数数组的每个元素类型与输入参数数组一一对应,且支持每个函数独立的泛型参数,你需要利用TypeScript的可变参数泛型和元组映射类型,替代原代码中全局统一的泛型T和X。
步骤1:重构基础类型定义
先定义带区分标志的参数类型(discriminated union),以及对应的函数类型:
// 基础函数类型:各自独立泛型 type FirstThing<T> = () => T; type SecondThing<T, X> = (something: X) => T; // 参数的区分联合类型:通过option1区分两种参数 type BaseParam = { option2?: boolean }; type FirstParam = BaseParam & { option1: "firstThing" }; type SecondParam = BaseParam & { option1: "secondThing" }; type FunctionParam = FirstParam | SecondParam;
步骤2:实现泛型映射类型
定义辅助类型,将输入的参数元组映射为对应的函数元组,每个位置的函数类型由参数的option1决定:
// 将单个参数转换为对应函数类型的辅助类型 type ParamToFunc<P, T, X = never> = P extends FirstParam ? FirstThing<T> : P extends SecondParam ? SecondThing<T, X> : never; // 将参数元组转换为函数元组的映射类型 type ParamsToFuncs< P extends readonly FunctionParam[], Ts extends readonly any[], Xs extends readonly any[] > = { [K in keyof P]: ParamToFunc<P[K], Ts[K], Xs[K]>; };
步骤3:实现泛型函数
编写函数,利用可变参数泛型捕获参数元组和对应的类型元组,返回精准映射的函数元组:
function someFunction< P extends readonly FunctionParam[], Ts extends readonly any[], Xs extends readonly any[] >(params: P): ParamsToFuncs<P, Ts, Xs> { return params.map((fp) => { if (fp.option1 === "firstThing") { // 返回FirstThing类型函数,返回值需符合对应位置的Ts[K] return (() => "aa" as unknown as Ts[number]) as any; } else { // 返回SecondThing类型函数,参数类型符合Xs[K],返回值符合Ts[K] return ((smth: Xs[number]) => "bb" as unknown as Ts[number]) as any; } }) as any; }
步骤4:调用示例
调用时指定参数元组、返回值类型元组和参数类型元组,TypeScript会精准推断每个返回函数的类型:
// f1: FirstThing<string>,f2: SecondThing<number, boolean> const [f1, f2] = someFunction< [FirstParam, SecondParam], [string, number], [never, boolean] >([{ option1: "firstThing" }, { option1: "secondThing" }]); // 验证类型:f1无参数,返回string const str = f1(); // str: string // 验证类型:f2需要boolean参数,返回number const num = f2(true); // num: number
简化调用(可选)
如果觉得指定三个泛型参数繁琐,可以通过类型断言在参数中携带类型信息,让TypeScript自动推断:
// 扩展参数类型,携带类型标记 type TypedFirstParam<T> = FirstParam & { _returnType?: T }; type TypedSecondParam<T, X> = SecondParam & { _returnType?: T; _argType?: X }; function someFunctionAuto< P extends readonly (TypedFirstParam<any> | TypedSecondParam<any, any>)[] >(params: P): { [K in keyof P]: P[K] extends TypedFirstParam<infer T> ? FirstThing<T> : P[K] extends TypedSecondParam<infer T, infer X> ? SecondThing<T, X> : never; } { return params.map((fp) => { if (fp.option1 === "firstThing") { return (() => "aa" as unknown as P[K]["_returnType"]) as any; } else { return ((smth: P[K]["_argType"]) => "bb" as unknown as P[K]["_returnType"]) as any; } }) as any; } // 调用时无需手动指定泛型,通过类型标记自动推断 const [f3, f4] = someFunctionAuto([ { option1: "firstThing", _returnType: undefined as string }, { option1: "secondThing", _returnType: undefined as number, _argType: undefined as boolean } ]); // f3: FirstThing<string>,f4: SecondThing<number, boolean>
核心原理
- 用可变参数泛型捕获输入的参数元组和类型元组,避免全局统一泛型的限制。
- 用元组映射类型将参数元组的每个元素转换为对应的函数类型,实现位置一一对应。
- 利用discriminated union区分不同参数类型,确保类型推断的准确性。
内容的提问来源于stack exchange,提问作者medicenfranito
相关产品推荐
相关产品推荐

