乐闻世界logo
搜索文章和话题

Typescript 如何遍历的 object 的 key ?

9 个月前提问
5 个月前修改
浏览次数193

6个答案

1
2
3
4
5
6

在TypeScript中,遍历对象的键可以使用几种不同的方法。以下是一些常用的方法:

1. for...in 循环

for...in 循环是JavaScript语言中遍历对象属性的传统方式。这种方法会遍历对象自己的属性以及原型链上可枚举的属性。

typescript
const obj = { a: 1, b: 2, c: 3 }; for (const key in obj) { if (obj.hasOwnProperty(key)) { console.log(key); // 输出 'a', 'b', 'c' } }

使用 hasOwnProperty 是为了确保只遍历对象自己的属性,而不包括原型链上的属性。

2. Object.keys()

Object.keys() 方法会返回一个包含对象自身可枚举属性名称的数组。

typescript
const obj = { a: 1, b: 2, c: 3 }; const keys = Object.keys(obj); keys.forEach(key => { console.log(key); // 输出 'a', 'b', 'c' });

这种方法不会遍历原型链上的属性。

3. Object.entries()

Object.entries() 方法返回一个给定对象自身可枚举属性的键值对数组。

typescript
const obj = { a: 1, b: 2, c: 3 }; for (const [key, value] of Object.entries(obj)) { console.log(key); // 输出 'a', 'b', 'c' }

类似于 Object.keys(),这种方法也不会包括原型链上的属性,并且提供了键和值。

4. Object.getOwnPropertyNames()

Object.getOwnPropertyNames() 方法返回一个数组,包含对象自身的所有属性(不仅仅是可枚举的属性)的名称。

typescript
const obj = { a: 1, b: 2, c: 3 }; const propertyNames = Object.getOwnPropertyNames(obj); propertyNames.forEach(name => { console.log(name); // 输出 'a', 'b', 'c' });

这个方法可以获得对象所有自有属性的名称,包括不可枚举的属性。

例子

假设我们有一个表示用户信息的对象,并想要遍历这个对象的键:

typescript
interface User { id: number; name: string; email: string; } const user: User = { id: 1, name: 'Jane Doe', email: 'jane.doe@example.com' }; Object.keys(user).forEach(key => { console.log(key); // 输出 'id', 'name', 'email' });

在这个例子中,我们使用了 Object.keys() 来遍历用户对象的键,并输出每个键。这种方法是常用且简洁的,适用于当你只需要对象的键时。

在TypeScript中使用这些方法时,也要注意对象的类型。如果对象的类型定义了可选属性或索引签名,那么在遍历时可能需要处理未定义的属性或动态键。

2024年6月29日 12:07 回复

你已经很接近了,你只需要将 替换=:. 您可以使用对象类型文字(请参阅规范第 3.5.3 节)或接口。使用对象类型文字与您所拥有的接近:

shell
var obj: { property: string; } = { property: "foo" };

但您也可以使用接口

shell
interface MyObjLayout { property: string; } var obj: MyObjLayout = { property: "foo" };
2024年6月29日 12:07 回复

更新 2019-05-15(改进的 Code Pattern 作为替代方案)

经过多年使用const功能更多的代码并从中受益后,我建议在大多数情况下不要使用我原来的答案(本节下面的标题,即在构建对象时,强制类型系统进入特定类型而不是让它推断类型通常是表明出现问题)。

相反,我建议const尽可能多地使用变量,然后作为最后一步组成对象:

shell
const id = getId(); const hasStarted = true; ... const hasFinished = false; ... return { hasStarted, hasFinished, id };
  • 这将正确键入所有内容,而无需显式键入。
  • 无需重新输入字段类型。
  • 根据我的经验,这会产生最干净的代码。
  • 这允许编译器提供更多的状态验证(例如,如果您在多个位置返回,编译器将确保始终返回相同类型的对象 - 这鼓励您在每个位置声明整个返回值 - 给出一个完全清晰的结果)该值的意图)。

奖励:可选字段 2022-09-29

shell
const id = getId(); const optionalField = getOptionalValue(); return { id, // This will always exist as a key in the object but it might be undefined optionalField, // This will only exist as a key in the object if it has a truthy value ...optionalField2 ? { optionalField } : {}, // This will only exist as a key in the object if it is not null or undefined ...optionalField2 != null ? { optionalField } : {}, };

添加 2020-02-26

如果您确实需要一个可以延迟初始化的类型:将其标记为可为空的联合类型(null 或 Type)。如果没有首先确保它具有值,类型系统将阻止您使用它。

在 中tsconfig.json,确保启用严格的 null 检查:

"strictNullChecks": true

然后使用此模式并允许类型系统保护您免受意外的空/未定义访问:

shell
const state = { instance: null as null | ApiService, // OR // instance: undefined as undefined | ApiService, }; const useApi = () => { // If I try to use it here, the type system requires a safe way to access it // Simple lazy-initialization const api = state?.instance ?? (state.instance = new ApiService()); api.fun(); // Also here are some ways to only access it if it has value: // The 'right' way: Typescript 3.7 required state.instance?.fun(); // Or the old way: If you are stuck before Typescript 3.7 state.instance && state.instance.fun(); // Or the long winded way because the above just feels weird if (state.instance) { state.instance.fun(); } // Or the I came from C and can't check for nulls like they are booleans way if (state.instance != null) { state.instance.fun(); } // Or the I came from C and can't check for nulls like they are booleans // AND I was told to always use triple === in javascript even with null checks way if (state.instance !== null && state.instance !== undefined) { state.instance.fun(); } }; class ApiService { fun() { // Do something useful here } }

99% 的情况下不要执行以下操作:

2016-02-10 更新 - 处理 TSX(感谢@Josh)

使用asTSX 操作员。

shell
var obj = { property: null as string };

一个更长的例子:

shell
var call = { hasStarted: null as boolean, hasFinished: null as boolean, id: null as number, };

原答案

使用强制转换运算符可以使其简洁(通过将 null 强制转换为所需的类型)。

shell
var obj = { property: <string> null };

一个更长的例子:

shell
var call = { hasStarted: <boolean> null, hasFinished: <boolean> null, id: <number> null, };

这比拥有两部分(第一部分声明类型,第二部分声明默认值)要好得多:

shell
var callVerbose: { hasStarted: boolean; hasFinished: boolean; id: number; } = { hasStarted: null, hasFinished: null, id: null, };
2024年6月29日 12:07 回复

我很惊讶没有人提到这一点,但您可以创建一个名为 的接口ObjectLiteral,它接受key: value类型对string: any

shell
interface ObjectLiteral { [key: string]: any; }

然后你会像这样使用它:

shell
let data: ObjectLiteral = { hello: "world", goodbye: 1, // ... };

额外的好处是,您可以根据需要在任意数量的对象上多次重复使用此界面。

祝你好运。

2024年6月29日 12:07 回复

您可以使用预定义的实用程序类型Record<Keys, Type>

shell
const obj: Record<string, string> = { property: "value", };

它允许为对象文字指定键:

shell
type Keys = "prop1" | "prop2" const obj: Record<Keys, string> = { prop1: "Hello", prop2: "Aloha", something: "anything" // TS Error: Type '{ prop1: string; prop2: string; something: string; }' is not assignable to type 'Record<Keys, string>'. // Object literal may only specify known properties, and 'something' does not exist in type 'Record<Keys, string>'. };

以及属性值的类型:

shell
type Keys = "prop1" | "prop2" type Value = "Hello" | "Aloha" const obj1: Record<Keys, Value> = { prop1: "Hello", prop2: "Hey", // TS Error: Type '"Hey"' is not assignable to type 'Value'. };
2024年6月29日 12:07 回复

如果您尝试编写类型注释,语法为:

shell
var x: { property: string; } = { property: 'hello' };

如果您尝试编写对象文字,语法为:

shell
var x = { property: 'hello' };

您的代码尝试在值位置使用类型名称。

2024年6月29日 12:07 回复

你的答案