Гид по технологиям

Enum в TypeScript — полное руководство

7 min read TypeScript Обновлено 08 Jan 2026
Enum в TypeScript: руководство
Enum в TypeScript: руководство

Крупный план тёмных клавиш пишущей машинки

Что такое enum (перечисление)

Enum, или перечисляемый тип, — это структура данных, с помощью которой можно определить набор именованных значений. Enum удобны, когда значение может принимать только ограниченное число вариантов. Вместо «магических» чисел или строк вы даёте значениям осмысленные имена, что повышает читаемость и снижает риск ошибок.

Кратко: enum отображает набор пар «ключ/значение» — ключ всегда строка, а значение по умолчанию — автоинкрементируемое число. Значения могут быть также строками или вычисляемыми выражениями.

Создание enum

Перечисления обычно задают фиксированный набор опций для некоторого параметра. Например, enum, представляющий основные цвета, может содержать Red, Yellow и Blue.

В TypeScript enum создают с помощью ключевого слова enum, затем указывают имя и блок фигурных скобок с членами перечисления. По соглашениям JavaScript/TypeScript имя enum обычно начинается с заглавной буквы.

enum Direction {  Up,  Down,  Left,  Right  
}  

В этом примере объявлено перечисление Direction с четырьмя членами. Поскольку явно не задано значение для членов, TypeScript присвоит им числовые значения, начиная с 0: Up = 0, Down = 1 и т.д. Если хотите — можно явно указать числа:

enum Direction {  Up = 0,  Down = 1,  Left = 2,  Right = 3,  
}  

Или смешивать: задать стартовое значение, а остальные пусть инкрементируются:

enum Status {  Active = 9,  Inactive,  // 10  
}  

Здесь Inactive автоматически получит значение 10.

Виды enum

TypeScript различает несколько вариантов перечислений по типу значений их членов.

Числовые enum

Это самый распространённый случай: члены перечисления получают числовые значения. Поведение описано выше — при отсутствии инициализатора значения автоинкрементируются.

Когда использовать: когда важно компактное представление в рантайме или когда значения используются в арифметике/индексации.

Строковые enum

Если все члены — строки, то нужно инициализировать каждый член строкой:

enum PrimaryColors {  Red = "RED",  Yellow = "YELLOW",  Blue = "BLUE"  
}  

Строковые enum удобны при сериализации (например, отправка в JSON) — их значения сразу читаемы.

Гетерогенные enum

Гетерогенные перечисления содержат и строки, и числа:

enum Result {  Success = "SUCCESS",  Failure = 0  
}  

TypeScript документация рекомендует избегать гетерогенных enum без веской причины: они усложняют код и повышают шанс ошибок.

Константные и вычисляемые члены

У каждого члена enum есть значение, которое может быть либо константой, либо вычисляемым.

Константные члены

Член считается константным, если выполняется хотя бы одно из условий:

  1. Это первый член enum и у него нет инициализатора.
  2. У члена нет инициализатора, и предыдущий член был числовой константой.
  3. Член инициализирован константным выражением (литерал и т.п.).

Константные выражения можно полностью вычислить во время компиляции. Это улучшает производительность и упрощает отладку, потому что при транспиляции в JavaScript заменяются конкретные значения.

Примеры константных enum:

// CASE 1  
enum Direction {  Up,  Down,  Left,  Right  
}  
  
// CASE 2  
enum Weekday {  Monday = 1,  Tuesday,  Wednesday,  Thursday,  Friday  
}  
  
// CASE 3  
enum Season {  Spring = "SPRING",  Summer = "SUMMER",  Autumn = "AUTUMN",  Winter = "WINTER"  
}  

Транспиляция константного строкового enum может выглядеть так:

var Season;  
(function (Season) {  
Season["Spring"] = "SPRING";  
Season["Summer"] = "SUMMER";  
Season["Autumn"] = "AUTUMN";  
Season["Winter"] = "WINTER";  
})(Season || (Season = {}));

Вычисляемые члены

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

enum Size {  Small = 1,  Medium = calculateSize(12),  Large = calculateSize(5)  
}  
  
functioncalculateSize(value: number): number{  
return value * 5;  
}  
  
console.log(Size.Large)  

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

var Size;  
(function (Size) {  
Size[Size["Small"] = 1] = "Small";  
Size[Size["Medium"] = calculateSize(12)] = "Medium";  
Size[Size["Large"] = calculateSize(5)] = "Large";  
})(Size || (Size = {}));  
  
console.log(Size.Large)  

Важно: если вам не нужна динамика в рантайме, предпочитайте константные члены.

Доступ к значениям enum

Доступ к значению члена enum осуществляется через точечную нотацию:

enum Direction {  Up = 0,  Down = 1,  Left = 2,  Right = 3,  
}  
  
console.log(Direction.Left)  // 2

Обратное отображение для числовых enum

В числовых enum TypeScript автоматически создаёт двунаправленное отображение: по имени вы получаете значение, а по значению — имя. Это удобно, когда у вас есть число и нужно узнать соответствующее имя члена.

Пример ручного обратного поиска:

enum Direction {  Up = 1,  Down,  Left,  Right  
}  
  
functiongetDirectionName(directionValue: number): string{  
// Reverse mapping  
const directionName = Direction[directionValue];  
return directionName;  
}  
  
console.log(getDirectionName(1)); // "Up"  
console.log(getDirectionName(3)); // "Left"  

