Typescript ENUM — баланс использования

Привет Всем.

Меня зовут Михаил. В НЛМК нахожусь на должности Frontend-разработчика.  Занимаюсь разработкой внутренних информационных систем на React + Typescript.

В этой статье поговорим про тип enum (перечисление) в Typescript, о случаях когда его можно и нужно использовать, а когда нет.

Перечисления бывают числовыми и строковыми. Например, представим в виде перечисления должности работников кафе.

Рассмотрим перечисления с числовыми значениями:

ed878febf943acaf3afc4327e0099b2c.png

Каждому элементу перечисления соответствует числовая константа начиная с 0 и увеличивается на 1 при движении сверху вниз по перечислению.

В этом легко убедиться:

256e01ac48aca189dcf9bdbc2cc4ff0f.png

в консоле мы увидим следующее:

925e82907aef60152986fcde96b195ea.png

Можно менять порядок, если проинициализировать один из элементов числовым значением.

dd9875b671dfda6845ebf753a90cd869.png

Тогда элементы после будут увеличены на 1 от заданного значения:

0e2dceb35e4481b689cfec49a9d86d09.png

Рассмотрим перечисления со строковыми значениями:

da97a7355ef50e14792fa4383c04ba42.png

в консоли мы увидим:

6bf0ac3207909d9e1f8b34a7f1116964.png

Числовые и строковые перечисления можно смешивать.

TypeScript компилируется в JavaScript. При компиляции типы удаляются и остается чистый JavaScript код. Например, простая функция суммирования с определением типов

1df43802a99c8a8c78bae06000443224.png

превратится в:

e3d61c44f3ba541f17cae0ded22dee11.png

Как мы видим, компилятор удалил все объявления типов.

Но с enum это работает немного иначе.

Разберем для чего и когда можно использовать enum, а когда лучше обойтись простым константным объектом.

Основной аргумент против enum — при компиляции enum, компилятор создает дополнительный JavaScript код и усложняет работу компилятору.

Вернемся к примеру с перечислением должностей работников кафе.

Используем enum и посмотрим на результат компиляции:  

7b19a4b24be3603794ff62362a341b02.png

превратилось в:

ec86d7629d12718c78b7f212b057666f.png

Получили не очень приятную конструкцию, состоящую из переменной и анонимного самовызывающегося функционального выражения.

При этом можно использовать методы объекта, например:

35688e44a65b25a1b37087ddbc1a8f6c.png

В консоли мы увидим:  

fab86089fdb5204bbf6939bc3eb0a923.png

Попробуем заменить enum на константный объект и посмотрим результаты компиляции:

943dd4fab0a0b0c6a5a154ad84124a0f.png

превратится в:  

96a1eebc3d3bbcf736488f75d86fe5ce.png

Тут константный объект определенно хорош.

Но enum может еще лучше!  

Для этого используем ключевое слово const:

05658a3a06d9ef1c072d8aff64a8d9a5.png

Взглянем на результат компиляции:

8deab2a95103ad478143d4159b420bf0.png

Теперь нет объекта, нет лишней переменной и анонимного самовызывающегося функционального выражения.

Получается, enum использовать даже профитнее, чем объект?

В этой части да, но есть несколько нюансов:

  1. Если в вашем проекте в файле tsconfig.json в секции compilerOptions  свойство  preserveConstEnums выставлено со значением  true, то эффекта от использования const enum не будет.

    5e5d9e6f8d40ff0ed87c80ed082ec234.png

Проверим это на нашем примере.

Поставим флаг в true:

e47c013fc3ed47565b129b2306ae69a7.png

И посмотрим на результат компиляции:

97d1f707d6255a53a0eaa7680fd606c0.png

превратился в:  

cc4fcd1c827be68a07209c4533f37b63.png

Т.е. весь эффект от использования const enum потерян и не имеет смысла.

  1. Если вам необходим только доступ к значению,   то однозначно используйте enum.

А вот если вам нужно где-то перебрать или получить все значения или ключи, то используйте константный объект а не const enum.

Почему не const enum, смотрим:

c056d265409b7fdb0a077c0e6e26c973.png

Мы увидим ошибку:

5ac7d310b094bf51122b807141eb4f82.png

А все потому, что нашего const enum не окажется в скомпилированном коде.

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

О типизации

Типизируем параметр принимаемый функцией »printPosition»:

08be4ccdd7cf40d2cafd74384102a5d2.png

или так:

b24bbb4d2bfc7d2a522909fe5c9af4dd.png

Но руками создавать union тип — это не то, что хотелось бы делать.

При использовании enum:  

bb5c4c5b52a1fa6b26b97666bd2512d3.pnged37009576fb3d87657d9f7f017bd51b.png

достаточно использовать шаблонную строку. Главное не забывать использовать const

Итак, подытожим плюсы и минусы использования enum:

Минусы:

  1. При использовании enum без const компилятор создает дополнительный JavaScript код, что усложняет работу компилятору и размер финального бандла;  

  2. При использовании enum с const — нет возможности получить для обработки все ключи или значения enum.

  3. Необходимо следить за флагом свойства preserveConstEnums в файле  tsconfig.json в секции compilerOptions, чтобы получить профит.  

Плюсы:

  1. При использовании const enum и необходимости только в значении дает отсутствие избыточного кода в скомпилированном  JavaScript, а значит, меньший размер и лучшую производительность;

  2. При использовании const enum — возможность быстрой и удобной типизации в отличие от использования константных объектов;

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

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

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

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

Итого:

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

Спасибо за внимание! Пишите комментарии, буду рад узнать ваше мнение по данному вопросу!

© Habrahabr.ru