Основы TypeScript: Перечисления (Enums)
Перечисления (enums) в TypeScript — это тип данных, который позволяет определить набор именованных констант. Они используются для представления набора связанных значений, которым присваиваются символические имена. Перечисления делают код более читаемым и облегчают работу с наборами констант.
Числовые перечисления (Numeric Enums)
По умолчанию, если вы не присваиваете значения элементам перечисления, TypeScript автоматически присваивает им числовые значения, начиная с 0 и увеличиваясь на единицу для каждого следующего элемента.
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right, // 3
}
let move: Direction = Direction.Up;
console.log(move); // Выведет 0
if (move === Direction.Up) {
console.log("Двигаемся вверх"); // Это будет выполнено
}Вы можете явно присвоить числовые значения элементам перечисления. Если вы присваиваете значение только некоторым элементам, элементы, следующие за ними, будут автоматически инкрементироваться, начиная с присвоенного значения.
enum Status {
Pending = 10,
Approved, // 11
Rejected = 20,
Canceled, // 21
}
let currentStatus: Status = Status.Approved;
console.log(currentStatus); // Выведет 11
if (currentStatus === Status.Rejected) {
console.log("Заявка отклонена");
} else if (currentStatus === Status.Approved) {
console.log("Заявка одобрена"); // Это будет выполнено
}Обратное сопоставление (Reverse Mapping)
Для числовых перечислений TypeScript генерирует обратное сопоставление. Это означает, что вы можете получить имя элемента перечисления по его числовому значению.
enum ResponseCode {
OK = 200,
NotFound = 404,
InternalServerError = 500,
}
console.log(ResponseCode.OK); // Выведет 200
console.log(ResponseCode[200]); // Выведет "OK"Обратное сопоставление создается только для числовых перечислений (где значения являются числами).
Строковые перечисления (String Enums)
В строковых перечислениях каждому элементу должно быть явно присвоено строковое значение. В отличие от числовых перечислений, строковые перечисления не поддерживают обратное сопоставление.
enum LogLevel {
Debug = "DEBUG",
Info = "INFO",
Warning = "WARNING",
Error = "ERROR",
}
let currentLevel: LogLevel = LogLevel.Info;
console.log(currentLevel); // Выведет "INFO"
if (currentLevel === LogLevel.Error) {
console.log("Произошла ошибка!");
}Гетерогенные перечисления (Heterogeneous Enums)
Гетерогенные перечисления содержат элементы с разными типами значений (числовыми и строковыми). Однако их использование не рекомендуется, так как они могут привести к непредсказуемому поведению и усложняют понимание кода.
enum Mixed {
A, // 0
B = "B",
C = 10,
D, // 11
}
console.log(Mixed.A); // 0
console.log(Mixed.B); // "B"
console.log(Mixed.C); // 10
console.log(Mixed.D); // 11
console.log(Mixed[0]); // "A"
// console.log(Mixed["B"]); // Ошибка: Элемент "B" не имеет числового значения, поэтому обратное сопоставление не работает
console.log(Mixed[10]); // "C"
console.log(Mixed[11]); // "D"Обратите внимание, что обратное сопоставление работает только для числовых элементов гетерогенного перечисления.
Перечисления с константными выражениями (Enum with Constant Expressions)
Значения элементов перечисления могут быть константными выражениями, которые вычисляются во время компиляции.
const START_VALUE = 100;
enum StatusCode {
OK = 200,
Redirect = 300 + 1,
NotFound = START_VALUE + 4,
}
console.log(StatusCode.OK); // 200
console.log(StatusCode.Redirect); // 301
console.log(StatusCode.NotFound); // 104Константные перечисления (Const Enums)
Константные перечисления объявляются с использованием ключевого слова const. В отличие от обычных перечислений, константные перечисления не создают объект во время выполнения. Вместо этого, значения элементов константного перечисления подставляются непосредственно в местах их использования в коде. Это может привести к уменьшению размера JavaScript-бандла.
const enum Operation {
Add,
Subtract,
Multiply,
}
function calculate(a: number, b: number, op: Operation): number {
switch (op) {
case Operation.Add:
return a + b;
case Operation.Subtract:
return a - b;
case Operation.Multiply:
return a * b;
}
}
let result = calculate(5, 3, Operation.Multiply);
console.log(result); // Выведет 15При компиляции код будет выглядеть примерно так (в зависимости от настроек компилятора):
function calculate(a, b, op) {
switch (op) {
case 0 /* Add */:
return a + b;
case 1 /* Subtract */:
return a - b;
case 2 /* Multiply */:
return a * b;
}
}
var result = calculate(5, 3, 2 /* Multiply */);
console.log(result);Обратите внимание, что объект Operation не существует во время выполнения. Из-за этого вы не сможете получить имя элемента константного перечисления по его значению (нет обратного сопоставления).
Использование перечислений
Перечисления полезны в ситуациях, когда у вас есть набор именованных констант, которые логически связаны друг с другом. Они улучшают читаемость кода по сравнению с использованием "магических чисел" или строковых литералов.
Примеры использования перечислений:
- Представление состояний (например,
Loading,Success,Error). - Определение набора действий (например,
Create,Read,Update,Delete). - Перечисление направлений (например,
Up,Down,Left,Right). - Определение уровней логирования (например,
Debug,Info,Warning,Error).
Заключение
Перечисления в TypeScript предоставляют удобный способ работы с наборами именованных констант. Они могут быть числовыми или строковыми, и TypeScript предоставляет различные возможности для их определения и использования. Выбор между обычными и константными перечислениями зависит от ваших потребностей в обратном сопоставлении и размере генерируемого JavaScript-кода. Правильное использование перечислений может сделать ваш код более понятным, поддерживаемым и типобезопасным.