Перейти к содержанию

Перечисления (Enums)

Перечисления

Перечисления позволяют определить набор именованных числовых констант. Они определяются используя ключевое слово enum.

enum Direction {
  Up = 1,
  Down,
  Left,
  Right,
}

Тело перечисления состоит из нуля или более элементов. Элементы перечисления имеют численное значение ассоциированное с именем, и могут быть либо константой, либо могут быть вычислены. Элемент перечисления считается константой, если:

  • Он не имеет инициализатора, предшествующий элемент перечисления был константой. В этом случае значение текущего элемента перечисления будет равняться значению предшествующего элемента перечисления плюс единица. Исключением является первый элемент перечисления. Если элемент не имеет инициализатора, ему присваивается значение 0.
  • Элемент перечисления инициализирован с константным выражением перечисления. Константное выражение перечисления - это подмножество TypeScript выражений, которое может быть полностью вычислено во время компиляции. Выражение является константным выражением перечисления, если оно является либо:
  • численным литералом
  • ссылкой к прежде определённому константному элементу перечисления (она может быть определёна в различных перечислениях). Если элемент определён в том же перечислении, на него можно сослаться, используя неквалифицированное имя.
  • константным выражением перечисления, взятым в круглые скобки
  • унарным оператором +, -, ~, применённым к константному выражению перечисления
  • бинарным оператором +, -, *, /, %, <<, >>, >>>, &, |, ^ с константным выражением перечисления как операнд. Константное выражение перечисления, вычисляемое в NaN или Infinity, приводит к ошибке во время компиляции

Во всех остальных случаях считается, что элемент перечисления вычисляем.

enum FileAccess {
  // константные элементы
  None,
  Read = 1 << 1,
  Write = 1 << 2,
  ReadWrite = Read | Write,
  // вычисляемые элементы
  G = '123'.length,
}

Перечисления - это действительные объекты, существующие во время выполнения. Одной из причин этого является способность поддерживать обратное отображение из значений перечисления к именам перечисления.

enum Enum {
  A,
}
let a = Enum.A
let nameOfA = Enum[Enum.A] // "A"

компилируется в:

var Enum
;(function (Enum) {
  Enum[(Enum['A'] = 0)] = 'A'
})(Enum || (Enum = {}))
var a = Enum.A
var nameOfA = Enum[Enum.A] // "A"

В сгенерированном коде перечисление скомпилировано в объект, который хранит прямое (имя -> значение) и обратное (значение -> имя) отображения. Ссылки к элементам перечисления всегда выполняются как доступы к свойству и никогда не встраиваются. Во многих случаях это является правильным решением. Однако, иногда требования жёстче. Чтобы избежать оплаты стоимости дополнительного сгенерированного кода и косвенного обращения при получении доступа к значениям перечисления можно использовать константные перечисления. Константые перечисления определяются используя модификатор const, предшествующий ключевому слову enum.

const enum Enum {
  A = 1,
  B = A * 2,
}

Константные перечисления могут только использовать константные выражения перечисления, и в отличие обычных перечислений они полностью удаляются в течение компиляции. Элементы константного перечисления встраиваются в местах использования. Это возможно, поскольку константные перечисления не могут иметь вычисляемых элементов.

const enum Directions {
  Up,
  Down,
  Left,
  Right,
}

let directions = [
  Directions.Up,
  Directions.Down,
  Directions.Left,
  Directions.Right,
]

в сгенерированном коде превратится в

var directions = [
  0 /* Up */,
  1 /* Down */,
  2 /* Left */,
  3 /* Right */,
]

Окружающие перечисления

Окружающие перечисления используются для описания формы уже существующих перечислений.

declare enum Enum {
  A = 1,
  B,
  C = 2,
}

Одно важное отличие между окружающим и не окружающим перечислениями в том, что в обычных перечислениях элементы, не имеющие инициализатора, считаются константными элементами. Для элемента не константного окружающего перечисления, не имеющего инициализатора, элемент считается вычисляемым.

Ссылки