Skip to main content

Flow Enums

Flow Enums define a fixed set of constants which create their own type.

Unlike other features of Flow, Flow Enums exist as values at runtime, as well as existing as types.

Read how to enable Flow Enums in your project.

Benefits

Enums provide several benefits over existing patterns:

  • Reduce repetition: Enum declarations provide both the type and the value of the enum.
  • Improve Flow performance: Enums are guaranteed to have good type-checking performance, unlike unions which may be expensive to type-check in certain situations.
  • Enable new functionality: Enums come with a cast method, which converts from a primitive type to an enum type safely.
  • Enhance safety: Enums define their own type which does not implicitly coerce to and from other types (e.g. from strings), and are required to be exhaustively checked in switch statements. These properties can help prevent logic bugs.

Quickstart

Defining enums

An enum named Status with three members: Active, Paused, and Off.

1enum Status {2  Active,3  Paused,4  Off,5}

By default, enums define members with string values which mirror their names. You can also explicitly set values:

1enum Status {2  Active = 'active',3  Paused = 'paused',4  Off = 'off',5}

You can use numbers as well:

1enum Status {2  Active = 1,3  Paused = 2,4  Off = 3,5}

Values must be unique, literals, and all of the same type. Check out the full docs on defining enums to learn more.

Using enums

To access an enum member, use dot access:

Status.Active

To use the enum type as an annotation, use the enum name:

const status: Status = Status.Active;

Cast from the representation type (in this case, a string) to the enum type:

const status: Status | void = Status.cast(someString);

You can easily provide a default value with the ?? operator:

const status: Status = Status.cast(someString) ?? Status.Off;

Read more about the other methods enums provide, including isValid, members, and getName.

Cast an enum type to its representation type (must be done explicitly):

status as string

Checks of enums in switch statements are exhaustive - we ensure you check all members:

1enum Status {2  Active,3  Paused,4  Off,5}6const status: Status = Status.Active;7
8// ERROR: Incomplete exhaustive check9switch (status) {
10 case Status.Active: break;11 case Status.Paused: break;12 // We forgot to add `case: Status.Off:` here, resulting in error above.13 // Using `default:` would also work to check all remaining members.14}
9:9-9:14: Incomplete exhaustive check: the member `Off` of enum `Status` [1] has not been considered in check of `status`. [invalid-exhaustive-check]

Read more about exhaustively checking enums.

Check out the the full docs on using enums to learn more.

When to use Flow Enums

If you previously defined a union type of literals, you can use an enum to define that type instead. Instead of

1type Status =2  | 'Active'3  | 'Paused'4  | 'Off';5
6const x: Status = 'Active';

or

1const Status = Object.freeze({2  Active: 'Active',3  Paused: 'Paused',4  Off: 'Off',5});6type StatusType = $Keys<typeof Status>;7const x: StatusType = Status.Active;

you can use:

1enum Status {2  Active,3  Paused,4  Off,5}6const x: Status = Status.Active;

See migrating from legacy patterns to learn more about migrating legacy JavaScript enum patterns to Flow Enums.

When to not use Flow Enums

Enums are designed to cover many use cases and exhibit certain benefits. The design makes a variety of trade-offs to make this happen, and in certain situations, these trade-offs might not be right for you. In those cases, you can continue to use existing patterns to satisfy your use cases. Read more about those situations.