TypeScript中如何获取Record值类型集合并实现函数映射的类型保留
解决方案
1. 获取Record所有值的联合类型
直接使用TS的索引访问语法即可实现,通用写法如下:
// 通用工具类型:提取Record/对象的值类型 type ValueOf<T> = T[keyof T]; // 示例使用 const sampleObj = { 'a': 1, 'b': false }; type SampleValue = ValueOf<typeof sampleObj>; // 推导结果为:number | boolean
2. 修复convert函数的类型推导
核心修改点:
- 给
convert新增第二个泛型TObj,精准捕获传入的函数对象的所有键名、每个函数的参数定义 - 通过映射类型处理返回值,自动剔除每个函数的第一个
context参数,保留剩余参数的类型约束 - 原函数对象不要直接用宽泛的
Record<string, xxx>注解,改用satisfies做结构约束,避免丢失精确类型
完整可运行代码:
type MyContext = { store: number[]; }; // 用satisfies约束结构,同时保留obj的精确类型 const obj = { log(ctx: MyContext, msg: string) { console.log(msg); }, add(ctx: MyContext, value: number) { ctx.store.push(value); } } satisfies Record<string, (context: MyContext, ...args: any[]) => void>; // 改造后的convert函数,带完整类型推导 const convert = < TContext, TObj extends Record<string, (context: TContext, ...args: any[]) => void> >(context: TContext, objectWithFunctions: TObj) => { const result: Record<string, (...args: any[]) => void> = {}; Object.keys(objectWithFunctions).forEach((functionName) => { const func = objectWithFunctions[functionName]; result[functionName] = (...args) => func(context, ...args); }); // 这里用as断言返回映射后的类型,逻辑是安全的 return result as { [K in keyof TObj]: // 提取原函数除第一个参数外的剩余参数,保留返回值类型 (...args: Parameters<TObj[K]> extends [infer _, ...infer RestArgs] ? RestArgs : never) => ReturnType<TObj[K]> }; }; const context: MyContext = { store: [] }; const newObj = convert(context, obj); // 正常调用,无报错 newObj.log('some message'); newObj.add(12); newObj.add(); // 报错:缺少参数value newObj.foo(); // 报错:不存在foo属性 console.log(newObj, context.store);
内容的提问来源于stack exchange,提问作者Roman Koliada
相关产品推荐
相关产品推荐

