# 常用工具类型解读
用 JavaScript 编写中大型程序是离不开 lodash 这种工具集的,而用 TypeScript 编程同样离不开类型工具的帮助,类型工具就是类型版的 lodash.
我们在本节会介绍一些类型工具的设计与实现,如果你的项目不是非常简单的 demo 级项目,那么在你的开发过程中一定会用到它们。
起初,TypeScript 没有这么多工具类型,很多都是社区创造出来的,然后 TypeScript 陆续将一些常用的工具类型纳入了官方基准库内。
比如 ReturnType、Partial、ConstructorParameters、Pick 都是官方的内置工具类型.
其实上述的工具类型都可以被我们开发者自己模拟出来,本节我们学习一下如何设计工具类型.
# 工具类型的设计
# 泛型
我们说过可以把工具类型类比 js 中的工具函数,因此必须有输入和输出,而在TS的类型系统中能担当类型入口的只有泛型.
比如Partial,它的作用是将属性全部变为可选.
type Partial<T> = { [P in keyof T]?: T[P] };
这个类型工具中,我们需要将类型通过泛型T传入才能对类型进行处理并返回新类型,可以说,一切类型工具的基础就是泛型.
# 类型递归
是的,在类型中也有类似于js递归的操作,上面提到的Partial可以把属性变为可选,但是他有个问题,就是无法把深层属性变成可选,只能处理外层属性:
interface Company {
id: number
name: string
}
interface Person {
id: number
name: string
adress: string
company: Company
}
type R1 = Partial<Person>

这里想处理深层属性,就必须用到类型递归:
type DeepPartial<T> = {
[U in keyof T]?: T[U] extends object
? DeepPartial<T[U]>
: T[U]
};
type R2 = DeepPartial<Person>

这个原理跟js类似,就是对外层的value做个判断,如果恰好是object类型,那么对他也进行属性可选化的操作即可.
# 关键字
像keyof、typeof这种常用关键字我们已经了解过了,现在主要谈一下另外一些常用关键字.
+ -这两个关键字用于映射类型中给属性添加修饰符,比如-?就代表将可选属性变为必选,-readonly代表将只读属性变为非只读.
比如TS就内置了一个类型工具Required<T>,它的作用是将传入的属性变为必选项:
type Required<T> = { [P in keyof T]-?: T[P] };
当然还有很常用的Type inference就是上一节infer关键字的使用,还有之前的Conditional Type条件类型都是工具类型的常用手法,在这里就不多赘述了。
# 常见工具类型的解读
# Omit
Omit这个工具类型在开发过程中非常常见,以至于官方在3.5版本正式加入了
