# How to correctly traverse an object in Ts

How to correctly traverse an object in Ts

Article first published on personal blog

This is a short essay...

JavaScript

Before explaining how to traverse an object with Ts, let's talk about how to implement it in Js, for...in, Object.keys, a simple example:

// 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

But in TypeScript, if you use it directly, you will find an error.

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)
复制代码

What we know for...inand Object.keysget is the key of the object, and all keys in the object are strings, so it cannot be assigned Personto name, address.

But we can keyofsolve this problem.

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

Object.keys

When used Object.keys, we can use asoperators to solve.

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

复制代码

We can abstract this out into a function:

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

getKeys(obj); // (keyof Person)[]
复制代码

Object.entries

We can also use Object.entries()to iterate over objects.

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

think

The following is my own thinking, if I am wrong, please correct me

What I want to Object.keys()return is one string[]because it is determined at runtime and we know TypeScriptit's just a static type check, even if we use keyof Personreturn name | address, but we can't be sure at runtime it's the two fields.

For example:

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

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

Then I found this sentence in the Github issue:

Types in TS are open ended. Therefore, keysofthere may be less than all properties obtained at runtime.

It made me understand even more why it was keys()returning one string[]instead of one (keyof Person)[].

Guess you like

Origin juejin.im/post/7079687437445922853