在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> = { |
上文对应的-?
代表着去掉可选,与之对应的还有+?
,两者正好相反