Обратное отображение не работает для строковых enum — у них нет автоматического обратного соответствия.

Сценарии применения

Enum применяют в самых разных ситуациях:

  • Переключатели (switch) и ветвления по фиксированным состояниям.
  • Параметры функций и интерфейсы API для ограничения допустимых значений.
  • Карты сопоставления между кодом и читаемыми метками (например, коды ошибок).
  • Представление состояний конечного автомата или стадий процесса.

Enum повышают понятность и упрощают рефакторинг: IDE может подсказать все места использования члена, а компилятор поймает опечатки в именах.

Когда enum не подходит

Enum полезны, но не всегда оптимальны. Примеры, когда их лучше не использовать:

  • Множество динамически меняющихся значений (например, список категорий из БД). В таких случаях используйте типы строк (union of strings) или объектную структуру, загружаемую из данных.
  • Когда важна только сериализация и значения определяются вне кода — храните строки в конфиге/БД и используйте тип-проверки на уровне приложения.
  • Когда нужен строгий сопоставимый набор значений во внешних API с возможностью расширения без деплоя — лучше применять версионирование API или схему расширяемых тегов.

Counterexample: если список статусов приходит из сервера и может меняться, жестко зашитый enum приведёт к рассинхронизации.

Альтернативные подходы

  1. Union типов строк (string literal union):

    • type Status = “active” | “inactive” | “pending”;
    • Преимущество: проще встраивать в типы и легко сериализовать.
  2. Константные объекты:

    • const Status = { Active: “ACTIVE”, Inactive: “INACTIVE” } as const;
    • type Status = typeof Status[keyof typeof Status];
    • Позволяет использовать объектные операции и маппинг.
  3. Использовать Tagged unions (sum types) для сложных состояний с данными.

Выбор зависит от требований: нужен ли двунаправленный mapping, нужна ли компактность в рантайме, важна ли читаемость в логах.

Психические модели и эвристики

  • Если значения фиксированы и не изменятся после релиза — enum уместен.
  • Если важна читаемость логов и API — используйте строковые enum или константные строки.
  • Для небольшой динамики используйте объектные константы и union-тип.
  • Избегайте гетерогенных enum без жёсткой причины.

Эти простые правила помогут выбрать правильную структуру данных.

Практическая шпаргалка (cheat sheet)

  • Объявление: enum Name { A, B, C }
  • Явное присвоение: A = 1
  • Строки: A = “A”
  • Двунаправленный мэппинг: работает только для чисел
  • Константный член: литерал или вычислим из предыдущего числового
  • Вычисляемый член: использует вызов функции — значение в рантайме

Быстрая проверка перед использованием enum:

  • Меняется ли набор значений? Если да — enum может быть нежелателен.
  • Нужно ли обратное маппирование? Если да — используйте числовые enum.
  • Требуется ли сериализация в человекочитаемом виде? Если да — строковые enum.

Чеклисты по ролям

Для разработчика:

  • Проверил, изменится ли набор значений со временем.
  • Выбрал строковой enum для удобной сериализации.
  • Добавил комментарий/пример использования для каждого члена.
  • Написал юнит-тесты на граничные случаи (неизвестное значение).

Для архитектора:

  • Оценил влияние enum на контракт API.
  • Решил способ версионирования при расширении набора значений.
  • Выбрал между enum и динамической конфигурацией.

Критерии приёмки

  • Перечисление покрывает все допустимые состояния доменной области.
  • Наличие тестов: проверка сериализации и обработки неизвестных значений.
  • Нет жёстких зависимостей на значения enum в бизнес-логике (используйте имена, а не числа).
  • Документация и комментарии для нестандартных значений и гетерогенных enum.

Частые ошибки и крайние случаи

  • Ожидание обратного мэппинга для строковых enum. Это не сработает.
  • Использование enum для динамических списков — приводит к багам при обновлениях.
  • Смешение семантик: давать одному enum как смысловые ярлыки, так и машинные коды — усложняет поддержку.

Пример ошибки: сравнивать значение с числом, а затем сериализовать в API как строку — рассинхронизация возможна.

Безопасность и приватность

Enum сами по себе не добавляют риск безопасности. Но при использовании строковых enum в API убедитесь, что передаваемые значения проходят проверку на сервере. Не полагайтесь только на enum на клиенте как на защитный механизм.

Короткий глоссарий (1 строка каждой записи)

  • Enum: перечисление фиксированных именованных значений.
  • Член enum: отдельный элемент перечисления (ключ/значение).
  • Константный член: значение, известно на этапе компиляции.
  • Вычисляемый член: значение определяется в рантайме.
  • Гетерогенный enum: сочетание чисел и строк.

Примеры использования в реальном коде

  • Состояния UI: Loading, Success, Error.
  • Коды ошибок внутри приложения.
  • Параметры конфигурации, где набор заранее известен.

Итог

Enum в TypeScript — это удобный инструмент для моделирования конечных множеств значений. Выбирайте между числовым и строковым видом в зависимости от требований к сериализации и уровню строгой типизации. Избегайте гетерогенных enum без необходимости и заменяйте enum на union строк или константные объекты, если набор значений динамичен.

Важно: перед введением enum подумайте о будущем расширении набора значений и о том, как это скажется на API и конфигурации.

Краткие выводы:

  • Enum делают код выразительнее.
  • Числовые enum дают автоматическое обратное отображение.
  • Строковые enum удобнее для сериализации.
  • При динамичных данных лучше использовать другие подходы.
Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство