如何用泛型为TypeScript嵌套函数返回值做类型安全标注?
问题描述
我有一个关联对应类型的映射器,但不知道如何正确为其中的func标注类型,相关代码如下:
type Action<T, K> = { key: K; func: // What should this be? }; type ActionMapper<T> = { [K in keyof T]: Action<T, K>; }; export enum EActionSelectPot { CREATE_ORDER = 'CREATE_ORDER', ADD_ITEM = 'ADD_ITEM', DELETE_ORDER = 'DELETE_ORDER', } const first_function = () => 'hi'; const second_function = () => ['hi']; const third_function = () => { hi: 'hi'; }; const test: ActionMapper<typeof EActionSelectPot> = { CREATE_ORDER: { key: EActionSelectPot.CREATE_ORDER, func: first_function, }, ADD_ITEM: { key: EActionSelectPot.ADD_ITEM, func: second_function, }, DELETE_ORDER: { key: EActionSelectPot.DELETE_ORDER, func: third_function, }, }; const hi = test.CREATE_ORDER.func();
我的目标是通过泛型让该对象自动推断函数类型,无需手动指定返回类型。不确定该需求是否可行,若可行该如何实现?曾尝试func: () => ReturnType[K]['func']>但未成功,希望得到实现方向指引。
实现方案
你的需求完全可行,核心是调整泛型类型的设计逻辑,让TypeScript能关联枚举键与对应函数的类型信息。
方案1:重构泛型类型,明确函数关联
先修改Action和ActionMapper的泛型定义,让它们能接收并关联每个枚举键对应的函数类型:
// 单个Action类型:绑定枚举键K和对应的函数类型F type Action<K extends string | number | symbol, F extends (...args: any[]) => any> = { key: K; func: F; }; // ActionMapper接收函数映射类型,自动生成对应结构 type ActionMapper<T extends Record<string | number | symbol, (...args: any[]) => any>> = { [K in keyof T]: Action<K, T[K]>; };
接着定义枚举对应的函数映射,再约束test变量:
export enum EActionSelectPot { CREATE_ORDER = 'CREATE_ORDER', ADD_ITEM = 'ADD_ITEM', DELETE_ORDER = 'DELETE_ORDER', } const first_function = () => 'hi'; const second_function = () => ['hi']; // 修复原代码语法错误:对象字面量需加括号或return const third_function = () => ({ hi: 'hi' }); // 定义枚举键与函数的映射类型 type ActionFunctions = { [EActionSelectPot.CREATE_ORDER]: typeof first_function; [EActionSelectPot.ADD_ITEM]: typeof second_function; [EActionSelectPot.DELETE_ORDER]: typeof third_function; }; // 自动推断每个func的类型 const test: ActionMapper<ActionFunctions> = { CREATE_ORDER: { key: EActionSelectPot.CREATE_ORDER, func: first_function, }, ADD_ITEM: { key: EActionSelectPot.ADD_ITEM, func: second_function, }, DELETE_ORDER: { key: EActionSelectPot.DELETE_ORDER, func: third_function, }, }; // 此时func返回类型已被正确推断 const hi = test.CREATE_ORDER.func(); // 类型为string
方案2:用泛型函数自动推导(更简洁)
无需手动定义函数映射类型,用泛型函数辅助创建对象,让TypeScript自动完成所有类型推断:
function createActionMapper<T>(mapper: T): T { return mapper; } // 直接创建对象,所有类型自动推断 const test = createActionMapper({ CREATE_ORDER: { key: EActionSelectPot.CREATE_ORDER, func: first_function, }, ADD_ITEM: { key: EActionSelectPot.ADD_ITEM, func: second_function, }, DELETE_ORDER: { key: EActionSelectPot.DELETE_ORDER, func: third_function, }, }); // 同样能正确识别每个func的返回类型 const items = test.ADD_ITEM.func(); // 类型为string[] const order = test.DELETE_ORDER.func(); // 类型为{ hi: string }
原尝试失败原因分析
你之前写的func: () => ReturnType[K]['func']>不可行,是因为:
K是枚举的键(如CREATE_ORDER)本身不是函数类型,ReturnType需要传入函数类型才能生效- 原
ActionMapper仅关联了枚举类型,没有绑定每个键对应的函数信息,TypeScript无法获取函数的返回类型
内容的提问来源于stack exchange,提问作者nerap
相关产品推荐
相关产品推荐

