Why is this an issue?

TypeScript allows all sorts of expressions to initialize enum members. However, as enums create their own scope, using identifiers can lead to unexpected results. The recommendation is thus to use only literal values when defining enum members.

What is the potential impact?

An enum member will shadow any variable defined with the same name in an enclosing scope. In the code example below, the day member value should derive from the hour const variable. But it is computed using the enum hour member instead, leading to the result 24 instead of the expected 1440.

const hour = 3600; // hour in seconds

enum DurationInMinutes {
    hour = 60, // hour in minutes
    day = 24 * hour / 60 // Expecting hour in seconds but got hour in minutes
}

How to fix it

The recommended approach for enums is to initialize members with literals. Not only are literals easier to read, but they also avoid unexpected results due to the enum scope.

Code examples

Noncompliant code example

const hello = 'Hello';
enum Foo {
  STRING = hello, // Variable
  OBJECT = { hello }.hello.length, // Object
  TEMPLATE = `${hello}, World`, // Template literal
  SET = new Set([hello, 'world']).size, // Constructor
  NUMBER = hello.length + 1, // Expression
}

Compliant solution

enum Foo {
  STRING = 'Hello',
  NUMBER = 0,
}

Resources

Documentation