概述
TypeScript 提供了一组强大的内置工具类型,旨在帮助开发者进行常见的类型转换和操作。这些工具类型极大地增强了 TypeScript 的类型系统,使得开发者能够编写更灵活和类型安全的代码。本文将详细介绍 TypeScript 的内置工具类型,并通过示例代码说明每个工具类型的使用方法和应用场景。
常用的内置工具类型
Partial<T>
Partial<T> 类型将对象类型 T 的所有属性变为可选。
示例
interface User {id: number;name: string;email: string;}type PartialUser = Partial<User>;let user: PartialUser = {name: "Alice"};
使用场景
- 配置对象:当函数或类的配置对象中,某些属性是可选时。
 - 数据更新:当部分更新对象的某些属性时,可以避免定义完整的对象结构。
 
function updateUser(userId: number, update: Partial<User>) {// 只更新提供的属性console.log(`Updating user ${userId} with`, update);}updateUser(1, { name: "Alice" });
Required<T>
Required<T> 类型将对象类型 T 的所有属性变为必选。
示例
interface User {id?: number;name?: string;email?: string;}type RequiredUser = Required<User>;let user: RequiredUser = {id: 1,name: "Alice",email: "alice@example.com"};
使用场景
- 表单验证:当表单中的所有字段都是必填时,使用 
Required确保所有字段都被填充。 - API 响应:当确保 API 响应中所有属性都存在时。
 
function createUser(user: Required<User>) {// 确保所有属性都存在console.log("Creating user with", user);}createUser({ id: 1, name: "Alice", email: "alice@example.com" });
Readonly<T>
Readonly<T> 类型将对象类型 T 的所有属性变为只读。
示例
interface User {id: number;name: string;email: string;}type ReadonlyUser = Readonly<User>;let user: ReadonlyUser = {id: 1,name: "Alice",email: "alice@example.com"};// user.id = 2; // Error: Cannot assign to 'id' because it is a read-only property.
使用场景
- 防止修改:当不希望对象属性被修改时,使用 
Readonly确保对象的不可变性。 - 常量定义:用于定义常量对象,使其属性不可变。
 
const userConfig: Readonly<User> = {id: 1,name: "Alice",email: "alice@example.com"};// userConfig.name = "Bob"; // Error: Cannot assign to 'name' because it is a read-only property.
Pick<T, K>
Pick<T, K> 类型从对象类型 T 中选择一组属性 K,创建新的子类型。
示例
interface User {id: number;name: string;email: string;}type UserContactInfo = Pick<User, "name" | "email">;let contactInfo: UserContactInfo = {name: "Alice",email: "alice@example.com"};
使用场景
- 选择特定属性:当只需要某个类型中的部分属性时,使用 
Pick提取所需属性。 - 数据传输:在网络请求或响应中,只传递必要的数据字段。
 
function getUserContactInfo(user: User): UserContactInfo {return {name: user.name,email: user.email};}let contactInfo = getUserContactInfo({ id: 1, name: "Alice", email: "alice@example.com" });console.log(contactInfo); // { name: "Alice", email: "alice@example.com" }
Record<K, T>
Record<K, T> 类型创建一个新的对象类型,其中键是 K 的成员,值是 T 类型。
示例
type Role = "admin" | "user" | "guest";type Permissions = Record<Role, string[]>;let permissions: Permissions = {admin: ["read", "write", "delete"],user: ["read", "write"],guest: ["read"]};
使用场景
- 键值对映射:当需要定义键值对结构时,使用 
Record创建类型安全的映射对象。 - 配置对象:用于定义具有固定键的配置对象。
 
interface Config {setting: string;value: any;}type ConfigMap = Record<string, Config>;let configMap: ConfigMap = {featureA: { setting: "enabled", value: true },featureB: { setting: "timeout", value: 3000 }};
Exclude<T, U>
Exclude<T, U> 类型从类型 T 中排除所有可以赋值给类型 U 的类型。
示例
type Primitive = string | number | boolean;type NonString = Exclude<Primitive, string>; // number | boolean
使用场景
- 类型过滤:当需要从联合类型中排除某些类型时,使用 
Exclude进行过滤。 - 类型优化:移除不需要的类型,以优化类型定义。
 
type AllowedTypes = Exclude<string | number | (() => void), Function>; // string | number
Extract<T, U>
Extract<T, U> 类型从类型 T 中提取所有可以赋值给类型 U 的类型。
示例
type Primitive = string | number | boolean;type StringOrNumber = Extract<Primitive, string | number>; // string | number
使用场景
- 类型选择:当需要从联合类型中提取某些类型时,使用 
Extract进行选择。 - 类型定义:定义只包含特定类型的联合类型。
 
type FunctionTypes = Extract<string | number | (() => void), Function>; // () => void
NonNullable<T>
NonNullable<T> 类型移除类型 T 中的 null 和 undefined。
示例
type NullableString = string | null | undefined;type NonNullString = NonNullable<NullableString>; // string
使用场景
- 类型约束:当需要移除类型中的 
null和undefined以确保类型安全时,使用NonNullable进行约束。 - 类型优化:移除不必要的 
null和undefined类型,以优化类型定义。 
function processValue(value: NonNullable<string>) {console.log("Processing:", value);}// processValue(null); // Error: Argument of type 'null' is not assignable to parameter of type 'string'.processValue("Hello"); // Processing: Hello
ReturnType<T>
ReturnType<T> 类型获取函数类型 T 的返回类型。
示例
function exampleFunction() {return { name: "Alice", age: 25 };}type ExampleReturnType = ReturnType<typeof exampleFunction>; // { name: string; age: number }
使用场景
- 类型推断:当需要推断函数的返回类型时,使用 
ReturnType获取返回类型。 - 类型重用:在多个地方使用相同的返回类型定义,以提高代码的可重用性。
 
function createUser() {return { id: 1, name: "Alice" };}type UserType = ReturnType<typeof createUser>;function printUser(user: UserType) {console.log("User:", user);}printUser(createUser()); // User: { id: 1, name: 'Alice' }
InstanceType<T>
InstanceType<T> 类型获取构造函数类型 T 的实例类型。
示例
class ExampleClass {constructor(public name: string, public age: number) {}}type ExampleInstance = InstanceType<typeof ExampleClass>; // ExampleClass
使用场景
- 类型推断:当需要推断类的实例类型时,使用 
InstanceType获取实例类型。 - 类型重用:在多个地方使用相同的实例类型定义,以提高代码的可重用性。
 
class User {constructor(public id: number, public name: string) {}}type UserInstance = InstanceType<typeof User>;function printUserInstance(user: UserInstance) {console.log("User:", user);}const user = new User(1, "Alice");printUserInstance(user); // User: User { id: 1, name: 'Alice'}
结论
内置工具类型是 TypeScript 类型系统中的重要组成部分,它们提供了灵活且强大的类型转换和操作方式。通过掌握这些内置工具类型,你可以编写出更具通用性和可重用性的代码。在实际开发中,合理使用这些工具类型可以提高代码的类型安全性和可读性,帮助你更好地处理复杂的数据结构和类型操作。
