Menu

TypeScript 工具类型大全:完整列表与示例

一页看全 TypeScript 所有内置工具类型:Partial、Required、Readonly、Pick、Omit、Record、Exclude、Extract、NonNullable、Parameters、ReturnType、Awaited、字符串工具类型等,每个都有一句话说明和可运行示例。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

工具类型是 TypeScript 内置的泛型类型,用来把一个类型转换成另一个类型。不必再写一个所有字段都可选的 User 类型,直接写 Partial<User>;不必复制三个字段,写 Pick<User, "id" | "name"> 即可。它们是全局的,不需要导入。

User 改变时,这四个派生类型会自动跟着变。TypeScript 标准库(lib.es5.d.ts)一共声明了 22 个工具类型。下面按作用的类型种类分组列出全部工具类型,有详细页面的附上了链接。

对象类型:Partial、Required、Readonly、Pick、Omit、Record

工具类型作用示例
Partial<T>让所有属性变成可选用 Partial<User> 表示更新数据
Required<T>让所有属性变成必需(去掉 ?)应用默认值之后的 Required<Config>
Readonly<T>让所有属性变成 readonlyReadonly<State>
Pick<T, K>只保留键 KPick<User, "id" | "name">
Omit<T, K>去掉键 KOmit<User, "password">
Record<K, V>键为 K、值为 V 的对象类型Record<"en" | "de", string>

Required<T> 与 Partial<T> 正好相反;Partial 一页同时讲解了这两者,包括像这里这样的展开运算会放进来的显式 undefined。

联合类型:Exclude、Extract、NonNullable

工具类型作用示例
Exclude<U, M>去掉可以赋值给 M 的联合成员Exclude<"a" | "b" | "c", "a"> 得到 "b" | "c"
Extract<U, M>保留可以赋值给 M 的联合成员Extract<string | number, number> 得到 number
NonNullable<T>去掉 null 和 undefinedNonNullable<string | null> 得到 string

这三个工具类型作用于联合类型,而不是对象。这是它们和 Pick、Omit 的关键区别:后两者接收的是一个对象类型和它的一组键。

函数和类:Parameters、ReturnType 等

工具类型作用示例
ReturnType<F>函数类型的返回类型ReturnType<typeof createStore>
Parameters<F>以元组形式给出参数类型Parameters<typeof fetchPage>[0]
ConstructorParameters<C>以元组形式给出类构造函数的参数ConstructorParameters<typeof Point>
InstanceType<C>构造函数创建的实例类型InstanceType<typeof Point>
ThisParameterType<F>函数 this 参数的类型ThisParameterType<typeof greet>
OmitThisParameter<F>去掉 this 参数后的函数类型greet.bind(obj) 的类型
ThisType<T>设置对象字面量方法中 this 的类型在构建器 API 中配合 noImplicitThis 使用
NoInfer<T>阻止从这个位置推断类型参数fallback: NoInfer<C>

这里需要写 typeof createOrder,因为这些工具类型接收的是类型,而 createOrder 是一个值。类也一样:typeof Point 是构造函数的类型,而直接把 Point 当作类型使用时,它本身就表示实例类型。

NoInfer 控制泛型从哪里获得类型:

如果没有 NoInfer,TypeScript 会根据两个实参推断 C,并把它拓宽为 "red" | "green" | "blue",于是 fallback 中的拼写错误也会被接受。

字符串:Uppercase、Lowercase、Capitalize、Uncapitalize

工具类型作用示例
Uppercase<S>把字符串字面量类型转成大写Uppercase<"get"> 得到 "GET"
Lowercase<S>转成小写Lowercase<"GET"> 得到 "get"
Capitalize<S>首字母大写Capitalize<"name"> 得到 "Name"
Uncapitalize<S>首字母小写Uncapitalize<"Name"> 得到 "name"

这四个工具类型内置在编译器中,而不是用 TypeScript 写成的。它们在模板字面量类型中最有用,例如用 `on${Capitalize<E>}` 生成事件处理函数的名字。

Promise:Awaited

工具类型作用示例
Awaited<T>await 得到的类型,会展开嵌套的 PromiseAwaited<Promise<Promise<number>>> 得到 number

Awaited<ReturnType<typeof fn>> 是给异步函数的结果类型命名的标准写法,无需另外声明。

组合使用工具类型

工具类型可以嵌套。下面几种组合经常出现,值得熟记:

嵌套的工具类型要从里往外读:Readonly<Pick<Post, "id" | "title">> 先保留两个属性,再把它们设为只读。用同样的组件还能写出只让部分键变成可选的 PartialBy 辅助类型;Partial 一页给出了完整写法。

工具类型在运行时不起任何作用

所有工具类型在代码编译时都会被擦除。类型为 Omit<User, "password"> 的值,如果来源对象带有 password,运行时它依然带着:

类型只限制你的代码能读取什么。要从数据中删掉一个字段,就像最后几行那样用解构把它去掉;要在运行时阻止修改,用 Object.freeze,而不是 Readonly。内置工具类型都是一行写成的映射类型和条件类型,所以你也可以用同样的工具编写自己的工具类型。

常见问题

TypeScript 中的工具类型是什么?

TypeScript 自带的一组泛型类型,用来把一个类型转换成另一个类型:Partial<T> 让所有属性变成可选,Pick<T, K> 只保留部分属性,ReturnType<F> 取得函数的返回类型,等等。它们声明在标准库里,所以无需导入就能使用。

使用工具类型需要导入吗?

不需要。Partial、Omit、Record、ReturnType 等都是 TypeScript 内置库文件中的全局类型。在任何地方直接写 Partial<User> 即可,不需要 import,也不需要安装 npm 包。

TypeScript 内置了哪些工具类型?

共 22 个,都声明在 lib.es5.d.ts 中:Partial、Required、Readonly、Pick、Omit、Record、Exclude、Extract、NonNullable、Parameters、ConstructorParameters、ReturnType、InstanceType、ThisParameterType、OmitThisParameter、ThisType、NoInfer、Awaited、Uppercase、Lowercase、Capitalize 和 Uncapitalize。

工具类型会在运行时修改对象吗?

不会。它们只描述类型,在编译出的 JavaScript 中会被擦除。Omit<User, "password"> 不会删除 password 属性,Readonly<T> 也不会冻结任何东西。要真正修改对象,需要写代码:用解构的剩余模式、Object.freeze 等。

可以自己编写工具类型吗?

可以。内置的工具类型就是普通的 TypeScript:大多数是 lib.es5.d.ts 中一行写成的映射类型或条件类型。type Nullable<T> = { [K in keyof T]: T[K] | null } 就是用同样方式写出的自定义工具类型。

Coddy 编程语言插图

和 Coddy 一起学编程

开始