TypeScript 中安全遍历对象的三种方法:for...in、Object.keys 与 Object.entries

作者:木棉

时间:2026-10-25

浏览:154

本文详解在 TypeScript 中遍历对象的三种常见方式:for...in、Object.keys 和 Object.entries。针对 TypeScript 静态类型检查导致的类型错误,分别介绍了使用 keyof 类型断言、类型转换及解构赋值等解决方案,并探讨了运行时属性与静态类型差异的根本原因。

文章目录

JavaScript

在探讨使用 TypeScript 遍历对象之前,我们先回顾 JavaScript 中的实现方式,例如 for...in 和 Object.keys,并展示一个简单示例:

// for...in
const obj = {
  name: 'itsuki',
  address: 'hangzhou',
};
for (const key in obj) {
  console.log(key, obj[key].toUpperCase());
}
// Object.keys
Object.keys(obj).forEach(key => {
  console.log(key, obj[key].toUpperCase());
});

// 输出
// name ITSUKI
// address HANGZHOU

TypeScript

for...in

然而,在 TypeScript 中直接沿用上述写法会引发类型错误。

type Person = {
  name: string;
  address: string;
};
const obj: Person = {
  name: 'itsuki',
  address: 'hangzhou',
};
function print(obj: Person) {
  for (const key in obj) {
    // ❌
    // key:string 不能分配给 { name:string; age:number }类型
    console.log(key, obj[key].toUpperCase());
  }
}
print(obj)

鉴于 for...in 和 Object.keys 返回的是字符串类型的键,而对象的属性值类型可能不同,因此无法直接将字符串键分配给 Person 类型的 name 或 address 属性。

此时,我们可以利用 keyof 操作符来解决这一类型不匹配问题。

function print(obj:Person){
  let key: keyof Person;
  for (key in obj) {
    // ✅
    console.log(key, obj[key].toUpperCase());
  }
}

Object.keys

在使用 Object.keys 时,可以通过类型断言(as 运算符)来修正类型检查。

function print(obj: Person) {
  Object.keys(obj).forEach((k) => {
    // ✅
    console.log(k, obj[k as keyof Person].toUpperCase());
  });
}

我们可以将此类逻辑封装为一个通用函数:

function getKeys<T>(obj: T) {
  return Object.keys(obj) as Array<keyof T>;
}
getKeys(obj); // (keyof Person)[]

Object.entries

此外,还可以使用 Object.entries() 方法来遍历对象。

Object.entries(obj).forEach(([k, v]) => {
  console.log(k, v);
});

思考

以下是个人对类型系统的理解,若有误请指正。

我认为 Object.keys() 返回 string[] 是因为该操作在运行时确定,而 TypeScript 仅进行静态类型检查。即便使用 keyof Person 推导出的类型是 name | address,也无法保证运行时对象一定仅包含这两个字段。

例如:

const obj2 = {
  name: 'itsuki',
  address: 'hangzhou',
  age: 20,
};

print(obj2)
// 编译时: ✅, 因为它有name、address属性
// 运行时: ❌, 因为age字段是number, 没有toUpperCase方法

随后我在 GitHub issue 中找到了相关解释:

TS 中的类型是开放式的。因此,keyof 可能会少于在运行时获得的所有属性。

这进一步解释了为什么 keys() 返回的是 string[] 而非 (keyof Person)[]。

总结

至此,关于如何在 TypeScript 中正确遍历对象的内容介绍完毕,更多相关 TypeScript 遍历对象内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章