Комментарии 21
Если мне не изменяет память то создатель TS жаловался на enum. Я полез в гугл чтобы найти ту статью, но поиск выдал очень много статей
Как говорится: отрицаешь - предлагай:
Вместо enum можно использовать объектыconst Position = { Director: 'Генеральный директор', Seller: 'Продавец' } as const
А вместо объектов можно использовать строковые и числовые переменные, только зачем?
Жалуетесь на енамы, при этом причины не приводите, так может быть с ними все хорошо и не надо колдовать?
Причина заключается в том, что это не стандарт языка, а нечто, что привносит TypeScript в рантайм, в отличие от остальной типизации, которая просто удаляется во время траспиляции. И как и в случае с декораторами, когда данная конструкция появится в JavaScript, она может сильно отличаться от текущей реализации. Возможно если бы enum'ы были за экспериментальным флагом как и декораторы, больше людей обращало бы на это внимания.
В документации TS есть аргумент в пользу объектов как раз из-за совместимости.
Объект не может заменить енум тк его нельзя использовать в качестве типа. Элементарно нельзя сделать
function foo(position: Position) {
}
type Position = typeof Positions[keyof typeof Positions];
Сделать обёртку над двойным typeof оставляю в качестве домашнего задания.
Если мне не изменяет память то создатель TS жаловался на enum.
Насколько помню, это связано, в первую очередь с тем, что enum
существует не только на уровне типов, а транслируется в не слишком очевидный код. Это противоречит современной философии TypeScript - добавлять фичи только на уровне типов, а если нужно что-то поменять в семантике времени исполнения - писать пропозалы для ECMAScript.
В том числе, с enum
можо зачем-то делать вот такую магию.
Этот нюанс решается с помощью const enum
Это очень хороший комментарий.
Два прекрасных подхода к перечислениям, - enum
и as const
Enum, конечно, самый универсальный, являясь и значением и типом.
Если объявлять объектом
`const Positions = { Director: 'Генеральный директор', Seller: 'Продавец' } as const;`
То для типа не обойтись без чего-то вроде
`type
Positions = (typeof
Positions)[keyof typeof
Positions];`
(что абсолютно то же самое, что 'Директор' | 'Продавец')
Но тут есть хорошая особенность! Что для одной задачи недостаток (когда позиции надо строго зафиксировать в enum), а для другой преимущество (когда необходимо работать с внешними текстами).
Дело в том, что при enum нельзя присвоить const seller: Positions.Seller = 'Продавец';
Только из enum, будьте добры. С объектом - ok.
Такая штука.
Так enum это и есть обёртка над объектами. Так же можно сказать что вместо async await можно использовать promise. Никто не спорит. Вкусовщина.
Самый простой и быстрый (но неправильный) способ решить эту проблему
И вроде бы проблема решена, но нет.
Расскажите пожалуйста почему неправильно и почему проблема не решена ?
Ну потому, что если через какое то время должность "бухгалтер" изменится на "старший бухгалтер" вам придётся менять все строки "бухгалтер" в коде. А найти их все будет ой как не просто
Во первых не понятно почему найти их будет непросто. Во вторых пример странный ибо это две разные должности. В третьих совершенно не факт что энум должен выводиться на экран. Но окей, допустим выводится и нужно изменить вывод. Для этого достаточно на всякий случай сделать малюсенькую функцию вывода и при выводе использовать её.
const getPositionView = (pos: Position) => pos === 'бухгалтер'
? "Старший бухгалтер"
: pos === "Директор"
? "Младший директор"
: pos
Проблема решена
Typescript умеет переименовывать константные строки, как и находить на них ссылки
Принял, если проблема только в этом, то получается на вкус и цвет )
Что касается меня, то:
1) не нравится лишний импорт.
2) напрягает, что оно компилится в настоящий JS код. В нынешнее время это конечно так себе аргумент, но это чисто моё "фе" )
П.С. Не хочу с вами спорить, будет чисто сотрясание воздуха, но пример у вас неудачный) Старший бухгалтер не появится в экосистеме, где невозможен обычный бухгалтер. Так что вы просто расширите enum. А вот если пропадет "бухгалтер" и появится "грузчик" с такой же бизнесовой логикой(пример тоже кстати отстой, тут важна идея), то вам скорее всего так же придется переименовывать ваш enum, ну типа как так то, под переменной "accountant" скрывается "грузчик" ))
Самый простой и быстрый (но неправильный) способ решить эту проблему - создать условный тип и перечислить в типе все возможные значения:
type Position = 'Директор' | 'Продавец';
interface Person {
name: string;
age: number;
position: Position;
}
Но ведь здесь нет условного типа (conditional type). Даже если вы не это имели в виду думаю что не стоит путать читателя.
Работа с Enum, как с интерфейсами.
Здесь и далее по текста - а при чём тут собственно интерфейсы? Почему "как с интерфейсами"?
И теперь, с помощью employeeTypeChecker, мы можем точно получить тип пользователя, с которым имеем дело в каждом конкретном случае. ... Это стало возможным благодаря тому, что в функции employeeTypeChecker мы работаем с Enum как с интерфейсом.
Ни интерфейсы, ни енамы здесь ни при чём. Приведённый вами employeeTypeChecker
точно так же воспроизводится с "неправильными" литеральными типами.
Также для полноты статьи стоило бы упомянуть такое явление, как const enum
, да и в целом проговорить почему енамы являются темой для споров в сообществе. У них ведь есть заметные недостатки при всех их преимуществах.
сомнительные преимущества, при использовании тех же литеральных типов мы имеем отличный автокомплит в ide и не обязаны каждый раз импортировать enum, если нужно где-то использовать тип с ним внутри
Блин... Что за система у вас такая, что при использовании фактически справочных элементов приходится контролировать соответствие значения элементу справочника?
Каким образом туда может попасть не то значение?
Несоответствие типа при ручном вводе еще можно понять, но несоответствие строки... Если нужно строгое соответствие, то не даёте вводить руками. Только select и т.п.
Не могу представить ни одного сценария, когда описанное вообще имеет смысл... Эдакая сферическая в вакууме проблема.
TypeScript здорового человека, или почему с Enum лучше