Перечисления¶
Перечисления - это способ организовать коллекцию связанных значений. Многие другие языки программирования (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 предупредит вас, если вы этого не сделаете (сообщение об ошибке В перечислении с несколькими объявлениями только одно объявление может не использовать инициализатор для своего первого элемента).