В останніх версіях TypeScript легко оголосити типові типи об’єднання. Тому вам слід віддавати перевагу типам об’єднань перед переліченнями.
Як оголосити ітеративні типи об’єднань
const permissions = ['read', 'write', 'execute'] as const;
type Permission = typeof permissions[number];
for (const permission of permissions) {
}
Коли фактичні значення типу об'єднання не описують себе дуже добре, ви можете назвати їх так само, як і з переліками.
enum Permission {
Read = 'r',
Write = 'w',
Execute = 'x'
}
const Permission = {
Read: 'r',
Write: 'w',
Execute: 'x'
} as const;
type Permission = typeof Permission[keyof typeof Permission];
for (const permission of Object.values(Permission)) {
}
Не пропустіть as const
твердження, яке відіграє вирішальну роль у цих моделях.
Чому не добре використовувати перелічення?
1. Неперервні переліки не відповідають поняттю "набраний набір JavaScript"
Я думаю, що ця концепція є однією з найважливіших причин, чому TypeScript став настільки популярним серед інших мов altJS. Non-const перелічення порушують концепцію, випускаючи об'єкти JavaScript, які живуть під час виконання, із синтаксисом, який не сумісний з JavaScript.
2. У переліках Const є деякі підводні камені
Перерахування Const не можна перенести за допомогою Babel
На даний момент існує два способи вирішення цієї проблеми: позбутися const enum вручну або за допомогою плагіна babel-plugin-const-enum
.
Оголошення const enum у зовнішньому контексті може бути проблематичним
Переміщення навколишнього середовища не дозволяється, коли надається --isolatedModules
прапор. Член команди TypeScript каже, що " const enum
для DT насправді не має сенсу" (DT відноситься до DefinitelyTyped) і "Ви повинні використовувати об'єднаний тип літералів (рядок або число) замість" const enum в контексті оточення.
Const enum під --isolatedModules
прапором поводяться дивно навіть поза зовнішнім контекстом
Я був здивований, прочитавши цей коментар на GitHub, і підтвердив, що поведінка все ще відповідає дійсності з TypeScript 3.8.2.
3. Числові переліки не є безпечними для типу
Ви можете призначити будь-яке число числовим перелікам.
enum ZeroOrOne {
Zero = 0,
One = 1
}
const zeroOrOne: ZeroOrOne = 2;
4. Оголошення рядкових переліків може бути зайвим
Іноді ми бачимо такий тип перерахувань рядків:
enum Day {
Sunday = 'Sunday',
Monday = 'Monday',
Tuesday = 'Tuesday',
Wednesday = 'Wednesday',
Thursday = 'Thursday',
Friday = 'Friday',
Saturday = 'Saturday'
}
Я повинен визнати, що існує функція перерахування, яка не досягається за типами об’єднань
Навіть якщо з контексту очевидно, що значення рядка включено до переліку, ви не можете призначити його перерахуванню.
enum StringEnum {
Foo = 'foo'
}
const foo1: StringEnum = StringEnum.Foo;
const foo2: StringEnum = 'foo';
Це уніфікує стиль присвоєння значення перелічення в коді, виключаючи використання рядкових значень або рядкових літералів. Ця поведінка не узгоджується з тим, як поводиться система типу TypeScript в інших місцях, і це якось дивно, і деякі люди, які вважали, що це слід виправити, порушували проблеми ( це і це ), в яких неодноразово згадувалося, що намір перерахувань рядків є забезпечити "непрозорі" типи рядків: тобто їх можна змінювати, не змінюючи споживачів.
enum Weekend {
Saturday = 'Saturday',
Sunday = 'Sunday'
}
const weekend: Weekend = Weekend.Saturday;
Зверніть увагу, що ця "непрозорість" не є досконалою, оскільки присвоєння значень перерахування типам рядкових літералів не обмежується.
enum Weekend {
Saturday = 'Saturday',
Sunday = 'Sunday'
}
const saturday: 'Saturday' = Weekend.Saturday;
Якщо ви вважаєте, що ця "непрозора" функція настільки цінна, що ви можете прийняти всі описані вище недоліки в обмін на неї, ви не можете відмовлятися від перерахувань рядків.
Як усунути перелічення з вашої кодової бази
З no-restricted-syntax
правилом ESLint, як описано .