TypeScript实例讲解(二十一)

494 阅读2分钟

这是我参与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 语法来优化了之前的问题,keyofPerson 接口的每一个属性值做了一次遍历,看上去这块代码还是比较复杂。优化后 keyname 时为 string 类型;keyage 时为 number 类型,此时已经就是最优的写法了。

如果类里面有一个对象,需要根据 index 或者 key 值去获取对象里面的某一项内容,同时又需要推断出返回内容的类型,这时候就可以使用到例3中 T extends keyof Person 这样比较复杂的语法。

本篇完!如果文章对你有一点点帮助,请记得点个赞哦。