Ответ
Enums в TypeScript имеют несколько потенциальных проблем:
- Числовые enums могут быть небезопасными — они допускают невалидные значения:
enum Status {
Active = 1,
Inactive = 2
}
const s: Status = 999; // Ошибки не будет
- Обратное маппинг может сбивать с толку:
enum Color { Red = 1 }
console.log(Color[1]); // "Red" - не всегда ожидаемое поведение
-
Tree-shaking — enums генерируют реальный код в runtime, что мешает удалению неиспользуемого кода.
-
Строковые enums не поддерживают обратное маппинг вообще.
-
Const enums решают проблему tree-shaking, но требуют
preserveConstEnumsи не работают в изолированных модулях.
Альтернатива — использовать union types:
type Status = 'active' | 'inactive'; Ответ 18+ 🔞
Слушай, давай разберём эту дичь с энамами в TypeScript, а то народ путается, как в тёмной комнате хуй искать.
Первое, что надо понять — числовые энамы это такая себе затея. Выглядит вроде прилично, объявил коды статусов, а под капотом-то пиздец. Допустим, сделали мы так:
enum Status {
Active = 1,
Inactive = 2
}
И вроде всё типобезопасно, ан нет! Какой-нибудь левый импорт или API может подсунуть тебе хуйню, и компилятор проглотит это, как манная каша.
const currentStatus: Status = 999; // И ни одной ошибки, ёпта!
Представляешь? Ты ждёшь 1 или 2, а тебе прилетает 999. Это как заказать пиццу, а тебе в коробке привозят дохлого хомяка — тип вроде еда, а нихуя не то.
Дальше — обратное маппирование. Это такая фишка, которая мозг выносит новичкам.
enum Color { Red = 1 }
console.log(Color[1]); // Выведет "Red"
С одной стороны, удобно. С другой — зачем? Это же чисто рантаймовая фигня, которая код раздувает. Ты хотел просто типы, а получил целый объект с ключами туда-сюда. Ёперный театр!
И вот это раздувание — третья проблема, tree-shaking. Энамы на выходе становятся реальными JavaScript-объектами. Если ты используешь только пару значений, весь enum всё равно попадёт в бандл. Мёртвый код не удаляется, как гандон прилипший.
Со строковыми энамами (enum Direction { Up = "UP" }) обратного маппинга вообще нет, что тоже иногда бесит.
Есть, конечно, const enum. Вот это вроде умная мысль — они полностью удаляются при компиляции, на их месте остаются только значения.
const enum Size { Small, Medium }
const mySize = Size.Small; // В JS станет просто `const mySize = 0;`
Но и тут, блядь, подвох! Чтобы они работали в изолированных модулях, нужно флаг preserveConstEnums или ещё какая-то магия. А без него — просто сломается всё, пидары налетели.
Так что же делать, если энамы такие проблемные? А альтернатива-то проще некуда, честное слово!
Используй union types из литералов:
type Status = 'active' | 'inactive';
type HttpCode = 200 | 404 | 500;
Смотри, какая красота:
- Никакого рантайм-кода — чистые типы, которые после компиляции испаряются.
- Полная типобезопасность —
const s: Status = 'pending'вызовет ошибку, ибо'pending'нет в разрешённых значениях. Никаких 999! - Отлично дружит с tree-shaking — ничего лишнего в бандле.
Короче, если тебе не нужна именно рантаймовая структура (например, для итерации по всем значениям), забей на классические enum. Юнион типы — твой друг, товарищ и брат. Меньше головной боли, меньше неожиданностей. Всё гениальное — просто, а всё сложное — часто просто хуйня.