我们平常是对值编程,而泛型是对类型编程
一、初识泛型
1.1 keyof
可以用来取得一个对象接口的所有 key 值
interface Foo {
name: string;
age: number;
}
type FooKeys = keyof Foo; // 'name' | 'age'
1.2 in
in 则可以遍历枚举类型
type Keys = "a" | "b";
type obj = {
[p in Keys]: number;
};
let a: obj = {
a: 1,
b: 2,
};
1.3 infer
infer
这个关键字, 在条件类型语句中, 我们可以用 infer
声明一个类型变量并且对它进行使用
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
function add(params: string) {
return params;
}
type returnType = ReturnType<typeof add>;
infer R
就是声明一个变量来承载传入函数签名的返回值类型, 简单说就是用它取到函数返回值的类型方便之后使用.
1.4 Partial
Partial 作用是将传入的属性变为可选项.
源码:
type Partial<T> = { [P in keyof T]?: T[P] };
示例:
interface Person {
name: string;
sex: number;
age: number;
}
type newP = Partial<Person>;
// type newP = {
// name?: string;
// sex?: number;
// age?: number;
// }
1.5 Required
Required 的作用是将传入的属性变为必选项
源码:
type Required<T> = { [P in keyof T]-?: T[P] };
示例:
interface Person {
name?: string;
sex?: number;
age?: number;
}
type newP = Required<Person>;
// type newP = {
// name: string;
// sex: number;
// age: number;
// }
1.6 Readonly
将传入的属性变为只读选项
源码:
type Readonly<T> = { readonly [P in keyof T]: T[P] };
示例:
interface Person {
name: string;
sex?: number;
age?: number;
}
type newP = Readonly<Person>;
// type newP = {
// readonly name: string;
// readonly sex?: number;
// readonly age?: number;
// }
1.7 Record
将 K 中所有的属性的值转化为 T 类型
源码:
type Record<K extends keyof any, T> = { [P in K]: T };
示例:
interface PageInfo {
title: string;
}
type Page = "home" | "about" | "contact";
const nav: Record<Page, PageInfo> = {
about: { title: "about" },
contact: { title: "contact" },
home: { title: "home" },
};
1.8 Pick
从 T 中取出 一系列 K 的属性
源码:
type Pick<T, K extends keyof T> = { [P in K]: T[P] };
示例:
interface Person {
name: string;
age: number;
visiable: boolean;
}
type Person1 = Pick<Person, "name" | "age">;
1.9 extends
条件类型
type TypeName<T> = T extends string
? "string"
: T extends number
? "number"
: T extends boolean
? "boolean"
: T extends undefined
? "undefined"
: T extends Function
? "function"
: "object";
var a: TypeName<string> = "string";
1.10 Exclude
提取出 T 不包含在 U 中的元素
源码:
type Exclude<T, U> = T extends U ? never : T
示例:
type A = number | string | boolean;
type B = number | boolean;
type newFoo = Exclude<A, B>;
// 相当于
// type Foo = string;
1.11 Extract
Extract 的作用是提取出 T 包含在 U 中的元素
源码:
type Extract<T, U> = T extends U ? T : never;
示例:
type A = number | string | boolean
type B = number | boolean
type Foo = Extract<A, B>
// 相当于
type Foo = number | boolean
1.12 Omit
生成一个新类型,该类型拥有 T 中除了 K 属性以外的所有属性
源码:
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>
示例:
type Foo = {
name: string
age: number
}
type Bar = Omit<Foo, 'age'>
// 相当于
type Bar = {
name: string
}
二、类型
2.1 联合类型
满足其中之一的类型就可以了。
interface NAS {
host: string;
port: number;
}
interface OSS {
key: string;
secret: string;
port: number;
}
type MyStorage = NAS | OSS;
const storage: MyStorage = { host: "127.0.0.1", port: 80 };
2.2 交叉类型
满足所有的情况
interface NAS {
host: string;
port: number;
}
interface OSS {
key: string;
secret: string;
port: number;
}
type MyStorage = NAS & OSS;
const storage: MyStorage = { host: "127.0.0.1", port: 80, key: "", secret: "" };
2.3 条件类型
interface NAS {
host: string;
port: number;
}
interface OSS {
key: string;
secret: string;
port: number;
}
enum StorageType {
NAS,
OSS,
}
type MyStorage<T> = T extends StorageType.NAS
? NAS
: T extends StorageType.OSS
? OSS
: never;
const myStorage: MyStorage<StorageType.NAS> = {
host: "",
port: 0,
};
三、应用
3.1. 交集
交集的定义:对于给定的两个集合,返回一个包含两个集合中共有元素的新集合。
type Intersection<T, U> = Pick<
T,
Extract<keyof T, keyof U> & Extract<keyof U, keyof T>
>;
interface NAS {
host: string;
port: number;
}
interface OSS {
key: string;
secret: string;
port: number;
}
type JiaoJi = Intersection<NAS, OSS>;
3.2. 差集
差集的定义:对于给定的两个集合,返回一个包含所有存在于第一个集合且不存在于第二个集合的元素的新集合。
type Diff<T extends object, U extends object> = Pick<
T,
Exclude<keyof T, keyof U>
>;
type C1 = { name: string; age: number; visible: boolean };
type C2 = { name: string; age: number; sex: number };
type C11 = Diff<C1, C2>;
// type C11 = {
// visible: boolean;
// }
3.3. 并集
对于给定的两个集合,返回一个包含两个集合中所有元素的新集合。
type C1 = { name: string; age: number; visible: boolean };
type C2 = { name: string; age: number; sex: number };
type Compute<A extends any> = A extends Function ? A : { [K in keyof A]: A[K] };
type Merge<O1 extends object, O2 extends object> = Compute< O1 & Omit<O2, keyof O1>>;
type C1C2 = Merge<C1, C2>;
// type C1C2 = {
// name: string;
// age: number;
// visible: boolean;
// sex: number;
// }
覆盖并集
type C1 = { name: string; age: number; visible: boolean };
type C2 = { name: string; age: string; sex: number };
type Intersection<T, U> = Pick<
T,
Extract<keyof T, keyof U> & Extract<keyof U, keyof T>
>;
type Diff<T extends object, U extends object> = Pick<
T,
Exclude<keyof T, keyof U>
>;
type Overwrite<
T extends object,
U extends object,
I = Diff<T, U> & Intersection<U, T>
> = Pick<I, keyof I>;
type overwrite = Overwrite<C1, C2>;
// type overwrite = {
// name: string;
// age: string;
// visible: boolean;
// }
附录
参考连接:
https://www.typescriptlang.org/docs/handbook/utility-types.html
https://zhuanlan.zhihu.com/p/40311981
https://baijiahao.baidu.com/s?id=1717228098181547699&wfr=spider&for=pc
https://blog.csdn.net/azl397985856/article/details/106913210/