ПрограммированиеFrontend разработчик

Зачем нужны и как работают const enum в TypeScript? Чем они отличаются от обычных enum и какие есть подводные камни и ограничения при их использовании?

Проходите собеседования с ИИ помощником Hintsage

Ответ.

История вопроса:

Enum — тип, пришедший из С/С++ и других языков, для описания финитных наборов именованных констант. В JavaScript их не было, но в TypeScript реализована поддержка. Для повышения производительности был придуман const enum — расширение, при котором значения подставляются непосредственно на этапе компиляции, а не как полноценных объектов.

Проблема:

Обычные enum генерируют в JS значительный объём вспомогательного кода (объекты, обеспечивающие двустороннюю связь имя<->значение). Это не всегда нужно, особенно если важна максимальная производительность и минимальный размер бандла.

Решение:

Использовать const enum, если необходимо инлайнить значения при компиляции и избежать лишнего кода. Однако у const enum есть ограничения — они работают только внутри TypeScript-проекта, их сложно использовать при транспиляции в разные модули, и могут быть проблемы с tree shaking и import/export.

Пример кода:

const enum Direction { Up, Down, Left, Right } const move = Direction.Left; // В JS превратится просто в 2

Ключевые особенности:

  • Значения подставляются напрямую без генерации объекта enum.
  • Не поддерживаются сложные значения или вычисления в теле enum.
  • Неэкспортируемые (чаще всего ошибки при использовании в библиотеках или с isolatedModules).

Вопросы с подвохом.

Можно ли использовать const enum в d.ts-файлах и библиотеках общего пользования?

Нет. Рекомендуется избегать const enum в библиотеках, так как они inlined только при компиляции, а это зачастую вызывает ошибки при повторной сборке и описании типов.

Что произойдет при использовании const enum с параметром isolatedModules или при компиляции с babel?

Произойдет ошибка: babel и isolatedModules не поддерживают inlining const enum, так как не могут гарантировать безопасную подстановку значений на этапе компиляции одного файла.

Можно ли использовать вычисленные значения и строковые значения в const enum?

Сложные вычисления (например, выражения через функции или переменные) запрещены. Можно только простые числа и строки.

Типовые ошибки и анти-паттерны

  • Использование const enum в общем API библиотеки или в .d.ts-файлах.
  • Транспиляция без поддержки inlining const enum (например, через babel без специального плагина).
  • Добавление сложных выражений и строчных значений вместо простых.

Пример из жизни

Негативный кейс

Опубликовали const enum в библиотеке, описали его в .d.ts, потребитель получил ошибку из-за отсутствия строки импорта в итоговом бандле.

Плюсы:

  • Быстрое исполнение, нет лишнего кода в зависимых проектах.

Минусы:

  • Ошибки компиляции и runtime у пользователей.

Позитивный кейс

Использовали const enum только внутри приватных частей проекта, не экспортируя наружу:

const enum Color { Red, Green, Blue } let arr = [Color.Red, Color.Green];

Плюсы:

  • Компактный выходной JS-код.
  • Гарантия безопасности и простоты поддержки.

Минусы:

  • Нельзя экспортировать наружу.