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

如何为TypeScript合并键值对的函数正确标注类型

解决TypeScript合并对象键值对的类型标注问题

你当前的代码返回类型用了字符串索引签名,所以不管写newKey还是newKey2都不会触发错误——因为TypeScript把[newKey: string]当成任意字符串键的索引,而非绑定到参数newKey的具体字面量。要实现严格的键名约束,需用泛型字面量类型锁定newKey,同时正确处理原键删除与新键添加的类型逻辑:

修正后的代码实现

function mergeKeyValues<T, K extends string, S>(
  obj: T,
  key1: keyof T,
  key2: keyof T,
  newKey: K,
  mergeFn: (a: T[typeof key1], b: T[typeof key2]) => S
): Omit<T, typeof key1 | typeof key2> & { [P in K]: S } {
  // 过滤待删除的键,构造新对象
  const filteredEntries = Object.entries(obj).filter(
    ([key]) => key !== key1 && key !== key2
  );
  const mergedValue = mergeFn(obj[key1], obj[key2]);
  
  return {
    ...Object.fromEntries(filteredEntries),
    [newKey]: mergedValue
  } as Omit<T, typeof key1 | typeof key2> & { [P in K]: S };
}

关键改进说明

  • 泛型锁定新键名:新增泛型K extends string,将newKey约束为具体字符串字面量(比如传入"fullName"时,K就是"fullName"),返回类型中的{ [P in K]: S }会严格对应这个字面量键,修改键名会直接触发类型错误。
  • 精确的合并函数参数类型:把mergeFn的参数从T[keyof T]改为T[typeof key1]和T[typeof key2],确保传入的两个值类型与原对象对应键的类型完全匹配。
  • 正确移除原键的类型:用Omit<T, typeof key1 | typeof key2>从原类型中剔除key1和key2,再与新键类型交叉,保证返回类型不含原键且包含指定新键。

测试示例

const user = { firstName: "John", lastName: "Doe", age: 30 };
const mergedUser = mergeKeyValues(
  user,
  "firstName",
  "lastName",
  "fullName",
  (a, b) => `${a} ${b}`
);

// mergedUser 的类型为:Omit<typeof user, "firstName" | "lastName"> & { fullName: string }
// 即 { age: number; fullName: string }
console.log(mergedUser.fullName); // "John Doe"
console.log(mergedUser.firstName); // 类型报错(原键已被删除)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 18:10:36