定义枚举
了解如何定义 Flow 枚举。想要快速概览?请查看 快速入门指南.
枚举声明是一个语句。它的名称定义了一个值(从中 访问其成员,并调用其 方法)和一个类型(可以 用作其成员类型的注解)。
枚举成员必须都是相同类型,这些成员可以是以下四种类型之一:字符串、数字、布尔值 和 符号。
每个枚举都有一些共同的属性
一致的成员类型
枚举成员的类型必须一致。例如,您不能在一个枚举中混合使用 string
和 number
成员。它们必须都是字符串、数字或布尔值(您不需要为基于 symbol
的枚举提供值)。
成员名称起始字符
成员名称必须是有效的标识符(例如,不能以数字开头),并且不能以小写字母 a
到 z
开头。以这些字母开头的名称保留用于枚举 方法(例如,Status.cast(...)
)。
以下情况不允许
1enum Status {2 active, // Error: names can't start with lowercase 'a' through 'z' 3}
2:3-2:8: Enum member names cannot start with lowercase 'a' through 'z'. Instead of using `active`, consider using `Active`, in enum `Status`.
唯一的成员名称
成员名称必须是唯一的。以下情况不允许
1enum Status {2 Active,3 Active, // Error: the name 'Active` was already used above 4}
3:3-3:8: Enum member names need to be unique, but the name `Active` has already been used before in enum `Status`.
文字成员值
如果您为枚举成员指定一个值,它必须是一个文字(字符串、数字或布尔值),而不是一个计算值。以下情况不允许
1enum Status {2 Active = 1 + 2, // Error: the value must be a literal 3}
2:12-2:12: The enum member initializer for `Active` needs to be a literal (either a boolean, number, or string) in enum `Status`.
唯一的成员值
成员值必须是唯一的。以下情况不允许
1enum Status {2 Active = 1,3 Paused = 1, // Error: the value has already been used above 4}
3:12-3:12: Invalid enum member initializer. Initializers need to be unique, but this one has already been used for a previous member [1] of enum `Status` [2]. [duplicate-enum-init]
在声明时固定
枚举不可扩展,因此您不能在代码运行时添加新的成员。在运行时,枚举成员值不能更改,并且成员不能删除。这样一来,它们的行为就像一个冻结的对象。
字符串枚举
字符串枚举是默认的。如果您没有指定 of
子句(例如,enum Status of number {}
、enum Status of symbol {}
等),并且没有指定任何值(例如,enum Status {Active = 1}
),那么定义将默认为字符串枚举。
与其他类型的枚举(例如,数字枚举)不同,您可以为枚举成员指定值,也可以不指定值并让它们默认。
如果您没有为枚举成员指定值,它们将默认设置为与成员名称相同的字符串。
1enum Status {2 Active,3 Paused,4 Off,5}
与以下情况相同
1enum Status {2 Active = 'Active',3 Paused = 'Paused',4 Off = 'Off',5}
您必须始终为所有成员指定值,或者不为任何成员指定值。以下情况不允许
1enum Status {2 Active = 'active',3 Paused = 'paused',4 Off, // Error: you must specify a value for all members (or none of the members) 5}
4:3-4:5: String enum members need to consistently either all use initializers, or use no initializers, in enum Status.
您可以选择使用 of
子句
1enum Status of string {2 Active,3 Paused,4 Off,5}
如果不存在 of
子句,我们将根据枚举的值推断枚举的类型。使用 of
子句将确保,如果您使用不正确的值,错误消息将始终将其解释为该类型的枚举。
数字枚举
数字枚举必须指定其值。
您可以像这样指定数字枚举
1enum Status {2 Active = 1,3 Paused = 2,4 Off = 3,5}
您可以选择使用 of
子句。这不会影响有效 Flow 枚举的类型检查行为,它只是确保所有枚举成员在定义位置都是 number
。
1enum Status of number {2 Active = 1,3 Paused = 2,4 Off = 3,5}
我们不允许数字枚举默认(与其他一些语言不同),因为如果从该枚举中间添加或删除一个成员,所有后续成员的值都会改变。这可能不安全(例如,推送安全、序列化、日志记录)。要求用户明确地重新编号,让他们考虑这样做带来的后果。
提供的值必须是数字文字。(注意:JavaScript 中没有负数的文字,它们是将一元 -
操作应用于数字文字的结果。)如果出现需要扩展允许值的请求,我们将来可能会扩展允许的值以包含某些非文字。
布尔值枚举
布尔值枚举必须指定其值。布尔值枚举只能有两个成员。
您可以像这样指定布尔值枚举
1enum Status {2 Active = true,3 Off = false,4}
您可以选择使用 of
子句。这不会影响有效 Flow 枚举的类型检查行为,它只是确保所有枚举成员在定义位置都是 boolean
。
1enum Status of boolean {2 Active = true,3 Off = false,4}
符号枚举
符号枚举不能指定其值。每个成员都是一个新的符号,符号描述设置为成员的名称。您必须在符号枚举中使用 of
子句,以将其与字符串枚举区分开来,字符串枚举是省略值时的默认值。
您可以像这样指定符号枚举
1enum Status of symbol {2 Active,3 Paused,4 Off,5}
具有未知成员的 Flow 枚举
您可以通过在声明末尾添加 ...
来指定您的枚举包含“未知成员”
1enum Status {2 Active,3 Paused,4 Off,5 ...6}7const status: Status = Status.Active;8
9switch (status) { 10 case Status.Active: break;11 case Status.Paused: break;12 case Status.Off: break;13}
9:9-9:14: Missing `default` case in the check of `status`. `Status` [1] has unknown members (specified using `...`) so checking it requires the use of a `default` case to cover those members. [invalid-exhaustive-check]
使用此方法时,Flow 将始终在 枚举上进行切换 时要求使用 default
,即使检查了所有已知的枚举成员。default
检查您没有显式列出的“未知”成员。
当枚举值跨越某个边界,并且每侧的枚举声明可能具有不同的成员时,此功能很有用。例如,在客户端和服务器上都使用的枚举定义:可以添加一个枚举成员,该成员会立即被服务器看到,但可以发送到尚未了解新成员的过时客户端。
此功能的一个用例是 GraphQL 枚举 的 JS 输出:可以使用具有未知成员的 Flow 枚举来代替添加的 '%future added value'
成员。
运行时的枚举
枚举在运行时作为值存在。我们使用 Babel 转换 将 Flow 枚举声明转换为对 枚举运行时 的调用(在 启用枚举文档 中了解更多信息)。我们使用运行时,以便所有枚举都可以共享枚举 方法 的实现。
我们使用 Object.create(null)
作为枚举的原型(它具有枚举方法),因此 Object.prototype
中的属性不会污染枚举。枚举对象的唯一自有属性是枚举成员。成员不可枚举(为此使用 .members()
方法)。整个枚举对象被冻结,因此它不能被修改。
风格指南
命名枚举
我们鼓励您使用 PascalCase
定义枚举名称,遵循其他类型的命名约定。全大写名称(例如,STATUS
)更难阅读,因此不建议使用。
我们鼓励您使用单数形式命名枚举。例如,Status
,而不是 Statuses
。就像 true
和 false
的类型是 boolean
,而不是 booleans
一样。
不要在名称后面添加 Enum
(例如,不要将您的枚举命名为 StatusEnum
)。这是不必要的,就像我们不会在每个类名后面添加 Class
,也不会在每个类型别名后面添加 Type
一样。
命名枚举成员
我们鼓励您使用 PascalCase
定义枚举成员名称。全大写名称(例如,ACTIVE
)更难阅读,因此不建议使用。此外,由于 Flow 强制执行这些是常量,因此您不需要使用名称来向程序员传达这种意图。
另请参阅:关于 枚举成员名称起始字符 的规则。
不要创建单独的类型
Flow 枚举,就像类一样,既是类型又是值。您不需要创建单独的类型别名,您可以使用枚举名称。
使用点访问来访问成员
优先使用 Status.Active
而不是 const {Active} = Status;
。这使得使用文本搜索更容易找到枚举的使用情况,并且使读者更清楚地了解涉及的枚举。此外,这是 涉及枚举的 switch 语句 所必需的。