持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天, 点击查看活动详情
在
TypeScript
类型操作中
typeof
和
in
经常放在一起使用,使用频率也很高,因此将这两个关键字放在一起介绍。
keyof
keyof
操作符接受一个对象类型作为参数,返回该对象属性名组成的
字面量联合类型
type Dog = { name: string; age: number; };
type D = keyof Dog; //type D = "name" | "age"
在一些高级类型中经常会用到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
会直接返回其类型
type Dog = { [y:number]: number };
type dog = keyof Dog; //type dog = number
type Doggy = { [y:string]: boolean };
type doggy = keyof Doggy; //type doggy = string | number
type Doggy = { [y:string]: unknown, [x:number]: boolean};
type doggy = keyof Doggy; //type doggy = string | number
可以看到索引类型为string
时,keyof
返回的类型是string | number
, 这是因为JavaScript
的对象属性会默认转换为字符串。
in
的右侧一般会跟一个联合类型,使用in
操作符可以对该联合类型进行迭代。
其作用类似JS
中的for...in
或者for...of
type Animals = 'pig' | 'cat' | 'dog'
type animals = {
[key in Animals]: string
// type animals = {
// pig: string; //第一次迭代
// cat: string; //第二次迭代
// dog: string; //第三次迭代
类型操作实战
Partial & Required
Partial
:将某个类型里的属性全部变为可选项
思路是通过泛型传入待处理类型,先用keyof
取到所给类型所有属性组成的字面量联合类型,然后使用in
进行遍历,同时结合 ?
操作符,将每个属性变成可选的
type Partial<T> = {
[P in keyof T]?: T[P]
[P in keyof T]
这段代码表示遍历T
中的每一个属性,那么T[P]
就是每个属性所对应的值,可以简单理解为前者取的是键key
,后者取的是值value
Required
:和Partial
的作用相反,是为了将某个类型里的属性全部变为必选的
interface Props {
a?: number;
b?: string;
const obj: Props = { a: 5 }; // b是可选的,因此缺少这个属性也可以
const obj2: Required<Props> = { a: 5 }; // 通过Required将属性变为必选的,等号右边对象缺少这个属性,因此赋值失败
//Property 'b' is missing in type '{ a: number; }' but required in type 'Required<Props>'.
实现思路和前面相似
type Partial<T> = {
[P in keyof T]-?: T[P]
上文对应的-?
代表着去掉可选,与之对应的还有+?
,两者正好相反