Я хотел бы повторить TypeScript тип enum
и получить имя каждого перечисляемого символа, например:
enum myEnum { entry1, entry2 }
for (var entry in myEnum) {
// use entry name here, e.g., "entry1"
}
Я хотел бы повторить TypeScript тип enum
и получить имя каждого перечисляемого символа, например:
enum myEnum { entry1, entry2 }
for (var entry in myEnum) {
// use entry name here, e.g., "entry1"
}
Код, который вы опубликовали, будет работать; он распечатает все члены перечисления, включая значения членов перечисления. Например, следующий код:
enum myEnum { bar, foo }
for (var enumMember in myEnum) {
console.log("enum member: ", enumMember);
}
Выведет следующее:
Enum member: 0
Enum member: 1
Enum member: bar
Enum member: foo
Если вам нужны только имена членов, а не значения, вы можете сделать что-то вроде этого:
for (var enumMember in myEnum) {
var isValueProperty = parseInt(enumMember, 10) >= 0
if (isValueProperty) {
console.log("enum member: ", myEnum[enumMember]);
}
}
Это напечатает только имена:
Член enum: bar
Участник enum: foo
Предостережение: это немного зависит от детали реализации: TypeScript скомпилирует перечисления в объект JS с значениями перечисления, являющимися членами объекта. Если бы TS решила реализовать их в будущем, описанная выше техника может нарушиться.
Хотя ответ уже предоставлен, почти никто не указал на документы
Вот фрагмент
enum Enum {
A
}
let nameOfA = Enum[Enum.A]; // "A"
Ого. Это закончилось тем, что стало проще, чем я думал, и это не имеет никакого отношения ко мне, что бы то ни было.
enum myEnum { entry1, entry2 }
console.log(myEnum[myEnum.entry1]); // Will output "entry1" to the console.
Предполагая, что вы придерживаетесь правил и только производите перечисления с числовыми значениями, вы можете использовать этот код. Это правильно обрабатывает случай, когда у вас есть имя, совпадающее с допустимым числом
enum Color {
Red,
Green,
Blue,
"10" // wat
}
var names: string[] = [];
for(var n in Color) {
if(typeof Color[n] === 'number') names.push(n);
}
console.log(names); // ['Red', 'Green', 'Blue', '10']
Для меня более простой, практичный и прямой способ понять, что происходит, заключается в следующем перечислении:
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("The color selected is " + colors[color]);
Он также создает хороший способ преобразования строки в нумерованное значение.
var colorName: string = "green";
var color: colors = colors.red;
if (colorName in colors) color = colors[colorName];
Две ситуации выше - гораздо более распространенная ситуация, потому что обычно вас гораздо больше интересует имя определенного значения и сериализует значения в общем виде.
Если вы только ищите имена и итерации позже, используйте:
Object.keys(myEnum).map(key => myEnum[key]).filter(value => typeof value === 'string') as string[];
С текущим TypeScript Версия 1.8.9 я использую типизированные перечисления:
export enum Option {
OPTION1 = <any>'this is option 1',
OPTION2 = <any>'this is option 2'
}
с результатами в этом объекте Javascript:
Option = {
"OPTION1": "this is option 1",
"OPTION2": "this is option 2",
"this is option 1": "OPTION1",
"this is option 2": "OPTION2"
}
поэтому я должен запрашивать ключи и значения и возвращать только значения:
let optionNames: Array<any> = [];
for (let enumValue in Option) {
let optionNameLength = optionNames.length;
if (optionNameLength === 0) {
this.optionNames.push([enumValue, Option[enumValue]]);
} else {
if (this.optionNames[optionNameLength - 1][1] !== enumValue) {
this.optionNames.push([enumValue, Option[enumValue]]);
}
}
}
И я получаю ключи опций в массиве:
optionNames = [ "OPTION1", "OPTION2" ];
Начиная с Typescript 2.4, перечисления могут содержать инициализаторы строк https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html.
Это позволяет вам написать:
enum Order {
ONE = "First",
TWO = "Second"
}
console.log('One is ${Order.ONE.toString()}');
и получить этот вывод:
Один первый
Это решение тоже работает.
enum ScreenType {
Edit = 1,
New = 2,
View = 4
}
var type: ScreenType = ScreenType.Edit;
console.log(ScreenType[type]); //Edit
Другое интересное решение , найденное здесь, использует карту ES6:
export enum Type {
low,
mid,
high
}
export const TypeLabel = new Map<number, string>([
[Type.low, 'Low Season'],
[Type.mid, 'Mid Season'],
[Type.high, 'High Season']
]);
USE
console.log(TypeLabel.get(Type.low)); // Low Season
Пусть ts-enum-util
(github, npm) сделает всю работу за вас и предоставит множество дополнительных типобезопасных утилит. Работает как со строковыми, так и с числовыми перечислениями, должным образом игнорируя записи обратного просмотра числового индекса для числовых перечислений:
Строковое перечисление:
import {$enum} from "ts-enum-util";
enum Option {
OPTION1 = 'this is option 1',
OPTION2 = 'this is option 2'
}
// type: ("OPTION1" | "OPTION2")[]
// value: ["OPTION1", "OPTION2"]
const keys= $enum(Option).getKeys();
// type: Option[]
// value: ["this is option 1", "this is option 2"]
const values = $enum(Option).getValues();
Числовое перечисление:
enum Option {
OPTION1,
OPTION2
}
// type: ("OPTION1" | "OPTION2")[]
// value: ["OPTION1", "OPTION2"]
const keys= $enum(Option).getKeys();
// type: Option[]
// value: [0, 1]
const values = $enum(Option).getValues();
Вы можете использовать пакет enum-values
который я написал, когда у меня была такая же проблема:
var names = EnumValues.getNames(myEnum);
Начиная с машинописного текста 2.4, перечисление больше не будет содержать ключ в качестве члена. источник из Tymescript readme
Предостережение заключается в том, что инициализированные строкой перечисления не могут быть преобразованы в обратный путь для получения исходного имени члена перечисления. Другими словами, вы не можете написать Colors ["RED"], чтобы получить строку "Red".
Мое решение:
export const getColourKey = (value: string ) => {
let colourKey = '';
for (const key in ColourEnum) {
if (value === ColourEnum[key]) {
colourKey = key;
break;
}
}
return colourKey;
};
Основываясь на некоторых ответах выше, я придумал эту сигнатуру безопасной для типов функции:
export function getStringValuesFromEnum<T>(myEnum: T): keyof T {
return Object.keys(myEnum).filter(k => typeof (myEnum as any)[k] === 'number') as any;
}
Использование:
enum myEnum { entry1, entry2 };
const stringVals = getStringValuesFromEnum(myEnum);
тип stringVals
является 'entry1' | 'entry2'
'entry1' | 'entry2'
Я думаю, что лучший способ - просто объявить желаемые значения перечисления. Таким образом, доступ к ним чистый и красивый (каждый раз).
enum myEnum { entry1 = 'VALUE1', entry2 = 'VALUE2' }
for (var entry in myEnum) {
console.log(entry);
}
будет производить:
VALUE1
VALUE2
Единственное решение, которое работает для меня во всех случаях (даже если значения являются строками), заключается в следующем:
var enumToString = function(enumType, enumValue) {
for (var enumMember in enumType) {
if (enumType[enumMember]==enumValue) return enumMember
}
}
Согласно документации по машинописи, мы можем сделать это через Enum со статическими функциями.
Получить Enum Name со статическими функциями
enum myEnum {
entry1,
entry2
}
namespace myEnum {
export function GetmyEnumName(m: myEnum) {
return myEnum[m];
}
}
now we can call it like below
myEnum.GetmyEnumName(myEnum.entry1);
// result entry1
чтобы узнать больше о Enum со статической функцией, перейдите по ссылке ниже https://basarat.gitbooks.io/typescript/docs/enums.html
Я написал класс EnumUtil, который выполняет проверку типа по значению enum:
export class EnumUtils {
/**
* Returns the enum keys
* @param enumObj enum object
*/
static getEnumKeys(enumObj: any, valueType: string): any[] {
return EnumUtils.getEnumValues(enumObj, valueType).map(value => enumObj[value]);
}
/**
* Returns the enum values
* @param enumObj enum object
*/
static getEnumValues(enumObj: any, valueType: string): any[] {
return Object.keys(enumObj).filter(key => typeof enumObj[key] === valueType);
}
}
Как это использовать:
enum TestEnum{
A= 0,
B= 1
}
EnumUtils.getEnumKeys(TestEnum, "number");
EnumUtils.getEnumValues(TestEnum, "number");
Результат для ключей: ["A", "B"]
Результат для значений: [0, 1]
Я нахожу это решение более элегантным:
for (let val in myEnum ) {
if ( isNaN( parseInt( val )) )
console.log( val );
}
Отображается:
bar
foo
Мой Enum такой:
export enum UserSorting {
SortByFullName = "Sort by FullName",
SortByLastname = "Sort by Lastame",
SortByEmail = "Sort by Email",
SortByRoleName = "Sort by Role",
SortByCreatedAt = "Sort by Creation date",
SortByCreatedBy = "Sort by Author",
SortByUpdatedAt = "Sort by Edit date",
SortByUpdatedBy = "Sort by Editor",
}
таким образом, это возвращение не определено:
UserSorting[UserSorting.SortByUpdatedAt]
Чтобы решить эту проблему, я выбрал другой способ сделать это с помощью Pipe:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'enumKey'
})
export class EnumKeyPipe implements PipeTransform {
transform(value, args: string[] = null): any {
let enumValue = args[0];
var keys = Object.keys(value);
var values = Object.values(value);
for (var i = 0; i < keys.length; i++) {
if (values[i] == enumValue) {
return keys[i];
}
}
return null;
}
}
И использовать это:
return this.enumKeyPipe.transform(UserSorting, [UserSorting.SortByUpdatedAt]);
Я нашел этот вопрос с помощью поиска "итерация машинописи по ключам перечисления". Поэтому я просто хочу опубликовать решение, которое работает для меня в моем случае. Может быть, это кому-то тоже поможет.
Мой случай следующий: я хочу перебрать каждый ключ перечисления, затем отфильтровать некоторые ключи, а затем получить доступ к некоторому объекту, ключи которого являются вычисленными значениями из перечисления. Так вот, как я делаю это без каких-либо ошибок TS.
enum MyEnum = { ONE = 'ONE', TWO = 'TWO' }
const LABELS = {
[MyEnum.ONE]: 'Label one',
[MyEnum.TWO]: 'Label two'
}
// to declare type is important - otherwise TS complains on LABELS[type]
// also, if replace Object.values with Object.keys -
// - TS blames wrong types here: "string[] is not assignable to MyEnum[]"
const allKeys: Array<MyEnum> = Object.values(MyEnum)
const allowedKeys = allKeys.filter(
(type) => type !== MyEnum.ONE
)
const allowedLabels = allowedKeys.map((type) => ({
label: LABELS[type]
}))
Это не совсем ответ на ваш вопрос, но это хитрость для решения вашей проблемы.
export module Gender {
export enum Type {
Female = 1,
Male = 2
};
export const List = Object.freeze([
{ Female: Type.Female },
{ Male: Type.Male }
]);
}
Вы можете расширить свою модель списка так, как вы хотите.
export const List = Object.freeze([
{ Female: { key: 'Female', value: Type.Female } },
{ Male: { key: 'Male', value: Type.Male } }
]);
Теперь вы можете использовать его следующим образом:
for(let gender of Gender.List){
console.log(gender.Female.key);
console.log(gender.Female.value);
}
или же:
if(i === Gender.Type.Male){
console.log("I'm a man.");
}