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

TypeScript中Extract<keyof R, string>无法索引类型T的错误解决与函数实现

TypeScript泛型合并对象报错:Type 'Extract<keyof R, string>' cannot be used to index type 'T'

错误代码

function mergeObjects<T extends object, R extends object>(obj1: T, obj2: R): object {
  const copy: T = { ...obj1 };

  for (const key in obj2) {
    if (!copy.hasOwnProperty(key)) {
      copy[key] = obj2[key]; // 此处触发类型错误
    }
  }

  return copy;
}

需求

实现mergeObjects泛型函数,接收两个对象,返回包含第一个对象所有属性,以及第二个对象中未在第一个对象出现的属性的新对象。示例:

const user = {
  name: 'Harry',
  surname: 'Potter',
};

const robot = {
  name: 'Cleaner',
  version: 12,
  wheels: 3,
};

// 期望返回结果
mergeObjects(user, robot) === {
  name: 'Harry',
  surname: 'Potter',
  version: 12,
  wheels: 3,
}

问题原因

TypeScript类型系统无法通过hasOwnProperty的运行时判断,推导出key一定不属于T的键集合,因此认为key不能安全地用来索引T类型的变量copy。

修复方案

方案1:类型断言+精确返回类型

通过类型断言告诉TypeScriptkey是copy的合法键,同时指定函数返回类型为T & Omit<R, keyof T>(即T的所有属性加上R中不在T内的属性):

function mergeObjects<T extends object, R extends object>(obj1: T, obj2: R): T & Omit<R, keyof T> {
  const copy = { ...obj1 } as T & Omit<R, keyof T>;

  for (const key in obj2) {
    if (!copy.hasOwnProperty(key)) {
      copy[key as keyof typeof copy] = obj2[key];
    }
  }

  return copy;
}

方案2:对象展开语法简化实现

利用对象展开的特性(后展开的对象属性会覆盖先展开的),直接一行代码实现,类型推导更简洁:

function mergeObjects<T extends object, R extends object>(obj1: T, obj2: R): T & Omit<R, keyof T> {
  return { ...obj2, ...obj1 };
}

这里将obj1放在后面展开,会覆盖obj2中重复的属性,正好满足保留第一个对象属性、合并第二个对象独有属性的需求。

内容的提问来源于stack exchange,提问作者m.strilec

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 14:17:19