TypeScript 枚举

2025年4月24日 | 阅读 8 分钟

Enum 是 Enumerations 的缩写。Enum 是 TypeScript 支持的一种新的数据类型。它用于定义一组命名常量,即一组相关值。TypeScript 同时支持数字枚举和字符串枚举。我们可以使用 enum 关键字来定义枚举。

通过允许您为一组值提供有意义的名称,枚举有助于提高代码的可读性和可维护性。当处理在逻辑上相关的数值时,例如一周中的某几天、方向或用户角色,它们特别有用。

为什么使用枚举?

由于以下原因,枚举在 TypeScript 中很有用:

  • 它使将来更改值变得容易。
  • 它减少了因传输或拼写错误数字而导致的错误。
  • 它仅在编译时存在,因此不分配内存。
  • 它通过 JavaScript 中的内联代码节省了运行时和编译时。
  • 它允许我们创建可以轻松与程序关联的常量。
  • 它将使开发人员能够在不支持枚举的 JavaScript 中开发内存效率高的自定义常量,但 TypeScript 帮助我们访问它们。

TypeScript 中有 **三种** 枚举类型。它们是:

TypeScript Enums
  • 数字枚举
  • 字符串枚举
  • 异构枚举

数字枚举

数字枚举是 **基于数字** 的枚举,它们将值存储为数字。这意味着我们可以将数字分配给枚举的实例。

示例

编译并运行

说明

在上面的示例中,我们有一个名为 **Direction** 的数字枚举。这里,我们将 **Up** 初始化为 1,并且所有后续成员都从该点 **自动递增**。这意味着 Direction.Up 的值为 1,**Down** 的值为 2,**Left** 的值为 3,**Right** 的值为 4。

输出

{
  '1': 'Up',
  '2': 'Down',
  '3': 'Left',
  '4': 'Right',
  Up: 1,
  Down: 2,
  Left: 3,
  Right: 4
}

根据我们的需要,它也允许我们省略枚举的初始化。我们可以像下面的示例一样声明不带初始化的枚举。

示例

编译并运行

说明

在这里,Up 没有被赋值,所以 TypeScript 自动分配一个从 0 开始的数字值,并且所有后续成员都以 1 递增。这意味着 Direction.Up 的值为 0,Direction.Down 的值为 1,Direction.Left 的值为 2,Direction.Right 的值为 3。当不需要关心成员的值时,自动递增行为很有用。但每个值必须与其他相同枚举中的值不同。

输出

{
  '0': 'Up',
  '1': 'Down',
  '2': 'Left',
  '3': 'Right',
  Up: 0,
  Down: 1,
  Left: 2,
  Right: 3
}

说明

在 TypeScript 枚举中,不一定总是为枚举成员分配顺序值。我们可以为枚举成员提供任何值,如下面的示例所示。

示例

编译并运行

输出

{
  '1': 'Up',
  '3': 'Down',
  '6': 'Left',
  '10': 'Right',
  Up: 1,
  Down: 3,
  Left: 6,
  Right: 10
}

枚举作为函数参数

我们还可以使用枚举作为 **函数类型** 或 **返回类型**,如下面的示例所示。

示例

编译并运行

说明

在上面的示例中,我们声明了一个枚举 AppStatus。接下来,我们创建了一个函数 checkStatus(),它接受一个输入参数 status 并返回一个枚举 AppStatus。在函数中,我们检查 status 的类型。如果 status 名称匹配,我们得到匹配的枚举成员。

输出

2

说明

在这里,我们可以看到最后一个语句中打印的值“2”在大多数情况下都不是很实用。这就是为什么首选和推荐使用基于字符串的枚举。

字符串枚举

字符串枚举的概念与数字枚举类似,除了字符串枚举在运行时有一些细微的差异。在字符串枚举中,每个枚举值都用字符串字面量或另一个字符串枚举成员而不是数值进行常量初始化。

字符串枚举没有自动递增行为。使用此枚举的好处是字符串枚举提供了更好的可读性。如果我们正在调试程序,字符串枚举允许我们在代码运行时提供有意义且易读的值,而与枚举成员本身的名称无关。

考虑下面的数字枚举示例,但它表示为字符串枚举

示例

编译并运行

输出

STOP

说明

在上面的示例中,我们声明了一个与上面数字枚举具有相同值的字符串枚举 AppStatus。但是字符串枚举与数字枚举不同,其中字符串枚举值用字符串字面量初始化。这些枚举之间的区别在于数字枚举值是自动递增的,而字符串枚举值需要单独初始化。

异构枚举

异构枚举包含字符串和数字值。但建议除非有需要利用 JavaScript 运行时行为,否则不要这样做。

示例

编译并运行

输出

Yes
2

说明

AppStatus 枚举被称为异构枚举,因为它混合了字符串和数字值,但反向映射仅适用于数字,不适用于普通字符串枚举。

在代码中,ACTIVE = 'Yes'(字符串),INACTIVE = 1(数字),ONHOLD = 2(数字)和 ONSTOP = 'STOP'(字符串)。当你记录 AppStatus.ACTIVE 时,它会打印 'Yes',当你记录 AppStatus.ONHOLD 时,它会打印 2。

计算成员和常量成员

我们知道每个枚举成员都有一个关联的值。这些值可以是常量或计算值。如果以下条件成立,我们可以将枚举成员视为常量:

