一、extends
这里主要介绍下 extends 关键字在 TS 中的两种用法,即接口继承和条件判断。
1、接口继承
extends 做继承功能,同 ES6 的 Class 语法用它来做类的继承用法类似。实例代码如下:
interface IName {
name: string
}
interface IAge {
age: number
}
interface IPerson extends IAge, IName {
sex: string
}
const obj: IPerson = {
age: 18,
name: 'Jenny',
sex: '女'
}
上述代码中,IAge 和 IName 两个接口,分别定义了 age,name属性,IPerson 则使用 extends 多重继承的方法,继承了 IAge 和 IName,同时定义了自身属性 sex,此时 IPerson 除了自身属性外,还同时拥有了来自 IAge 和 IName 的属性。
2、条件判断
条件判断会以一个条件表达式进行类型关系检测,从而在两种类型中选择其一。
T extends U ? X : Y
上述代码含义为:如果 T 包含的类型是 U 包含的类型的 ‘子集’,那么取结果 X,否则取结果 Y。
实现一个简单的示例代码:
type WhatType<T> = T extends null | undefined ? never : T
let typeString: WhatType<string> = 'abc' // string 类型
let typeNull: WhatType<null> // never 类型
上述代码含义为:如果泛型参数 T 为 null 或 undefined,那么取 never,否则直接返回 T。
二、infer
在条件类型语句中,可以用 infer 声明一个类型变量,并且对它进行使用。
infer 可以在 extends 的条件语句中推断待推断的类型。示例代码如下:
type ParamType<T> = T extends (...args: infer P) => any ? P : T;
interface User {
name: string;
age: number;
}
type Func = (user: User) => void;
type Param = ParamType<Func>; // Param = User
type AA = ParamType<string>; // string
三、keyof - 枚举类型(可以理解为 keyof 对象类型)
keyof 操作符用来获取某种类型的所有 key 值,返回一个联合类型。示例代码如下:
interface IPerson {
name: string,
age: number
}
type allKey1 = keyof IPerson // 'name' | 'age'
type allKey2 = keyof IPerson[] // 'length | 'toString | 'pop' | 'push' | 'concat' | 'join' | ......
type allKey3 = keyof { [x: string]: IPerson } // string | number
四、typeof
typeof 操作符用来在类型上下文中获取变量或者属性的类型。示例代码如下:
interface IPerson {
name: string,
age: number
}
const user: IPerson = {
name: 'jenny',
age: 18
}
type student = typeof user // IPerson
五、in - 枚举类型
in 操作符用来遍历枚举类型。示例代码如下:
type keys = 'a' | 'b' | 'c'
type obj = {
[p in keys]: any
} // { a: any, b: any, c: any}
六、Partial - 对象类型
Partial 的作用是将某个类型里的属性全部变成可选,该方法是联合了 keyof 和 in 实现的。
type Partial<T> = {
[P in keyof T]?: T[P]
}
以上代码中,首先通过 keyof T 拿到 T 的所有属性名,然后使用 in 进行遍历,将值赋给 P,最后通过 T[P] 取得相应的属性值。中间的 ? 号,用于将所有属性变为可选。示例代码如下:
interface IPerson {
name: string,
age: number
}
type person = Partial<IPerson>
// 相当于
// type person = {
// name?: string | undefined;
// age?: number | undefined;
// }
七、Required - 对象类型
Required 的作用就是将某个类型中的属性全部变为必选。
type Required<T> = {
[P in keyof T]-?: T[P];
};
-? 的作用就是把可选属性的可选性去掉,使该属性变成必选项。示例代码如下:
interface IPerson {
name?: string,
age?: number
}
type person = Required<IPerson>
// 相当于
// type person = {
// name: string;
// age: number;
// }
八、Readonly - 对象类型
Readonly 的作用是将某个类型所有属性变为只读属性,也就意味着这些属性不能被重新赋值。
type Readonly<T> = {
readonly [P in keyof T]: T[P]
}
在每一个 key 前面加上 readonly。示例代码如下:
interface IPerson {
name: string,
age: number
}
type person = Readonly<IPerson>
// 相当于
// type person = {
// readonly name: string;
// readonly age: number;
// }
const obj:person = {
name: 'lucy',
age: 18
}
// 此处 TS 会报错:无法为 name 重新赋值,因为它是只读属性
obj.name="jenny"
九、Mutable - 对象类型
Mutable 的作用是将 T 中所有属性的 readonly 移除。
type Mutable<T> = {
-readonly [P in keyof T]: T[P]
}
在每一个 key 前面加上 -readonly。示例代码如下:
interface IPerson {
readonly name: string,
readonly age: number
}
type person = Mutable<IPerson>
// 相当于
// type person = {
// name: string;
// age: number;
// }
十、Exclude - 枚举类型
Exclude<T, U> 的作用是将某个类型中属于另一个的类型移除掉。
type Exclude<T, U> = T extends U ? never : T;
实现效果为从 T 中去除 T 与 U 的交集后的类型。示例代码如下:
type exclude0 = Exclude<string | number | boolean, number> // string | boolean
type exclude1 = Exclude<'a' | 'b' | 'c', 'a' | 'c'> // 'b'
十一、Extract - 枚举类型
Extract<T, U> 的作用是将某个类型中属于另一个的类型提取出来。
type Extract<T, U> = T extends U ? T : never;
这个和上面的 Exclude 恰好相反,实现效果为从 T 中提取 T 与 U 的交集类型。示例代码如下:
type extract0 = Extract<string | number | boolean, number> // number
type extract1 = Extract<'a' | 'b' | 'c', 'a' | 'c'> // 'a' | 'c
十二、Pick - 对象类型
Pick<T, K extends keyof T> 的作用是将某个类型中的子属性挑出来,变成包含这个类型部分属性的子属性。
type Pick<T, K extends keyof T> = {
[P in K]: T[P]
}
T 是多类型,K 是 T 的部分类型,然后遍历 K 拿到键,再去 T 里拿到相应的值。简单来说就是:
从 T 中提取出 T 与 K 属性值相同的属性。示例代码如下:
interface IPerson {
name: string,
age: number,
sex: string
}
type person = Pick<IPerson, 'name'>
const user: person = {
name: 'jenny',
age: 18 // TS 提示报错,age 不在 person 类型中
}
Pick 与 Extract 都有从 T 中提取 T 与 K 相交的那部分,它们的区别在于 Pick 作用于对象类型,返回的类型用于定义对象;Extract 作用与枚举类型,返回的类型用于定义枚举类型变量。
十三、Record
Record<K extends keyof any, T> 的作用是将 K 中所有的属性的值转换为 T 类型。
type Record<K extends keyof any, T> = {
[P in K]: T
}
将 K 中有类型的属性进行遍历,再将每个 key 赋值为 T 类型。示例代码如下:
type record0 = Record<'a' | 'b', number>
// 相当于
// type record0 = {
// a: number,
// b: number
// }
十四、Omit
Omit<T, K extends keyof any> 的作用是使用 T 类型中除了 K 类型的所有属性。
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>
实现效果为从对象 T 中剔除 key 为 K 中的属性。
interface IPerson {
name: string,
age: number,
sex: string
}
type person = Omit<IPerson, 'name'>
// 相当于
// type person = {
// age: number,
// sex: string
// }
十五、ReturnType
ReturnType 的作用是用于获取函数 T 的返回类型。
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
示例代码如下:
type T1 = ReturnType<() => string> // string
type T2 = ReturnType<(s: string) => void> // void
十六、 NonNullable - 枚举类型
NonNullable 的作用是剔除 T 为 null、undefined 的类型。
type NonNullable<T> = T extends null | undefined ? never : T;
示例代码如下:
type T = NonNullable<string | string[] | null | undefined> // string | string[]
原文链接:https://blog.csdn.net/lhz_333/article/details/124468366