在TypeScript类型操作中typeof和in经常放在一起使用,使用频率也很高,因此将这两个关键字放在一起介绍。
keyof
使用
keyof操作符接受一个对象类型作为参数,返回该对象属性名组成的字面量联合类型
1 | type Dog = { name: string; age: number; }; |
在一些高级类型中经常会用到keyof any, 这又是什么鬼?鼠标放上去看看就知道了
可以看到keyof any 返回的是一个联合类型:string | number | symbol,结合前文说到keyof是为了取得对象的key值组成的联合类型,那么key值有可能是什么类型呢?自然就是string | number | symbol。
该关键字一般会和extends关键字结合使用,对对象属性的类型做限定,比如K extends keyof any就代表K的类型一定是keyof any所返回的联合类型的子类,如果输入不符合限定,那么自然也就不能作为对象的属性,类型系统就会报错。
因此,keyof any 表示了对象key值可能的取值类型。这一点在本文之后的一些类型实现中也会用到。
注意点
遇到索引签名时,typeof会直接返回其类型
1 | type Dog = { [y:number]: number }; |
可以看到索引类型为number时,keyof 返回的类型是string | number, 这是因为JavaScript的对象属性会默认转换为字符串。
in
in的右侧一般会跟一个联合类型,使用in操作符可以对该联合类型进行迭代。
其作用类似JS中的for...in或者for...of
1 | type Animals = 'pig' | 'cat' | 'dog' |
类型操作实战
Partial & Required
Partial:将某个类型里的属性全部变为可选项
思路是通过泛型传入待处理类型,先用keyof取到所给类型所有属性组成的字面量联合类型,然后使用in进行遍历,同时结合 ?操作符,将每个属性变成可选的
1 | type Partial<T> = { |
[P in keyof T]这段代码表示遍历T中的每一个属性,那么T[P]就是每个属性所对应的值,可以简单理解为前者取的是键key,后者取的是值value
Required:和Partial的作用相反,是为了将某个类型里的属性全部变为必选的
1 | interface Props { |
实现思路和前面相似
1 | type Partial<T> = { |
上文对应的-?代表着去掉可选,与之对应的还有+?,两者正好相反