发布于 2026-01-06 1 阅读
0

使用实用类型转换 TypeScript 中的类型

使用实用类型转换 TypeScript 中的类型

有时,你会遇到需要某种类型变体的情况。例如,你可能需要省略某些键,只保留某些键,甚至将某个类型的所有键标记为未定义或必需,等等。

TypeScript 提供了实用类型(Utility Types),旨在解决这个问题。本文将介绍这些内置的实用类型,以及一个提供更多实用功能的第三方库(附带示例),这些功能或许能帮助您实现上述目标。

内置实用程序类型

本节重点介绍 TypeScript 内置的实用类型,它们数量众多,我无法一一介绍,我只会根据自己的理解,举例说明几个关键类型。

部分的

此实用程序类型从现有类型构造一个新类型,顶层键被标记为可选(?)

interface Type {
    field: string;
}

type Type2 = Partial<Type>;
Enter fullscreen mode Exit fullscreen mode

注意:此设置仅作用于一层,这意味着低于一层的键不会受到影响。如果您想将所有键标记为可选,无论它们位于哪一层,请查看下方的 PartialDeep 选项。

必需的

这种实用类型的作用与上述相反,它会创建一个新类型,并将旧类型中所有可选的键标记为必需。

interface Type {
    field?: string;
    optional?: string;
}

type Type2 = Required<Type>;
Enter fullscreen mode Exit fullscreen mode

忽略

此实用工具类型从现有类型构造一个新类型,同时从新类型中省略指定的键。

interface Type {
    field1?: string;
    field2: string;
    field3: string;
}

type Type2 = Omit<Type, "field3" | "field1">;
Enter fullscreen mode Exit fullscreen mode

挑选

这种实用工具类型通过从旧类型中选择指定的键来构造一个新类型。它的功能与上述的“省略”操作相反。

interface Type {
    field1?: string;
    field2: string;
    field3?: string;
    field4: string;
    field5?: string;
}

type Type2 = Pick<Type, "field2" | "field3">;
Enter fullscreen mode Exit fullscreen mode

只读

此实用程序类型从现有类型构造一个新类型,并将所有键标记为只读,即它们不能被重新赋值。这对于冻结对象的类型非常有用,例如Object.freeze()

interface Type {
    field1?: string;
    field2: string;
    field3: string;
}

type Type2 = Readonly<Type>;
Enter fullscreen mode Exit fullscreen mode

记录

该实用类型构造一个新类型,其中联合成员作为键,类型作为键的类型。

interface Name {
    firstName: string;
    lastName: string;
}

type Names = "user1" | "user2";

type Type2 = Record<Names, Name>;
Enter fullscreen mode Exit fullscreen mode

记录实用程序类型

以上是一些我觉得非常有用的内置实用程序类型,您可以在此处的官方文档中找到更多关于内置实用程序类型的信息

扩展内置实用程序类型

虽然上述内置实用类型非常强大,但它们并不能涵盖所有使用场景,而这正是提供更多实用功能的库发挥作用的地方。type -fest就是一个很好的例子,它提供了更多实用功能。

虽然我不会深入研究 type-fest 提供的所有实用程序,但我会重点介绍一些非常有用的、基于内置类型实用程序的实用程序。

除了

这是上述 Omit 工具类型的一个变体,但更为严格。它通过从现有类型中省略指定的键来构造一个新类型,但与 Omit 不同的是,被省略的键必须严格存在于现有类型中。

// import { Except } from "type-fest"

interface X {
  a: string;
  b: string;
  c: string;
}

// Omit Example
type Y = Omit<X, "d">

// Except Example
type Z = Except<X, "d" >
Enter fullscreen mode Exit fullscreen mode

如下面的图片所示,如果您提供的键不存在,Except 会抛出错误。

合并

通过合并两种类型来构造一种新类型,其中第二种类型的键会覆盖第一种类型的键。

// import { Merge } from "type-fest"

interface X {
  a: string;
  b: string;
  c: string;
}

interface Y {
  c: number;
  d: number;
  e: number;
}

type Z = Merge<X, Y>

const x : Z = {
  a: "is string",
  b: "is string",
  c: 1,
  d: 2,
  e: 3,
}
Enter fullscreen mode Exit fullscreen mode

部分深度

这种实用工具类型会创建一个新类型,其中所有层级的所有键都是可选的。它与Partial内置的实用工具类型非常相似,但有一个显著区别:它会遍历所有层级,而前者只在第一层级生效。

// import { PartialDeep } from "type-fest";

interface X {
  a: string;
  b: string;
  c: string;
}

interface Y {
  c: number;
  d: number;
  e: number;
  f: X;
}

type Z = PartialDeep<Y>;

const x: Z = {};
Enter fullscreen mode Exit fullscreen mode

ReadonlyDeep

这种实用工具类型会创建一个新类型,并将所有层级的所有键都标记为必需。它与内置Readonly实用工具类型类似,但与内置实用工具类型不同的是,这种类型会遍历所有层级的所有键,从而使它们成为不可变的。

可变

这种实用类型构造一个类型,该类型从类型中的键中剥离readonly,本质上与内置实用类型的作用相反Readonly

// import { Mutable } from "type-fest";

interface X {
  readonly a: string;
  readonly d: string;
}

type Y = Mutable<X>;
Enter fullscreen mode Exit fullscreen mode

结论

在本文中,我研究了 TypeScript 实用类型,以及它们如何帮助您从现有类型自动创建类型,而不会导致重复,从而无需保持相关类型同步。

我重点介绍了一些我在日常开发工作中特别常用的内置实用类型。此外,我们还研究了 type-fest,这是一个包含大量实用类型的库,它扩展了内置类型,我们也重点介绍了其中的一些类型。

资源

文章来源:https://dev.to/this-is-learning/transforming-types-in-typescript-with-utility-types-3mhl