Добавить в корзинуПозвонить
Найти в Дзене
PurpleSchool

Подробный гайд по Enums в TypeScript

Перечисления (Enums) являются одной из немногих функций TypeScript, которые не являются расширением типовых функций JavaScript. Перечисления позволяют разработчику определить набор именованных констант. Использование перечислений может упростить документирование намерений или создание набора различных вариантов. TypeScript предоставляет как числовые, так и строковые перечисления. В конце статьи я также оставил вам блок бесплатных материалов для обучения разработке. Сначала мы начнем с числовых перечислений, которые, вероятно, более знакомы вам, если вы изучаете другие языки. Перечисление можно определить с помощью ключевого слова enum. Выше у нас числовое перечисление, где Up инициализируется значением 1. С этого момента все следующие члены автоматически увеличиваются. Другими словами, Direction.Up имеет значение 1, Down - 2, Left - 3 и Right - 4. При желании мы можем полностью отказаться от инициализаторов: Здесь Up будет иметь значение 0, Down - 1 и т. д. Такое поведение автоинкремен
Оглавление

Перечисления (Enums) являются одной из немногих функций TypeScript, которые не являются расширением типовых функций JavaScript. Перечисления позволяют разработчику определить набор именованных констант. Использование перечислений может упростить документирование намерений или создание набора различных вариантов. TypeScript предоставляет как числовые, так и строковые перечисления. В конце статьи я также оставил вам блок бесплатных материалов для обучения разработке.

Числовые перечисления

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

-2

Выше у нас числовое перечисление, где Up инициализируется значением 1. С этого момента все следующие члены автоматически увеличиваются. Другими словами, Direction.Up имеет значение 1, Down - 2, Left - 3 и Right - 4. При желании мы можем полностью отказаться от инициализаторов:

-3

Здесь Up будет иметь значение 0, Down - 1 и т. д. Такое поведение автоинкрементирования полезно в случаях, когда нам не важны сами значения членов перечисления, но важно, чтобы каждое значение отличалось от других значений в том же перечислении.

Использовать перечисления очень просто: просто обращайтесь к любому элементу как к свойству самого перечисления и объявляйте типы, используя имя перечисления:

-4

Числовые перечисления могут содержать вычисляемые и константные элементы. Короткая версия состоит в том, что перечисления без инициализаторов либо должны быть первыми, либо должны следовать за числовыми перечислениями, инициализированными числовыми константами или другими константными элементами перечисления. Другими словами, следующее недопустимо:

-5

Enums предоставляют удобный способ работы с набором именованных констант. Однако, их эффективное использование требует понимания тонкостей реализации и потенциальных ограничений. Неправильное использование Enums может привести к нечитаемому коду и проблемам с поддержкой. Если вы хотите детальнее погрузиться в тонкости работы с типами в TypeScript и освоить продвинутые техники, позволяющие создавать надежный и масштабируемый код — приходите на наш большой курс TypeScript с нуля. На курсе 192 уроков и 17 упражнений, AI-тренажеры для безлимитной практики с кодом и задачами 24/7, решение задач с живым ревью наставника, еженедельные встречи с менторами.

Строковые перечисления

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

-6

Хотя строковые перечисления не имеют автоинкрементного поведения, преимущество строковых перечислений в том, что они хорошо "сериализуются". Другими словами, если вы занимаетесь отладкой и вам нужно прочитать значение числового перечисления во время выполнения программы, то это значение часто бывает непрозрачным - оно не передает никакого полезного смысла само по себе (хотя обратное отображение часто может помочь). Строковые перечисления позволяют вам давать значимое и читаемое значение, когда ваш код работает, независимо от имени самого элемента перечисления.

Смешанные перечисления

В техническом плане перечисления могут быть смешаны со строковыми и числовыми элементами:

-7

Если вы не пытаетесь использовать поведение JavaScript во время выполнения в своих целях, рекомендуется этого не делать.

Вычисляемые и константные элементы

Каждый элемент перечисления имеет связанное с ним значение, которое может быть либо константным, либо вычисляемым. Элемент перечисления считается константным, если:

  • Он является первым элементом в перечислении и не имеет инициализатора, в этом случае ему присваивается значение 0: tsx // E.X является константным: enum E { X, }
  • Он не имеет инициализатора, и предыдущий элемент перечисления был числовой константой. В этом случае значение текущего элемента перечисления будет значением предыдущего элемента перечисления плюс один: tsx // Все элементы перечисления в 'E1' и 'E2' являются константными enum E1 { X, Y, Z, } enum E2 { A = 1, B, C, }
  • Элемент перечисления инициализирован выражением константного перечисления. Выражение константного перечисления - это подмножество выражений TypeScript, которые могут быть полностью вычислены во время компиляции.

Во всех остальных случаях элемент перечисления считается вычисляемым.

-8

Объединенные перечисления и типы элементов перечисления

