Kodokon kodokon.com

Enum и const-утверждения: современные альтернативы

Разберись в ограничениях enum и выводи свои типы из замороженных констант с помощью as const.

7 мин · 3 вопросов

Открыть этот урок в Kodokon

enum есть в языке с самых первых версий, и ты встретишь его во множестве проектов. Он собирает именованные константы под одним типом, который годится и как значение, и как аннотация.

TYPESCRIPT
enum Role {
  User = "USER",
  Admin = "ADMIN",
}

function canDelete(role: Role): boolean {
  return role === Role.Admin;
}
Классический строковый enum

И всё же современная экосистема от него уходит. enum - это синтаксис, которого нет в JavaScript: компилятор порождает объект во время выполнения, что усложняет работу некоторых инструментов и несовместимо с опцией erasableSyntaxOnly. Альтернатива: обычный объект, замороженный через as const, из которого ты выводишь тип.

TYPESCRIPT
const ROLES = {
  User: "USER",
  Admin: "ADMIN",
} as const;

type Role = (typeof ROLES)[keyof typeof ROLES];

function canDelete(role: Role): boolean {
  return role === ROLES.Admin;
}
Объект as const с выведенным типом - современный эквивалент

as const работает и с массивами: каждый элемент становится литералом только для чтения, а (typeof SIZES)[number] даёт объединение значений. Один источник истины питает и работающий код, и типы.

TYPESCRIPT
const SIZES = ["sm", "md", "lg"] as const;

type Size = (typeof SIZES)[number];

function isSize(value: string): value is Size {
  return (SIZES as readonly string[]).includes(value);
}
Массив as const: перебираемый во время выполнения, объединение на уровне типов

Проверка знаний

Убедись, что запомнил ключевые моменты этого урока.

  1. Какое главное отличие enum от объекта, замороженного через as const?
    • enum - это специфичный для TypeScript синтаксис, который порождает код, а объект as const остаётся обычным JavaScript
    • Объект as const медленнее во время выполнения
    • enum может содержать только числа
  2. Что даёт as const, применённый к массиву ['sm', 'md']?
    • string[]
    • Кортеж литеральных типов только для чтения
    • Изменяемый массив типа Array<'sm' | 'md'>
    • Ошибку компиляции
  3. Как получить объединение значений объекта ROLES, замороженного через as const?
    • keyof typeof ROLES
    • (typeof ROLES)[keyof typeof ROLES]
    • typeof ROLES