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

如何编写支持泛型/重载的类型安全柯里化记录字段映射函数

类型安全的柯里化记录字段映射函数实现问题

我想编写一个柯里化函数,以类型安全的方式映射记录的每个字段,但不知道如何使用映射类型处理字段映射函数(fn: TFunc)为泛型或重载函数的情况。

export const mapRecordFields = <TFunc extends (x: any) => any> (
  fn: TFunc, // 可能是泛型或重载函数
) => <TRecord extends Record<string, any>> (
  record: TRecord,
): { [P in keyof TRecord]: /* ??? */ } => { /* 忽略实现细节 */ };

const identity = <T> (x: T): T => x;
const toSingleElementArr = <T> (x: T): [T] => [x]

const structure = {
  x: 1,
  y: 'qwe',
} as const;

const result1 = mapRecordFields(identity)(structure); // 期望推断类型:{x: 1, y: 'qwe'}
const result2 = mapRecordFields(toSingleElementArr)(structure); // 期望推断类型:{x: [1], y: ['qwe']}

我尝试了StackOverflow上的相关解决方案,但仍无法让result的类型正确推断,请问是否有可行的解决方法?


解决方案

要实现类型安全的映射,核心是利用TypeScript的条件类型和泛型推断,让映射函数的返回类型能精准作用于记录的每个字段。修改后的函数定义如下:

export const mapRecordFields = <TFunc> (
  fn: TFunc
) => <TRecord extends Record<string, unknown>> (
  record: TRecord
): { [P in keyof TRecord]: TFunc extends (x: infer X) => infer Y ? (TRecord[P] extends X ? Y : never) : never } => {
  // 示例实现逻辑(可根据需求调整)
  const mapped: any = {};
  for (const key in record) {
    mapped[key] = fn(record[key]);
  }
  return mapped;
};

关键细节:

  • 通过TFunc extends (x: infer X) => infer Y提取映射函数的输入类型X和输出类型Y
  • 对记录的每个字段TRecord[P],校验其是否符合X的类型约束,返回对应的Y类型
  • 针对泛型映射函数,TypeScript会自动为每个字段的具体类型推断出正确的返回值类型

测试验证:

const identity = <T> (x: T): T => x;
const toSingleElementArr = <T> (x: T): [T] => [x]

const structure = {
  x: 1,
  y: 'qwe',
} as const;

const result1 = mapRecordFields(identity)(structure); 
// 实际推断类型:{ readonly x: 1; readonly y: "qwe"; }

const result2 = mapRecordFields(toSingleElementArr)(structure); 
// 实际推断类型:{ readonly x: [1]; readonly y: ["qwe"]; }

如果映射函数是重载类型,TypeScript也会根据传入字段的具体类型匹配对应的重载签名,保证类型安全。

内容的提问来源于stack exchange,提问作者SimpleV

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 21:09:21