TypeScript 的一些工具泛型
2021/05/27
先来看一下它们的源码:
/**
* 让 T 中所有属性都变为可选
*/
type Partial<T> = {
[P in keyof T]?: T[P];
};
/**
* 让 T 中所有属性都变为只读
*/
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
/**
* 从 T 中,选取指定一组属性,返回一个新的类型定义。
*/
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
/**
* 构造一个 key 是 K 中属性且类型是 T 的类型
*/
type Record<K extends keyof any, T> = {
[P in K]: T;
};
/**
* 从 T 中找出 U 中没有的元素(从 T 中排除 U )
*/
type Exclude<T, U> = T extends U ? never : T;
/**
* 从 T 中找出 U 中有的元素(从 T 中取出 U )
*/
type Extract<T, U> = T extends U ? T : never;
/**
* 从 T 中取出 K 中没有的属性(忽略 K 中存在的属性)
*/
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
/**
* 获取函数的返回类型
*/
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
/**
* 让 T 中所有属性都变为可选
*/
type Partial<T> = {
[P in keyof T]?: T[P];
};
/**
* 让 T 中所有属性都变为只读
*/
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
/**
* 从 T 中,选取指定一组属性,返回一个新的类型定义。
*/
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
/**
* 构造一个 key 是 K 中属性且类型是 T 的类型
*/
type Record<K extends keyof any, T> = {
[P in K]: T;
};
/**
* 从 T 中找出 U 中没有的元素(从 T 中排除 U )
*/
type Exclude<T, U> = T extends U ? never : T;
/**
* 从 T 中找出 U 中有的元素(从 T 中取出 U )
*/
type Extract<T, U> = T extends U ? T : never;
/**
* 从 T 中取出 K 中没有的属性(忽略 K 中存在的属性)
*/
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
/**
* 获取函数的返回类型
*/
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
Record
以 keyof 格式快速创建一个类型,此类型包含一组指定的属性且都是必填。
type k1 = Record<string | number, number | string>
// 相当于
type k1 = {
[x: string]: string | number,
[x: number]: string | number,
}
type k1 = Record<string | number, number | string>
// 相当于
type k1 = {
[x: string]: string | number,
[x: number]: string | number,
}
Partial
将类型定义的所有属性都修改为可选。
interface Person {
name: string,
age: number
}
type k1 = Partial<Person>
// 等同于
type k1 = {
name?: string;
age?: number;
}
interface Person {
name: string,
age: number
}
type k1 = Partial<Person>
// 等同于
type k1 = {
name?: string;
age?: number;
}
Readonly
将类型定义的所有属性改为只读。
interface Person {
name: string,
age: number
}
type k1 = Readonly<Person>;
// 等同于
type k1 = {
readonly name: string;
readonly age: number;
}
interface Person {
name: string,
age: number
}
type k1 = Readonly<Person>;
// 等同于
type k1 = {
readonly name: string;
readonly age: number;
}
Pick
从类型定义的属性中,选取指定一组属性,返回一个新的类型定义。
interface Person {
name: string,
age: number
}
type k1 = Pick<Person, 'name'>
// 相当于
type k1 = {
name: string
}
interface Person {
name: string,
age: number
}
type k1 = Pick<Person, 'name'>
// 相当于
type k1 = {
name: string
}
Exclude
从 T 中找出 U 中没有的元素(通俗来讲就是从 T 中排除 U )。
type k1 = Exclude<'name' | 'age', 'name'>
// 相当于
type k1 = 'age'
type k1 = Exclude<'name' | 'age', 'name'>
// 相当于
type k1 = 'age'
Extract
作用与 Exclude
相反,从 T 中找出 U 中有的元素(通俗来讲就是从 T 中取出 U )。
type k1 = Extract<'name' | 'age', 'name'>
// 相当于
type k1 = 'name'
type k1 = Extract<'name' | 'age', 'name'>
// 相当于
type k1 = 'name'
Omit
用 Pick
和 Exclude
进行组合, 忽略对象某些属性功能。
type k1 = Omit<{name: string, age: number}, 'name'>
// 相当于
type k1 = {
age: number
}
type k1 = Omit<{name: string, age: number}, 'name'>
// 相当于
type k1 = {
age: number
}
ReturnType
获取函数的返回类型。
理解 ReturnType
需要先来了解 infer
, infer
表示在 extends
条件语句中待推断的类型变量。
一个例子:
type ParamType<T> = T extends (...args: infer P) => any ? P : T;
type fn = (str: string) => void;
type k1 = ParamType<fn> // string,返回了 fn 类型参数的类型
type ParamType<T> = T extends (...args: infer P) => any ? P : T;
type fn = (str: string) => void;
type k1 = ParamType<fn> // string,返回了 fn 类型参数的类型
如果 T 能赋值给 (...args: infer P) => any
,则结果是 (...args: infer P) => any
类型中的参数 P,否则返回为 T。
再回到 ReturnType
,如果传入的是一个函数就返回函数的返回值的类型,否则返回 any
。
// getInt 函数接收一个字符串,然后将其转换成整数值
const getInt = (str: string) => {
return parseInt(str);
};
type k1 = ReturnType<typeof getInt>; // number
// getInt 函数接收一个字符串,然后将其转换成整数值
const getInt = (str: string) => {
return parseInt(str);
};
type k1 = ReturnType<typeof getInt>; // number