TypeScript类型实现
参考:https://wangtunan.github.io/blog/typescript/challenge.html#%E4%BB%8B%E7%BB%8D
初级
内置Pick(选取)
Pick表示从一个类型中选取指定的几个字段组合成一个新的类型
type Person = {
name: string;
age: number;
address: string;
sex: number;
}
type MyPick<T,K extends keyof T> = {
[P in K]:T[P]
}
type PickResult = MyPickPerson, 'name' | 'address'>
代码详解:
keyof:操作符提取其属性的名称,K extends keyof T:表示K只能是keyof T的子类型,如果我们在使用Pick的时候传递了不存在于T的字段,会报错:
内置Readonly(只读)
Readonly是用来让所有属性变为只读,其用法为:
type MyReadonly<T> = {
readonly [P in keyof T]:T[P]
}
// 结果:{ readonly name: string; readonly age: number; readonly address:string;readonly sex:number;}
type ReadonlyResult = MyReadonly<Person>
内置Exclude(排除)
Exclude是排除的意思,它从T类型中排除属于U类型的子集,可以理解成取T对于U的差集,用法如下:
// 结果:'name'|'age'
type ExcludeResult = Exclude<'name'|'age'|'sex', 'sex'|'address'>
// 实现
type MyExclude<T, U> = T extends U ? never : T
T extends U:这段代码会从T的子类型开始分发,例如:
T extends U
=> 'name'|'age'|'sex' extends 'sex'|'address'
=> (
'name' extends 'sex'|'address' ? never : 'name' |
'age' extends 'sex'|'address' ? never : 'age' |
'sex' extends 'sex'|'address' ? never : 'sex'
)
=> 'name'|'age'
在类型系统中,属性更多的类型是子类型
- 子类型是可以赋值给父类型的,也就是
父类型变量 = 子类型变量是安全的,因为子类型上涵盖了父类型所拥有的的一切属性- 如果父类型赋值给子类型就会有问题,因为父类型的属性较少,父类型可能会缺少子类型的属性,因此会发生类型错误
内置Extract(交集)
Extract<T, U>用来取联合类型T和U的交集,用法如下:
Length(元组的长度)
type Lenth<T extends any> = T extends {length:number}?T['length']:never
type result = Lenth<[1,2,3]>
代码详解:
T extends { length: number; }:判断T是否是{ length: number; }的子类型,如果是则代表T为数组或者类数组。T['length']:取T对象的length属性的值(注意,在TypeScript中不能使用T.length来取值,而应该使用T['length'])
注意,在ts中,取类型的属性,不能使用
Type.Prop来获取,应通过Type[prop]中括号来读取属性值 比如:T.length【X】T['length']) 【√】