**1.** 它是枚举的第一个成员,没有初始化值。在这种情况下,它被赋值为 0。

示例

编译并运行

输出

{ '0': 'Abhishek', Abhishek: 0 }

**2.** 它没有初始化值,并且前面的枚举成员是数字常量。在这种情况下,当前枚举成员的值将是前面枚举成员的值加一。

示例

编译并运行

输出

{
  '0': 'Abhishek',
  '1': 'Ravi',
  '2': 'Ajay',
  Abhishek: 0,
  Ravi: 1,
  Ajay: 2
}
{
  '1': 'Engineer',
  '2': 'Leader',
  '3': 'Businessman',
  Engineer: 1,
  Leader: 2,
  Businessman: 3
}

在 TypeScript 中,我们可以说一个表达式是常量枚举表达式,如果它是:

  • 文字枚举表达式。
  • 对先前定义的常量枚举成员的引用。
  • 带括号的常量枚举表达式。
  • 它是应用于常量枚举表达式的 +, -, ~ 一元运算符之一。
  • 以常量枚举表达式作为操作数的 +, -, *, /, %, <<, >>, >>>, &, |, ^ 二元运算符。

在所有其他情况下,枚举成员被认为是 **计算值**。下面的枚举示例包含计算值的枚举成员。

示例

编译并运行

输出

3
120

说明

上面的 Weekend 枚举示例的 Saturday 值是通过函数 getDate 计算得出的。下面的函数检查传入的字符串是否为“Dominoz”,如果是则返回 3。所以 Saturday 得到 3,而 Sunday 是 Saturday * 40,即 120。这显示了枚举可能具有的值。

反向映射

TypeScript 枚举也支持反向映射。这意味着我们可以访问枚举成员的值,也可以从其值访问成员名称。我们可以从下面的示例中理解反向映射。

注意:字符串枚举不支持反向映射。

示例

编译并运行

输出

2
2
Sunday

说明

这里,Weekend 枚举从 Friday = 1 开始,所以通过自动递增 Saturday = 2,Sunday = 3。Weekend. 值 2 可以通过 Saturday 和 Weekend["Saturday"] 访问。让我们看看 Weekend[3] 如何工作,它执行反向查找并返回字符串“Sunday”。这演示了 TypeScript 中枚举提供的双重映射。

运行时的枚举

枚举是真实存在的对象,它们在运行时存在。我们可以从下面的示例中理解它。

它实际上可以传递给函数,如下面的示例所示。

环境枚举

我们可以使用环境枚举来描述 **现有枚举类型的形状**。

环境枚举和非环境枚举之间主要有 **一个区别**。在常规枚举中,没有初始化程序的成员如果其前面的枚举成员被认为是常量的,则被认为是 **常量**。但是,没有初始化程序的(非 const)环境枚举成员始终被认为是 **计算值** 枚举。

用例

1. 管理应用程序状态

当您知道要在应用程序中表示的所有可能状态时(例如,用户身份验证(LOGGED_IN、LOGGED_OUT、PENDING)或订单处理(PLACED、SHIPPED、DELIVERED、CANCELLED)),最好使用枚举。

2. 定义角色和权限

它也用于提及用户角色,例如 ADMIN、MODERATOR、USER,并对系统的某些特定部分进行访问控制。

3. 使用 HTTP 状态码

像 Spring MVC 这样的大型框架甚至为常见的 HTTP 响应代码(OK = 200、NOT_FOUND = 404、INTERNAL_SERVER_ERROR = 500)提供了枚举,因此您的 API 处理代码将更加清晰和具有描述性。

4. UI控件和可见性状态

枚举可以确认 UI 状态,如 VISIBLE、HIDDEN、DISABLED 和 LOADING,从而更方便地以结构化的方式处理组件行为。

常见问题解答 (FAQs)

Q1: TypeScript 中的枚举是什么?

枚举(Enum,Enumeration 的缩写)是一种特殊的数据类型,它允许您在 Python 中定义一组数字常量。枚举使我们能够编写更易读的代码,并将一些值逻辑上归入一个通用标识符的范围内。

Q2: TypeScript 中有哪些类型的枚举?

TypeScript 支持三种类型的枚举:

  • 数字枚举(默认)
  • 字符串枚举
  • 异构枚举(字符串和数字值的混合)

Q3: 枚举可以有计算值吗?

是的。您可以为枚举成员保留从函数或计算表达式返回的值。但是,计算成员必须遵循手动初始化。

Q4: 枚举是否支持反向映射?

是的,反向映射仅适用于数字枚举。TypeScript 创建名称到值的映射和值到名称的映射。字符串枚举的工作方式不同。

Q5: 什么是 const enum,何时使用它?

const enum 是一种经过编译器优化的枚举,在发出的输出中不会生成任何代码。它在编译期间完全被剥离,引用被替换为字面值。如果您不需要反向映射,则可以使用它。

Q6: 我可以在条件检查或 switch 语句中使用枚举吗?

当然。虽然枚举有助于条件逻辑,如 if 语句或 switch 块,但当内容受控且值属于某些固定相关项时,它们的效果最好。

Q7: 枚举是 TypeScript 特有的吗?

枚举通常用于定义用户角色,如 ADMIN、MODERATOR、USER,并根据这些角色控制对系统特定部分的访问。


下一主题TypeScript forEach