Cómo atravesar correctamente un objeto en Ts
Artículo publicado por primera vez en blog personal
Este es un breve ensayo...
JavaScript
Antes de explicar cómo atravesar un objeto con Ts, hablemos de cómo implementarlo en Js, for...in
, Object.keys
, un ejemplo simple:
// 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
复制代码
Mecanografiado
para... en
Pero en TypeScript, si lo usa directamente, encontrará un 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)
复制代码
Lo que conocemos for...in
y Object.keys
obtenemos es la clave del objeto, y todas las claves del objeto son cadenas, por lo que no se puede asignar Person
a name
, address
.
Pero podemos keyof
resolver este problema.
function print(obj:Person){
let key: keyof Person;
for (key in obj) {
// ✅
console.log(key, obj[key].toUpperCase());
}
}
复制代码
Objeto.claves
Cuando se usa Object.keys
, podemos usar as
operadores para resolver.
function print(obj: Person) {
Object.keys(obj).forEach((k) => {
// ✅
console.log(k, obj[k as keyof Person].toUpperCase());
});
}
复制代码
Podemos abstraer esto en una función:
function getKeys<T>(obj: T) {
return Object.keys(obj) as Array<keyof T>;
}
getKeys(obj); // (keyof Person)[]
复制代码
Objeto.entradas
También podemos usar Object.entries()
para iterar sobre objetos.
Object.entries(obj).forEach(([k, v]) => {
console.log(k, v);
});
复制代码
pensar
Lo siguiente es mi propio pensamiento, si me equivoco, por favor corrígeme.
Lo que quiero Object.keys()
devolver es uno string[]
porque se determina en tiempo de ejecución y sabemos TypeScript
que es solo una verificación de tipo estático, incluso si usamos keyof Person
return name | address
, pero no podemos estar seguros en tiempo de ejecución de que sean los dos campos.
Por ejemplo:
const obj2 = {
name: 'itsuki',
address: 'hangzhou',
age: 20,
};
print(obj2)
// 编译时: ✅, 因为它有name、address属性
// 运行时: ❌, 因为age字段是number, 没有toUpperCase方法
复制代码
Luego encontré esta oración en el problema de Github:
Los tipos en TS son abiertos. Por lo tanto,
keysof
puede haber menos de todas las propiedades obtenidas en tiempo de ejecución.
Me hizo entender aún más por qué keys()
devolvía uno string[]
en lugar de uno (keyof Person)[]
.