typescript中循环对象(for...in)的类型问题 keyof

290 阅读2分钟

1)、 在js里,对象的键是变量没有问题。直接使用: 对象[键名]

2)、在ts里,就需要对键名做专门的类型定义

一、定义对象时,明确写出键和值的取值类型

let obj: { [key: string]: any }

表示obj变量是对象类型,键是字符串类型,值是any类型。代码如下:

1、给对象定义类型时,明确写出对象的键的类型和可接受的值的类型。
​
如:
let obj: { [key: string]: any }
表示obj变量是对象类型,键是字符串类型,值是any类型。
​
obj = { name: "张三疯", age: 12 };
​
for (const key in obj) {
  console.log(`${key}: ${obj[key]}`);
}
​
再如:
let obj: { [key: string]: (number | string) }
表示obj变量是对象类型,键是字符串类型,值是number | string 类型。
obj = { name: "张三疯", age: 12 };
​
for (const key in obj) {
  console.log(`${key}: ${obj[key]}`);
}
​

注意:key取值只能是string,number,symbol,或者 template literal type(模板文字类型)

二、如果定义对象时,对象的属性名和类型都对应的明确了

(如:用interface或者type定义了对象类型)。

就可以使用 keyof 的方式限制键的取值可能性。如下示例。要注意看注释

interface IBanner {
  img: string;
  alt: string;
  link: string;
}
​
let obj: IBanner;
obj = {
  "img":"hello",
  "alt":"这是一张图片",
  "link":"https://blog.csdn.net/jiang7701037"
};
​
// 下面这句话限定了key的取值只能是字符串:"img","alt","link",
let key:keyof typeof obj;//或者:let key:keyof IBanner;
for(key in obj){
  console.log(`${key}: ${obj[key]}`);
  //???如果企图在这里面给 obj[key]赋值的话,是做不到的。因为,ts对obj[key]推论出的类型是never。
}
​
// key ="img";
key ="hello";//不能这样赋值,因为 key的取值只能是字符串:"img""alt""link" 三者之一。

三、再看一个稍微复杂一点的例子。也是用了keyof

interface ITypeIndex {
  extralarge: "extralarge";
  major: "major";
  ordinary: "ordinary";
}
​
// 定义对象类型
interface IState{
  text:string,
  count:number;
  type:keyof ITypeIndex; //此处如果写成字符串是不行的, keyof ITypeIndex就是类型的定义。
}
​
// 定义对象数组
const states:IState[] = [
  {
    text:"特大",
    count:2,
    type:"extralarge"
  },
  {
    text:"重大",
    count:10,
    type:"major"
  },
  {
    text:"一般",
    count:20,
    type:"ordinary"
  }
]
​
​
interface IObj {
  extralarge: number;
  major: number;
  ordinary: number;
}
​
​
const obj:IObj = {
  extralarge: 1,
  major: 2,
  ordinary: 3,
}
​
​
states.forEach(item=>{
  console.log(obj[item.type]);
})
​