详解Typescript常用的高级类型
Mercer-Lee的空间 2020-06-29
TS
JS
TS中有官方给出的高级类型来辅助我们日常开发,但是无论是书本还是文档讲的都不是很清晰,网上的文章更是生涩难懂,故写下这篇文章来记录和帮助需要的人。
# 前置知识:keyof
首先在了解高级类型之前要先理解keyof:
interface User {
name: string;
mobile: string;
}
type keys = keyof User; // 相当于type keys = 'name' | 'mobile'
从上面可以看出,keyof是取interface的键。理解了keyof才能理解后面的高级类型:Record、Pick。
# 前置知识:Mapped types
Mapped types是Typescript的映射类型,能够让你快速创建类型:
type NewUser = {
[K in 'name' | 'mobile']: string;
};
// 上面的代码等同于:
type NewUser = {
name: string;
mobile: string;
}
根据上面的keyof我们也可以:
interface User {
name: string;
mobile: string;
}
type NewUser = {
[K in keyof User]: string;
};
前置知识已经学完了,后面我们可以进入主题学习Typescript的高级类型了。
# Record类型
Record类型是最常用的类型,可以快速创建一个类型,我们先来看Record的源码:
/**
* Construct a type with a set of properties K of type T
*/
type Record<K extends keyof any, T> = {
[P in K]: T;
};
看代码其实已经很明显了,结合上面的前置知识的代码,我们可以直接示例:
type User = Record<'name' | 'mobile', string>;
// 上面的代码相当于
type User = {
name: string;
mobile: string;
}
# Partial类型
Partial类型是将类型的所有属性都修改为可选。源码如下:
/**
* Make all properties in T optional
*/
type Partial<T> = {
[P in keyof T]?: T[P];
};
Partial的使用如下:
type User = {
name: string;
mobile: string;
}
type NewUser = Partial<User>;
// 相当于
type NewUser = {
name?: string;
mobile?: string;
}
结合Record我们也可以这样:
type NewUser = Partial<Record<'name' | 'mobile', string>>;
# Readonly类型
Readonly类型就跟名字一样,将传入的类型的所有属性都定义为只读。源码如下:
/**
* Make all properties in T readonly
*/
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
具体使用如下:
type User = Readonly<Record<'name' | 'mobile', string>>;
// 等同于
type User = {
readonly name: string;
readonly mobile: string;
}
# Pick类型
Pick类型是将传入的类型,选择一个指定的类型然后返回一个新的类型。源码如下:
/**
* From T, pick a set of properties whose keys are in the union K
*/
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
具体使用如下:
type User = {
name: string;
mobile: string;
address: string;
}
type NewUser = Pick<User, 'name' | 'mobile'>;
// 相当于
type NewUser = {
name: string;
mobile: string;
}
# 总结
其实这些高级类型Typescript在2016年就给出了,所以早就被应用在了一些包和框架上,这些类型其实在日常的开发中也是能够用到的,故记录下来。