如何在TypeScript中正确的遍历一个对象

作者:你要不要喝奶茶 时间:2024-04-25 13:09:36 

JavaScript

在讲解用 Ts 遍历一个对象之前, 我们先说说 在 Js 中怎么实现, 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拿到的是对象的 key, 而在对象中所有的 key 都是字符串, 所以它无法分配给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 中的类型是开放式的。因此, keysof 可能会少于在运行时获得的所有属性。

它更要我明白了, 为什么keys()返回的是一个string[], 而不是一个(keyof Person)[].

来源:https://juejin.cn/post/7079687437445922853

标签:typescript,遍历,对象
0
投稿

猜你喜欢

  • JS基于设计模式中的单例模式(Singleton)实现封装对数据增删改查功能

    2024-04-29 14:08:48
  • flask框架自定义过滤器示例【markdown文件读取和展示功能】

    2023-03-07 19:22:27
  • Centos7 下Mysql5.7.19安装教程详解

    2024-01-25 08:28:18
  • SQL 联合查询与XML解析实例详解

    2024-01-26 18:26:58
  • 谈谈Python进行验证码识别的一些想法

    2022-09-19 12:50:53
  • ASP页面内VBScript和JScript的交互

    2007-09-11 13:49:00
  • 实例验证MySQL|update字段为相同的值是否会记录binlog

    2024-01-21 01:37:40
  • pycharm如何为函数插入文档注释

    2023-09-13 09:53:56
  • 详解python第三方库的安装、PyInstaller库、random库

    2023-03-13 06:57:46
  • vue-cli 引入jQuery,Bootstrap,popper的方法

    2024-05-21 10:17:21
  • django中操作mysql数据库的方法

    2024-01-18 13:37:55
  • python3.4中清屏的处理方法

    2023-11-14 04:09:21
  • JS定时器实例

    2024-04-29 13:25:21
  • SQL Server 2008网络协议深入理解

    2024-01-17 02:42:34
  • SQL Server 2016 配置 SA 登录教程

    2024-01-13 10:17:53
  • Python 面向对象编程的三大特性之继承

    2021-08-18 18:19:04
  • python 平衡二叉树实现代码示例

    2022-04-24 03:20:34
  • 详解ES6之async+await 同步/异步方案

    2023-08-24 11:10:54
  • 在 CentOS 7 中安装 MySQL 8 的教程详解

    2024-01-17 03:33:56
  • Python 25行代码实现的RSA算法详解

    2023-04-06 17:05:58
  • asp之家 网络编程 m.aspxhome.com