Проверка наличия значения в Enum TypeScript: полное руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Зачем проверять значение в Enum TypeScript? Живой пример из практики

Представьте: вы пишете бэкенд на Node.js с TypeScript. Клиент присылает статус заказа — строку "shipped". У вас есть enum OrderStatus с вариантами: Pending, Processing, Shipped, Delivered. Но вдруг приходит "CANCELLED" или "unknown". Что делать? Правильно — проверить, существует ли значение в enum TypeScript.

Эта задача — одна из самых частых на Stack Overflow (тысячи просмотров). И не зря: enum в TypeScript — не просто набор констант, а хитрый зверь с числовыми и строковыми вариантами. В этом руководстве мы разберем все способы проверки наличия значения в enum, от простых до продвинутых, с примерами кода и пояснениями.

Если вы только начинаете изучать TypeScript или хотите углубить знания — эта статья для вас. Поехали!

Что такое Enum в TypeScript? Краткий ликбез

Enum (перечисление) — это способ задать набор именованных констант. В TypeScript есть два типа enum:

  • Числовые enum — значения автоматически инкрементируются (0, 1, 2...).
  • Строковые enum — каждому члену явно присваивается строка.

Пример числового enum:

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

Пример строкового enum:

enum Status {
    Active = "ACTIVE",
    Inactive = "INACTIVE",
    Pending = "PENDING"
}

Зачем вообще проверять значение? Потому что данные извне (API, формы, базы данных) могут быть любыми. Без проверки вы рискуете получить undefined или ошибку выполнения.

Способ 1. Классика: Object.values() + includes()

Самый популярный и читаемый способ — превратить enum в массив значений и проверить вхождение с помощью includes().

Для строковых enum:

enum Color {
    Red = "RED",
    Green = "GREEN",
    Blue = "BLUE"
}

function isColor(value: string): boolean {
    return Object.values(Color).includes(value as Color);
}

console.log(isColor("RED"));    // true
console.log(isColor("YELLOW")); // false

Для числовых enum — хитрость! Object.values() возвращает обратную маппинг (ключи и значения). Поэтому нужно фильтровать только числа:

enum NumberEnum {
    A = 1,
    B = 2,
    C = 3
}

function isNumberEnumValue(value: number): boolean {
    return Object.values(NumberEnum).filter(v => typeof v === 'number').includes(value);
}

console.log(isNumberEnumValue(2)); // true
console.log(isNumberEnumValue(5)); // false

Этот подход универсален, но требует осторожности с числовыми enum. Плюс: простой и наглядный. Минус: нужно помнить про фильтрацию.

Способ 2. Type Guard: проверка через ключи enum

Если вам нужно не просто проверить значение, но и получить гарантию типа, используйте type guard. Этот метод особенно полезен при работе с API, где вы хотите сузить тип.

enum UserRole {
    Admin = "admin",
    User = "user",
    Guest = "guest"
}

function isUserRole(value: string): value is UserRole {
    return Object.values(UserRole).includes(value as UserRole);
}

function processRole(role: string) {
    if (isUserRole(role)) {
        // TypeScript знает, что role — это UserRole
        console.log(`Роль: ${role}`);
    } else {
        console.log("Неизвестная роль");
    }
}

processRole("admin"); // Роль: admin
processRole("moderator"); // Неизвестная роль

Этот подход дает безопасность типов и сокращает количество проверок в коде. Рекомендую для серьезных проектов.

Способ 3. Кастомный хелпер: универсальная функция

Чтобы не писать однотипные проверки для каждого enum, создайте универсальную функцию-хелпер. Это лучшая практика для больших кодовых баз.

// Утилита для проверки значений в любом enum
function enumContains<T extends Record<string, string | number>>(
    enumObj: T, 
    value: string | number
): value is T[keyof T] {
    return Object.values(enumObj).includes(value as T[keyof T]);
}

// Использование
enum HttpStatus {
    OK = 200,
    NotFound = 404,
    ServerError = 500
}

enum Direction {
    North = "NORTH",
    South = "SOUTH"
}

console.log(enumContains(HttpStatus, 200)); // true
console.log(enumContains(HttpStatus, 403)); // false
console.log(enumContains(Direction, "SOUTH")); // true
console.log(enumContains(Direction, "EAST")); // false

Этот хелпер работает и с числами, и со строками. Совет: вынесите его в отдельный модуль utils/enum.ts и используйте во всем проекте.

Способ 4. Для числовых enum: проверка через обратный маппинг

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

enum StatusCode {
    Success = 1,
    Failure = 2,
    Pending = 3
}

function isStatusCode(value: number): boolean {
    return value in StatusCode;
}

console.log(isStatusCode(1)); // true (ключ "Success")
console.log(isStatusCode(4)); // false

Но будьте осторожны: оператор in проверяет ключи, а для числовых enum ключи — это строки "1", "2" и т.д. Поэтому value in StatusCode работает только для чисел, которые являются значениями enum. Минус: не работает для строковых enum (там нет обратного маппинга).

Способ 5. Использование Map или Set для производительности

Если вы проверяете значения десятки тысяч раз (например, в цикле обработки данных), массив includes() может быть медленным. Решение — создать Set или Map из значений enum один раз и использовать его.

enum PaymentMethod {
    Card = "card",
    Cash = "cash",
    Crypto = "crypto"
}

// Создаем Set для быстрой проверки
const paymentMethodSet = new Set(Object.values(PaymentMethod));

function isValidPaymentMethod(value: string): boolean {
    return paymentMethodSet.has(value);
}

// Тестирование
console.log(isValidPaymentMethod("card"));   // true
console.log(isValidPaymentMethod("bitcoin")); // false

Для числовых enum используйте ту же технику, но с фильтрацией (как в способе 1). Производительность: Set.has() — O(1), Array.includes() — O(n). Разница заметна на больших данных.

Блоги

Рекомендаций по книгам