这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战
接上一篇:TypeScript实例讲解(二十)
本篇内容:TypeScript 泛型中 keyof 的使用。
// 例 1
interface Person {
name: string;
age: number;
}
class Student {
constructor(private info: Person) {}
getInfo(key: string) {
return this.info[key] // 提示错误
}
}
const student = new Student({
name: 'bear',
age: 20
});
student.getInfo('name'); // bear
例1 Student 类接收一个 Person 类型的数据,并存到 info 变量里面。另外定义了一个 getInfo() 方法,它的作用是通过 key 获取对应的值。
注意观察这段代码最后是能够编译成功的,因为最后我们通过 key 获取到了对应的值 bear。但是方法中的 this.info[key] 这里是提示错误了的。原因是我们传 key 值到 getInfo() 方法的时候无法保证 key 的取值是 name 或者是 age 这两个值中的其中一个,如果传了一个之外的 key 值则会返回 undefined 。
为了解决上面的问题,需要增加一种保护机制。
// 例 2(完善例1)
class Student {
constructor(private info: Person) {}
getInfo(key: string) {
if (key === 'name' || key === 'age') {
return this.info[key]
}
}
}
经过完善之后不再提示错误,但是又有一个问题:student.getInfo('name') 的类型是 string | number | undefined,因为我们传的 key 值不定,返回的类型也不定,TypeScript不会更深度的帮我们判断,只是大致地分析一下可能传入的值是 name ,也可能是 age,还可能是其他的。这样看上去还是不够完美。
// 例 3(优化例1)
class Student {
constructor(private info: Person) {}
getInfo<T extends keyof Person>(key: T): Person[T]{
return this.info[key]
}
}
例3用泛型结合 keyof 语法来优化了之前的问题,keyof 对 Person 接口的每一个属性值做了一次遍历,看上去这块代码还是比较复杂。优化后 key 为 name 时为 string 类型;key 为 age 时为 number 类型,此时已经就是最优的写法了。
如果类里面有一个对象,需要根据 index 或者 key 值去获取对象里面的某一项内容,同时又需要推断出返回内容的类型,这时候就可以使用到例3中 T extends keyof Person 这样比较复杂的语法。
本篇完!如果文章对你有一点点帮助,请记得点个赞哦。