Как получить имена элементов перечисления (enum)?
Я хочу перебрать объект enum в TypeScript и получить имена каждого перечисляемого символа. Например, у меня есть следующий enum:
enum myEnum { entry1, entry2 }
Я решил использовать цикл for-in, чтобы пройтись по элементам:
for (var entry in myEnum) {
// здесь нужно использовать имя entry, например, "entry1"
}
Однако это не работает так, как я ожидал. Как правильно получить имена символов из enum в TypeScript?
5 ответ(ов)
Код, который вы привели, будет работать; он выведет все элементы перечисления (enum), включая значения этих элементов. Например, следующий код:
enum myEnum { bar, foo }
for (var enumMember in myEnum) {
console.log("член перечисления: ", enumMember);
}
выведет следующее:
Член перечисления: 0
Член перечисления: 1
Член перечисления: bar
Член перечисления: foo
Если вы хотите получить только имена членов перечисления, а не их значения, вы можете сделать что-то похожее на это:
for (var enumMember in myEnum) {
var isValueProperty = Number(enumMember) >= 0
if (isValueProperty) {
console.log("член перечисления: ", myEnum[enumMember]);
}
}
Это выведет только имена:
Член перечисления: bar
Член перечисления: foo
Предупреждение: этот подход немного зависит от деталей реализации: TypeScript компилирует перечисления в объект JS, где значения перечисления являются членами объекта. Если TypeScript решит реализовать их по-другому в будущем, данный метод может перестать работать.
Простой и практичный способ понять, что происходит с перечислением, выглядит так:
enum colors { red, green, blue };
На самом деле будет преобразовано примерно в следующее:
var colors = { red: 0, green: 1, blue: 2,
[0]: "red", [1]: "green", [2]: "blue" }
Исходя из этого, будет верно следующее:
colors.red === 0
colors[colors.red] === "red"
colors["red"] === 0
Это создает удобный способ получить имя перечисленного значения следующим образом:
var color: colors = colors.red;
console.log("Выбранный цвет: " + colors[color]);
Также это создает удобный способ конвертации строки в значение перечисления.
var colorName: string = "green";
var color: colors = colors.red;
if (colorName in colors) color = colors[colorName];
Эти две ситуации гораздо более распространены, потому что, как правило, вам больше интересно имя конкретного значения и сериализация значений в универсальном виде.
Если вам нужно получить только имена и затем итерировать по ним, вы можете использовать следующий код:
const result = Object.keys(myEnum)
.map(key => myEnum[key])
.filter(value => typeof value === 'string') as string[];
Этот код сначала извлекает все ключи из перечисления (myEnum
), затем с помощью map
получает соответствующие значения для этих ключей, и в итоге фильтрует только строковые значения. Результат будет массивом строк.
Если вы соблюдаете правила и создаете перечисления (enums) только с числовыми значениями, вы можете использовать следующий код. Он корректно обрабатывает случай, когда имя перечисления совпадает с допустимым числовым значением.
enum Color {
Red,
Green,
Blue,
"10" // что?
}
var names: string[] = [];
for (var n in Color) {
if (typeof Color[n] === 'number') names.push(n);
}
console.log(names); // ['Red', 'Green', 'Blue', '10']
В этом коде, благодаря циклу for...in
, мы можем перебрать все элементы перечисления Color
. Условие if (typeof Color[n] === 'number')
помогает нам отличить имена от значений, и в итоге мы получаем массив names
, который включает в себя как стандартные имена, так и имена, представляющие числовые значения.
Похоже, что ни одно из предложенных здесь решений не сработает с строковыми перечислениями в режиме strict
.
Рассмотрим перечисление:
enum AnimalEnum {
dog = "dog", cat = "cat", mouse = "mouse"
}
При попытке доступа к этому перечислению с использованием AnimalEnum["dog"]
может возникнуть ошибка, подобная следующей:
Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'typeof AnimalEnum'.ts(7053)
.
Чтобы правильно решить эту проблему, запишите доступ следующим образом:
AnimalEnum["dog" as keyof typeof AnimalEnum]
Сравнение членов enum в Java: использовать == или equals()?
'unknown' против 'any': в чем разница?
@Directive против @Component в Angular
ESLint: 8.0.0 Не удалось загрузить плагин '@typescript-eslint'
Как создать заглушку для интерфейса / определения типа в TypeScript?