Перечисления¶
Перечисления - это способ организовать коллекцию связанных значений. Многие другие языки программирования (C/C#/Java) имеют тип данных enum
, а JavaScript - нет. Тем не менее, TypeScript имеет. Вот пример описания перечисления в TypeScript:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Эти значения перечислений являются числами
, поэтому далее я буду называть их числовыми перечислениями.
Числовые перечисления и числа¶
TypeScript перечисления основанные на числах. Это означает, что числа могут быть назначены на экземпляр перечисления, а также всё, что совместимо с числом
.
1 2 3 4 5 6 7 |
|
Числовые перечисления и строки¶
Прежде чем мы углубимся в перечисления, давайте рассмотрим генерируемый ими JavaScript, вот пример TypeScript:
1 2 3 4 5 |
|
генерирует следующий JavaScript:
1 2 3 4 5 6 |
|
давайте сосредоточимся на строке Tristate[Tristate["False"] = 0] = "False";
. Внутри неё выражение Tristate["False"] = 0
не требует особых объяснений, по факту оно присваивает свойству "False"
объекта Tristate
значение 0
.
Обратите внимание, что в JavaScript оператор присваивания возвращает присвоенное значение (в данном случае 0
). Поэтому следующая операция, выполняемая средой выполнения JavaScript, это Tristate[0] = "False"
. Это означает, что вы можете использовать переменную Tristate
для преобразования строковой версии перечисления в число или числовой версии перечисления в строку. Это продемонстрировано ниже:
1 2 3 4 5 6 7 8 9 |
|
Изменение числа, в числовом перечислении¶
По умолчанию перечисления начинаются с 0
, а затем каждое последующее значение автоматически увеличивается на 1. В качестве примера рассмотрим следующее:
1 2 3 4 5 |
|
Однако вы можете изменить число, связанное с любым элементом перечисления, назначив его конкретным. Это показано ниже, где мы начинаем с 3 и начинаем увеличивать:
1 2 3 4 5 |
|
СОВЕТ: Я обычно инициализирую первое перечисление с
= 1
, чтобы можно было наверняка проверить значение перечисления на достоверность.
Числовые перечисления в качестве флагов¶
Одним из отличных вариантов использования перечислений является возможность использовать перечисления в качестве Флагов
. Флаги позволяют вам проверить, верно ли определенное условие из набора условий. Рассмотрим следующий пример, где у нас есть набор свойств о животных:
1 2 3 4 5 6 7 |
|
Здесь мы используем оператор сдвига влево для перемещения 1
вокруг определенного уровня битов, чтобы получить побитовые непересекающиеся числа 0001
, 0010
, 0100
и 1000
(это десятичные числа 1
,2
,4
,8
если вам интересно). Побитовые операторы |
(или) / &
(и) / ~
(не) являются вашими лучшими друзьями при работе с флагами и продемонстрированы ниже:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
Здесь:
- мы использовали
|=
, чтобы добавить флаги - комбинация
&=
и~
для очистки флага |
объединить флаги
Примечание: вы можете комбинировать флаги для создания удобных сокращений в определении перечисления, например
EndangeredFlyingClawedFishEating
ниже:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Строковые перечисления¶
Мы смотрели только на перечисления, где значениями являются числа
. На самом деле вы также можете использовать перечисления со строковыми значениями. Например
1 2 3 4 5 6 7 8 |
|
С ними проще работать и проверять, так как они предоставляют выразительные / проверяемые строковые значения.
Вы можете использовать эти значения для простого сравнения строк. Например
1 2 3 4 5 6 7 8 9 |
|
Константные перечисления¶
Если у вас есть определение перечисления, подобное следующему:
1 2 3 4 5 6 7 |
|
Строка var lie = Tristate.False
компилируется в JavaScript как var lie = Tristate.False
(да, вывод совпадает с вводом). Это означает, что во время выполнения потребуется поиск Tristate
, а затем Tristate.False
. Чтобы повысить производительность, вы можете записать enum
как const enum
. Это продемонстрировано ниже:
1 2 3 4 5 6 7 |
|
генерирует следующий JavaScript:
1 |
|
то есть компилятор:
- Встраивает любое использование перечисления (
0
вместоTristate.False
). - Не генерирует JavaScript для определения перечисления (во время выполнения отсутствует переменная
Tristate
), поскольку его использование встроено.
Константные перечисления с флагом preserveConstEnums¶
Встраивание имеет очевидные преимущества в производительности. Тот факт, что во время выполнения отсутствует переменная Tristate
, просто означает что компилятор помогает вам не генерировать JavaScript, который фактически не используется во время выполнения.
Однако вы, возможно, захотите, чтобы компилятор по-прежнему генерировал JavaScript-версию определения перечисления для перевода числа в строку или строки в число, как мы рассматривали выше. В этом случае вы можете использовать флаг компилятора --preserveConstEnums
, и он все равно сгенерирует определение var Tristate
, чтобы вы могли использовать Tristate["False"]
или Tristate[0]
вручную во время выполнения, если это нужно. Это никак не влияет на встраивание.
Перечисление со статическими функциями¶
Вы можете использовать объявление перечисления
+ область имен
, чтобы добавить статические методы в перечисление. Следующий пример демонстрирует как мы добавляем статический элемент isBusinessDay
в перечисление Weekday
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Перечисления расширяемы¶
ПРИМЕЧАНИЕ: расширяемые перечисления имеют значение только в том случае, если вы не используете модули. Вы должны использовать модули. Следовательно, этот раздел является последним.
Вот сгенерированный JavaScript для перечисления из известного выше примера:
1 2 3 4 5 6 |
|
Мы уже объяснили часть Tristate[Tristate["False"] = 0] = "False";
. Теперь обратите внимание на оборачивающий код (function (Tristate) { /*code here */ })(Tristate || (Tristate = {}));
особенно часть (Tristate || (Tristate = {}));
. Он в основном описывает локальную переменную Tristate
, которая будет либо указывать на уже определенное значение Tristate
, либо инициализировать новый пустой объект {}
.
Это означает, что вы можете разделить (и расширить) определение перечисления на несколько файлов. Например, ниже мы разделили определение для Color
на два блока
1 2 3 4 5 6 7 8 9 10 11 |
|
Обратите внимание, что вы должны повторно инициализировать первый элемент (здесь DarkRed = 3
) в продолжении перечисления, чтобы получить производный код, а не значения перезаписанные из предыдущего определения (то есть 0
, 1
, ... и так далее). TypeScript предупредит вас, если вы этого не сделаете (сообщение об ошибке В перечислении с несколькими объявлениями только одно объявление может не использовать инициализатор для своего первого элемента
).