Существует особое подмножество константных элементов перечисления, которые не вычисляются: литеральные элементы перечисления. Литеральный элемент перечисления - это константный элемент перечисления без инициализированного значения или с значениями, инициализированными:

  • Любым строковым литералом (например, "foo", "bar", "baz")
  • любым числовым литералом (например 1, 100)
  • унарным минусом, применённым к любому числовому литералу (например, -1, -100)

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

Первое - это то, что элементы перечисления также становятся типами. Например, мы можем сказать, что определенные элементы могут иметь только значение элемента перечисления:

-9

Другое изменение заключается в том, что сами типы перечислений эффективно становятся объединением каждого элемента перечисления. С объединенными перечислениями система типов может использовать тот факт, что она знает точный набор значений, которые существуют в самом перечислении. Благодаря этому TypeScript может перехватывать ошибки, когда мы, возможно, сравниваем значения неправильно. Например:

-10

В этом примере мы сначала проверили, является ли x не E.Foo. Если эта проверка пройдет, тогда наше || сократится, и тело 'if' будет выполняться. Однако, если проверка не удалась, тогда x может быть только E.Foo, поэтому не имеет смысла проверять, не равен ли он E.Bar.

Перечисления во время выполнения

Перечисления являются реальными объектами, существующими во время выполнения. Например, следующее перечисление

-11

можно передавать в функции

-12

Перечисления во время компиляции

Хотя перечисления являются реальными объектами, существующими во время выполнения, ключевое слово keyof работает иначе, чем можно было бы ожидать для обычных объектов. Вместо этого используйте keyof typeof для получения типа, представляющего все ключи перечисления в виде строк.

-13

Обратное преобразование

Помимо создания объекта со свойствами для элементов, числовые перечисления также получают обратное преобразование от значений перечисления к именам перечисления. Например, в этом примере:

-14

TypeScript компилирует это в следующий JavaScript:

-15

В этом сгенерированном коде перечисление компилируется в объект, который хранит как прямые (имя -> значение), так и обратные (значение -> имя) преобразование. Ссылки на другие элементы перечисления всегда выводятся как обращения к свойствам и никогда не встраиваются.

Обратите внимание, что для строковых элементов перечисления обратное преобразование вообще не генерируется.

const-перечисления

В большинстве случаев перечисления являются вполне подходящим решением. Однако иногда требования более жесткие. Чтобы избежать платы за дополнительный сгенерированный код и дополнительные непрямые обращения при доступе к значениям перечисления, можно использовать const-перечисления. Const-перечисления определяются с помощью модификатора const:

-16

Const-перечисления могут использовать только выражения константных перечислений и, в отличие от обычных перечислений, они полностью удаляются во время компиляции. Элементы const-перечисления встраиваются в места использования. Это возможно, поскольку const-перечисления не могут иметь вычисляемых элементов.

-17

Пример выше в сгенерированном коде станет

-18

Окружающие перечисления

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

-19

Одно важное отличие между окружающим и не окружающим перечислениями в том, что в обычных перечислениях элементы, не имеющие инициализатора, считаются константными элементами. Для элемента не константного окружающего перечисления, не имеющего инициализатора, элемент считается вычисляемым.

Объекты против перечислений

В современном TypeScript вам может не понадобиться перечисление, когда достаточно будет объекта с параметром as const:

-20

Главный аргумент в пользу этого формата по сравнению с перечислениями TypeScript заключается в том, что он держит ваш код в гармонии с состоянием JavaScript, и когда/если перечисления будут добавлены в JavaScript, вы сможете перейти к дополнительному синтаксису.

Заключение

В данной статье мы рассмотрели перечисления (enums) в TypeScript, как инструмент для создания наборов именованных констант. Изучили различные типы перечислений: числовые, строковые и константные (const enum), а также концепции константных и вычисляемых элементов. Подчеркнуто, что перечисления позволяют повысить читаемость, поддерживаемость и типобезопасность кода. Рассмотрено применение перечислений в качестве типов для создания более строгих интерфейсов. Понимание этих концепций позволяет разработчикам TypeScript создавать более структурированный и эффективный код.

Enum'ы – полезный инструмент, но TypeScript предлагает и другие способы создания типов, например, с использованием Type Aliases и Union Types. Грамотное применение этих альтернатив позволит создавать более гибкие и поддерживаемые решения. Чтобы систематизировать знания о типах, их создании и продвинутых возможностях TypeScript, изучите наш курс TypeScript с нуля. В первых 3 модулях уже доступно бесплатное содержание — начните погружаться в мир TypeScript прямо сегодня.

Бесплатные полезности

  1. Смотрите видео: код-ревью, собеседования и новости разработки на нашем Дзене – https://dzen.ru/purpleschool?tab=longs
  2. Создайте личный план обучения и получите доступ к базе из 500+ бесплатных уроков в бесплатных картах развития на нашем сайте – https://purpleschool.ru/skills
  3. Разберитесь в том, как устроен мир IT на бесплатном курсе «Основы разработки» – https://purpleschool.ru/course/code-basics