<返回目录     Powered by claud/xia兄

第13课: 工具类型

什么是工具类型?

TypeScript提供了一系列内置的工具类型,用于对类型进行转换和操作,提高代码的灵活性和可维护性。

Partial<T>

将类型T的所有属性变为可选:

interface User {
  name: string;
  age: number;
  email: string;
}

type PartialUser = Partial;
// { name?: string; age?: number; email?: string; }

function updateUser(user: User, updates: Partial): User {
  return { ...user, ...updates };
}

updateUser(user, { age: 26 }); // 只更新age

Required<T>

将类型T的所有属性变为必需:

interface Props {
  a?: number;
  b?: string;
}

type RequiredProps = Required;
// { a: number; b: string; }

const obj: RequiredProps = {
  a: 5,
  b: "hello"
};

Readonly<T>

将类型T的所有属性变为只读:

interface Todo {
  title: string;
  description: string;
}

const todo: Readonly = {
  title: "Delete inactive users",
  description: "Clean database"
};

todo.title = "Hello"; // 错误:只读属性

Pick<T, K>

从类型T中选择属性K:

interface User {
  id: number;
  name: string;
  age: number;
  email: string;
}

type UserPreview = Pick;
// { id: number; name: string; }

const preview: UserPreview = {
  id: 1,
  name: "Alice"
};

Omit<T, K>

从类型T中排除属性K:

interface User {
  id: number;
  name: string;
  age: number;
  email: string;
}

type UserWithoutEmail = Omit;
// { id: number; name: string; age: number; }

const user: UserWithoutEmail = {
  id: 1,
  name: "Alice",
  age: 25
};

Record<K, T>

创建一个键为K、值为T的对象类型:

type Page = "home" | "about" | "contact";

interface PageInfo {
  title: string;
  url: string;
}

const pages: Record = {
  home: { title: "Home", url: "/" },
  about: { title: "About", url: "/about" },
  contact: { title: "Contact", url: "/contact" }
};

Exclude<T, U>

从类型T中排除可以赋值给U的类型:

type T0 = Exclude<"a" | "b" | "c", "a">;
// "b" | "c"

type T1 = Exclude void), Function>;
// string | number

Extract<T, U>

从类型T中提取可以赋值给U的类型:

type T0 = Extract<"a" | "b" | "c", "a" | "f">;
// "a"

type T1 = Extract void), Function>;
// () => void

NonNullable<T>

从类型T中排除null和undefined:

type T0 = NonNullable;
// string | number

type T1 = NonNullable;
// string[]

ReturnType<T>

获取函数类型T的返回值类型:

function f1(): { a: number; b: string } {
  return { a: 1, b: "hello" };
}

type T0 = ReturnType;
// { a: number; b: string; }

type T1 = ReturnType<() => string>;
// string

Parameters<T>

获取函数类型T的参数类型元组:

function f1(arg: { a: number; b: string }): void {}

type T0 = Parameters;
// [arg: { a: number; b: string; }]

type T1 = Parameters<(s: string) => void>;
// [s: string]

ConstructorParameters<T>

获取构造函数类型T的参数类型元组:

class C {
  constructor(a: number, b: string) {}
}

type T0 = ConstructorParameters;
// [a: number, b: string]

InstanceType<T>

获取构造函数类型T的实例类型:

class C {
  x = 0;
  y = 0;
}

type T0 = InstanceType;
// C

type T1 = InstanceType;
// any

Awaited<T>

获取Promise类型T的解析值类型:

type A = Awaited>;
// string

type B = Awaited>>;
// number

type C = Awaited>;
// boolean | number

组合使用工具类型

interface User {
  id: number;
  name: string;
  age: number;
  email: string;
  password: string;
}

// 创建用户时不需要id
type CreateUserDTO = Omit;

// 更新用户时所有字段可选,但不能更新id
type UpdateUserDTO = Partial>;

// 用户公开信息(不包含密码)
type PublicUser = Omit;

// 只读的用户信息
type ReadonlyUser = Readonly;

自定义工具类型

// 深度只读
type DeepReadonly = {
  readonly [P in keyof T]: T[P] extends object ? DeepReadonly : T[P];
};

// 深度部分
type DeepPartial = {
  [P in keyof T]?: T[P] extends object ? DeepPartial : T[P];
};

// 可为空
type Nullable = T | null;

// 可选键
type Optional = Omit & Partial>;
工具类型的优势:
练习:
  1. 使用Partial创建一个更新函数
  2. 使用Pick和Omit创建不同的数据传输对象
  3. 使用Record创建一个配置对象类型
  4. 创建一个自定义工具类型,实现特定的类型转换