1.
keyof
和in
1.1
keyof
keyof
与Object.keys
略有相似,只不过keyof
取interface
的键
interface Point { x: number; y: number; } // type keys = "x" | "y" type keys = keyof Point;
假设有一个
object
如下所示,我们需要使用typescript
实现一个get
函数来获取它的属性值
const data = { a: 3, hello: 'world' } function get(o: object, name: string) { return o[name] }
我们刚开始可能会这么写,不过它有很多缺点
- 无法确认返回类型:这将损失
ts
最大的类型校验功能- 无法对
key
做约束:可能会犯拼写错误的问题这时可以使用
keyof
来加强get
函数的类型功能
function get<T extends object, K extends keyof T>(o: T, name: K): T[K] { return o[name] }
1.2
in
in
则可以遍历枚举类型,例如
type Keys = "a" | "b" type Obj = { [p in Keys]: any } // -> { a: any, b: any }
keyof
产生枚举类型,,in
使用枚举类型遍历,所以他们经常一起使用,看下 Partial 源码
type Partial<T> = { [P in keyof T]?: T[P] };
上面语句的意思是
keyof T
拿到T
所有属性名,然后in
进行遍历,将值赋给 P,最后T[P]
取得相应属性的值
2.
Required
&Partial
&Pick
type Required<T> = { [P in keyof T]-?: T[P]; }; type Partial<T> = { [P in keyof T]?: T[P]; }; type Pick<T, K extends keyof T> = { [P in K]: T[P]; }; interface User { id: number; age: number; name: string; }; // 相当于: type PartialUser = { id?: number; age?: number; name?: string; } type PartialUser = Partial<User> // 相当于: type PickUser = { id: number; age: number; } type PickUser = Pick<User, "id" | "age">
这几个类型已内置在
Typescript
中
3.
Condition Type
类似于
js
中的 三目 运算符,可以使用它扩展一些基本类型
T extends U ? X : Y type isTrue<T> = T extends true ? true : false // 相当于 type t = false type t = isTrue<number> // 相当于 type t = false type t1 = isTrue<false>
4.
never
&Exclude
&Omit
type Exclude<T, U> = T extends U ? never : T; // 相当于: type A = 'a' type A = Exclude<'x' | 'a', 'x' | 'y' | 'z'>
结合
Exclude
可以推出Omit
的写法
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>; interface User { id: number; age: number; name: string; }; // 相当于: type PickUser = { age: number; name: string; } type OmitUser = Omit<User, "id">
5. ?
interface
&type
的区别
一般来说,
interface
与type
区别很小,比如以下两种写法差不多
interface A { a: number; b: number; }; type B = { a: number; b: number; }
其中
interface
可以如下合并多个,而type
只能使用&
类进行连接
interface A { a: number; } interface A { b: number; } const a: A = { a: 3, b: 4 }
最后考大家一个ts 问题 如何从一个接口中 过滤出 想要的数据类型呢 ,这个类型怎么写???
这个源码中经常出现类似的,ts 中的高级过滤类型
type Filter<Source,Condition> = Pick<Source,{ [K in keyof Source]: Source[K] extends Condition ? K : never }[keyof Source]> interface Example { a:string, b:string, c:number, } type Test = Filter<Example, string>