You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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函数的类型推导

核心修改点:

  1. 给convert新增第二个泛型TObj,精准捕获传入的函数对象的所有键名、每个函数的参数定义
  2. 通过映射类型处理返回值,自动剔除每个函数的第一个context参数,保留剩余参数的类型约束
  3. 原函数对象不要直接用宽泛的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 05:48:04