Enums should always be singular

Photo by Foo Visuals on Unsplash

Enums should always be singular

Well... not always, but most of the time. Learn some good reasons why ๐Ÿ˜‰

ยท

2 min read

Use the singular form, enum OrderStatus instead of enum OrderStatuses, and enum ProductType instead of enum ProductTypes.

An enum is often used to type a variable that will only ever hold a single enum value at a time, such as an Order that is either PENDING_PAYMENT or COMPLETED.

When to use the plural form

It is possible to design an enum type so that variables would be able to hold multiple values at a time. Consider the following example:

enum Directions {
  NONE = 0,
  LEFT = 1,
  RIGHT = 2,
  UP = 4,
  DOWN = 8
}

// Multiple values assigned
const sides = Directions.LEFT | Directions.RIGHT;

// Will be printed
if (sides & Directions.LEFT) console.log("LEFT is set");
if (sides & Directions.RIGHT) console.log("RIGHT is set");

// Will not be printed
if (sides & Directions.UP) console.log("UP is set");
if (sides & Directions.DOWN) console.log("DOWN is set");

For this to work:

  • The enum values must all be numbers power of 2 (0, 1, 4, 8, 16, 32, and so forth)
  • Mulitple values must be assigned using the bitwise operator |
  • Values must be checked using the bitwise operator &

image.png

In this case, it is recommended to use the plural form to indicate that the enum was designed to allow setting multiple values to a single variable.

This is known as flags enum in other languages.

How does it work? ๐Ÿค”

Magic! ๐Ÿช„๐Ÿง

I kid.

The | and & operators are called "bitwise" operators because they work with bits.

When we set the enum values to 0, 1, 2, 4 and 8, we are doing the equivalent of:

  • NONE = 0000 (binary representation of 0)
  • LEFT = 0001 (binary representation of 1)
  • RIGHT = 0010 (binary representation of 2)
  • UP = 0100 (binary representation of 4)
  • DOWN = 1000 (binary representation of 8)

The | operator sets each bit to 1 if one of two bits is 1.

When we set sides to Directions.LEFT | Directions.RIGHT, we are combining 0001 and 0010 in such a way that sides is now 0011.

The & operator sets each bit to 1 if both bits are 1.

When we check if (sides & Directions.LEFT), we are checking 0011 (the value of sides) against 0001, which will yield 0001, which will be coerced to true.

This is why all enum values must be power of 2, so that their bits don't overlap.

Fun fact ๐Ÿ’ก

Did you notice that enum is an anagram of menu? Hence the cover picture.

ย