本文正在参加「金石计划」
flag:每月至少产出三篇高质量文章~
Typescript
中的实用类型是一些预定义的泛型类型,可用于操作或创建其他新类型。这些类型在所有 Typescript 项目中都是全局可用的,因此无需添加任何依赖项即可使用它们。
一、官方内置 utility types
1、Partial<Type>
构建一个类型,将类型的所有属性设置为可选。这个工具将返回一个表示给定类型的所有子集的类型。下面来看一个例子:
2、Required<Type>
构建一个由Type的所有属性组成的类型,设置为必填。与 Partial
相反。
3、Record<Keys, Type>
构建一个对象类型,其属性键是 Keys
,其属性值是 Type
。这个工具可以用来将一个类型的属性映射到另一个类型。
4、Omit<Type, Keys>
通过从 Type
中选取所有属性,然后删除 Keys
(字符串字面或字符串字面的联合)来构造一个类型
我们还可以通过传递一个union
类型:
5、Pick<Type, Keys>
通过从 Type
中选取属性集合 Keys
(字符串字头或字符串字头的联合)来构造一个类型
5.1 Partial + Pick
5.2 Omit + Partial + Pick
6、Readonly<Type>
构建一个类型,Type的所有属性设置为只读,这意味着构建的类型的属性不能被重新分配。
这个 utility types
对于表示将在运行时失败的赋值表达式很有用(即当试图重新分配一个冻结对象的属性时)。比如,Object.freeze:
function freeze<Type>(obj: Type): Readonly<Type>;
7、Mutable<Type>
创建一个 Mutable
类型帮助程序,允许你将所有只读类型转换为可变类型。
8、Exclude<UnionType, ExcludedMembers>
通过从 UnionType
中排除可分配给 ExcludedMembers
的所有 union
成员来构造一个类型。
你还可以exlude
多个联合成员:
9、Extract<Type, Union>
通过从 Type
中提取可分配给 Union
的所有 union成员
,构造一个类型。
10、ReturnType<Type>
构建一个由函数 Type
的返回类型组成的类型。
11、Parameters<Type>
从一个函数类型 Type
的参数中使用的类型构建一个元组类型。
11.1 ThisParameterType<Type>
提取一个函数类型的 this参数
的类型,如果该函数类型没有 this参数
,则为 unknown
。
11.2 OmitThisParameter<Type>
移除 Type
的 this参数
。如果 Type
没有明确声明的 this参数
,结果只是 Type
。否则,一个没有 this参数
的新函数类型将从 Type
创建。泛型被擦除,只有最后的重载签名被传播到新的函数类型。
11.3 ConstructorParameters<Type>
从构造函数的类型中构造一个元组或数组类型。它产生一个具有所有参数类型的元组类型(如果 Type
不是一个函数,则是一个 never
类型)。
12、ThisType<Type>
这个工具类型并不返回一个转换后的类型。相反,它作为一个上下文的 this类型
的标记。注意,必须启用 noImplicitThis
才能使用这个工具类型。
在上面的例子中,makeObject
的参数中的方法对象有一个包括 ThisType<D & M>
的上下文类型,因此方法对象中 this
的类型是 { x: number, y: number } & { moveBy(dx: number, dy: number): number }
。注意,方法属性的类型是如何同时作为推理目标和方法中this
类型的来源的。
ThisType<T>
标记接口只是在lib.d.ts
中声明的一个空接口。除了在对象字面的上下文类型中被识别之外,该接口的行为与任何空接口一样。
13、NonNullable<Type>
通过从 Type
中排除 null
和 undefined
来构造一个类型。
14、InstanceType<Type>
构建一个由 Type
中构造函数的实例类型组成的类型。
15、Awaited<Type>
这种类型是为了模拟像 async
函数中的 await
或 Promises
上的 .then()
方法这样的操作,特别是它们递归地解除 Promises
的方式。
Awaited + ReturnType
二、社区知名 utility types 库
1、utility-types
比较知名,也比较老(目前只支持到 v3.7
)的一个实用类型的集合,补充了 TypeScript
内置的映射类型和别名(想想静态类型的 "lodash"
),可以 copy 一些自己想要的到项目中使用。
2、type-fest
项目地址:type-fest
有大量的类型可供选择:
3、ts-toolbelt
项目地址:ts-toolbelt
ts-toolbelt
是目前最大的,也是经过最多测试的类型库,具有+200个
实用工具。我们的类型集合打包了市场上一些最先进的映射类型、条件类型和递归类型。
三、建议:不要过度使用 utility types
有时候,过度使用实用程序类型可能会导致代码难以理解和维护。特别是将多种类型嵌套在一起。比如下面这个例子:
type User = { id: number; name: string; email: string; }; type VeryComplexUser = Readonly<Pick<User, "id">> & Partial<Omit<User, "email">> & { email: User["email"] | null } & { role: string } & Record<"email", string> & { role: User["name"] extends "admin" ? "admin" : "user"; } & { name: User["name"]; } & { id: { [K in keyof User["id"]]: User["id"][K] }; } & { email: User["email"] & string; } & { role: Exclude<User["role"], "guest">; };
头大不头大~
end~