TypeScript:能否为接收函数对象的泛型函数定义完整签名?
当然可以!你遇到的问题本质是之前的泛型定义没有针对对象的每个属性做单独的类型推断,而是用了统一的泛型约束导致类型被抹平。TypeScript的**映射类型(Mapped Types)**正是解决这类问题的利器,它能遍历对象的每个属性,为每个属性单独保留对应的返回类型。
完整的类型签名与实现
我们可以借助映射类型和TypeScript内置的工具类型,精准定义这个函数的类型:
// 先定义一个基础类型,约束输入对象的属性都是函数 type FunctionObject = { [key: string]: (...args: any[]) => any }; function resolveFunctions<T extends FunctionObject>(obj: T): { [K in keyof T]: ReturnType<T[K]>; } { const result: Record<string, any> = {}; for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { // 调用每个函数并存储返回值 result[key] = obj[key](); } } return result as { [K in keyof T]: ReturnType<T[K]> }; }
代码解释
- 泛型约束:
T extends FunctionObject确保传入的对象所有属性都是函数类型; - 返回类型映射:
{ [K in keyof T]: ReturnType<T[K]> }是核心——遍历输入对象T的每个属性K,将返回值的类型设置为对应函数T[K]的返回类型(ReturnType是TS内置工具类型,专门提取函数的返回值类型); - 实现逻辑:遍历对象并调用每个函数,最终返回的结果会被TS自动推断为对应属性的精确类型。
使用示例
当你传入包含不同返回类型函数的对象时,返回值的类型会完美保留每个属性的原始返回类型:
const demoFuncs = { getUserId: () => 1001, getUserName: () => "Alice", getIsActive: () => true }; const resolvedObj = resolveFunctions(demoFuncs); // resolvedObj的类型会被TS精确推断为: // { // getUserId: number; // getUserName: string; // getIsActive: boolean; // }
扩展:支持带参数的函数
如果需要支持传入带参数的函数,我们可以进一步扩展类型,为每个函数匹配对应的参数:
function resolveFunctionsWithArgs<T extends FunctionObject>( obj: T, args: { [K in keyof T]: Parameters<T[K]> } ): { [K in keyof T]: ReturnType<T[K]> } { const result: Record<string, any> = {}; for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { result[key] = obj[key](...args[key]); } } return result as { [K in keyof T]: ReturnType<T[K]> }; } // 使用示例 const resolvedWithArgs = resolveFunctionsWithArgs( { calculateSum: (a: number, b: number) => a + b, joinStrings: (str1: string, str2: string) => `${str1}-${str2}` }, { calculateSum: [10, 20], joinStrings: ["Hello", "World"] } ); // resolvedWithArgs的类型:{ calculateSum: number; joinStrings: string; }
内容的提问来源于stack exchange,提问作者aleclofabbro
相关产品推荐
相关产品推荐

