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

如何将Record的键作为索引,使函数参数类型匹配对应属性类型?

解决TypeScript中useFormTransform的精确类型约束问题

我完全理解你的需求——你希望transform参数里的每个转换函数,能精确接收对应属性的原始类型,而不是所有属性类型的联合(比如string | undefined | number)。原来的类型定义用了Partial<Record<keyof T, (value: T[keyof T]) => any>>,这里的问题在于T[keyof T]是所有属性类型的联合,所以每个转换函数的参数类型会被放宽到这个联合,而不是对应单个属性的精确类型。

咱们可以用TypeScript映射类型来解决这个问题,它能逐个遍历泛型T的键,并为每个键绑定对应的精确类型:

修正后的函数类型定义

const useFormTransform = <T>(
  formValues: T,
  transform: {
    // 遍历T的每个键K,定义可选的转换函数,参数类型精确为T[K]
    [K in keyof T]?: (value: T[K]) => any;
  }
) => {
  // 示例实现逻辑(你可以替换成自己的代码)
  return Object.fromEntries(
    Object.entries(formValues).map(([key, value]) => {
      const transformer = transform[key as keyof T];
      return [key, transformer ? transformer(value as T[keyof T]) : value];
    })
  ) as { 
    // 推导返回值类型:如果有转换函数则用其返回类型,否则保留原始类型
    [K in keyof T]: (typeof transform)[K] extends undefined ? T[K] : ReturnType<(typeof transform)[K]> 
  };
};

验证使用效果

现在再用你的示例代码测试,每个转换函数的参数类型会自动匹配对应属性的精确类型:

type Line = { id?: string; fromQuantity: number };
const line: Line = { id: 'abc', fromQuantity: 123 };

// 此时:
// - id对应的转换函数参数f的类型是string | undefined
// - fromQuantity对应的转换函数参数f的类型是number(完全匹配line.fromQuantity的类型)
useFormTransform(
  line,
  {
    id: (f) => f,
    fromQuantity: (f) => transformNumber(f), // 这里f直接是number类型,无需再用Number(f)转换
  },
);

关键原理说明

原来的Record<keyof T, ...>会把所有键的类型统一成keyof T,对应的参数类型也就变成了所有属性类型的联合。而映射类型[K in keyof T]?会逐个处理每个键K,并将函数参数类型绑定到T[K]——也就是该键对应的原始属性类型,这样就实现了精确的类型约束。

另外,上面的返回值类型推导也做了优化,会根据你是否提供了转换函数,自动推导最终返回对象的类型(转换后的类型或原始类型)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 09:57:33