Я хотів би ввести TypeScript і enum
тип і отримати кожне перелічене ім'я символу, наприклад:
enum myEnum { entry1, entry2 }
for (var entry in myEnum) {
// use entry's name here, e.g., "entry1"
}
Я хотів би ввести TypeScript і enum
тип і отримати кожне перелічене ім'я символу, наприклад:
enum myEnum { entry1, entry2 }
for (var entry in myEnum) {
// use entry's name here, e.g., "entry1"
}
Відповіді:
Код, який ви опублікували, буде працювати; він виведе всіх членів enum, включаючи значення членів enum. Наприклад, наступний код:
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: бар
Член Enum: foo
Caveat: це трохи покладається на деталі реалізації: TypeScript компілює перерахунки до JS-об'єкта, при цьому значення enum є членами об'єкта. Якщо TS вирішив впроваджувати їх в майбутньому різними, вищезгадана методика може зламатись.
+enumMember >= 0
повинно бути, isFinite(+enumMember)
тому що негативні значення чи значення з плаваючою точкою також відображаються на зворотному рівні. ( Ігровий майданчик )
Хоча відповідь уже надана, майже ніхто не вказав на документи
Ось фрагмент
enum Enum {
A
}
let nameOfA = Enum[Enum.A]; // "A"
Майте на увазі, що члени перерахунків рядків взагалі не отримують зворотного відображення.
0
чи 1
з цього перерахунку? export enum Octave { ZERO = 0, ONE = 1 }
enum Enum {"A"}; let nameOfA = Enum[Enum.A];
:? Що стосується
Якщо припустити, що ви дотримуєтесь правил і створюєте лише перерахунки з числовими значеннями, ви можете використовувати цей код. Це правильно обробляє випадок, коли у вас є ім'я, яке збігається випадково
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[];
Object.values(myEnum).filter(value => typeof value === 'string') as string[];
Object.values(myEnum).filter(value => typeof value === 'string').map(key => { return {id: myEnum[key], type: key }; });
З поточною версією TypeScript 1.8.9 я використовую набрані Enums:
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()}`);
і отримати цей вихід:
Один - Перший
Ще одне цікаве рішення, знайдене тут, - використання ES6 Map:
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']
]);
ВИКОРИСТАННЯ
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();
Починаючи з TypeScript 2.4, enum більше не міститиме ключ як член. джерело з TypeScript readme
Застереження полягає в тому, що ініціалізовані рядки перерахунки не можуть бути зворотно відображені для отримання оригінального імені члена enum. Іншими словами, ви не можете написати Colors ["RED"], щоб отримати рядок "Red".
Моє рішення:
export const getColourKey = (value: string ) => {
let colourKey = '';
for (const key in ColourEnum) {
if (value === ColourEnum[key]) {
colourKey = key;
break;
}
}
return colourKey;
};
Ви можете використовувати enum-values
пакет, який я написав, коли у мене була така ж проблема:
var names = EnumValues.getNames(myEnum);
На підставі деяких відповідей вище, я придумав цю функцію безпечної для підпису функції:
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'
(keyof T)[]
замість keyof T
. Також export
зупиняє роботу вашого дитячого майданчика.
Здається, жодна відповідь тут не працюватиме з string-enums в -mode 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]
keyof
з typeof
! Інше рішення здається досить непрозорим, але зрештою, я думаю, що Typescript повинен продовжувати вдосконалюватись на DX - Досвід розробників для Enum
Згідно з документацією TypeScript, ми можемо це зробити за допомогою Enum зі статичними функціями.
Отримати ім'я Enum зі статичними функціями
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
Єдине рішення, яке працює для мене у всіх випадках (навіть якщо значення є рядками), це наступне:
var enumToString = function(enumType, enumValue) {
for (var enumMember in enumType) {
if (enumType[enumMember]==enumValue) return enumMember
}
}
Старе питання, але, чому не використовувати a const
об’єктну карту?
Замість цього:
enum Foo {
BAR = 60,
EVERYTHING_IS_TERRIBLE = 80
}
console.log(Object.keys(Foo))
// -> ["60", "80", "BAR", "EVERYTHING_IS_TERRIBLE"]
console.log(Object.values(Foo))
// -> ["BAR", "EVERYTHING_IS_TERRIBLE", 60, 80]
Зробіть це (зверніть увагу на as const
акторський склад ):
const Foo = {
BAR: 60,
EVERYTHING_IS_TERRIBLE: 80
} as const
console.log(Object.keys(Foo))
// -> ["BAR", "EVERYTHING_IS_TERRIBLE"]
console.log(Object.values(Foo))
// -> [60, 80]
console.log(Object.keys(Foo))
в першому прикладі тільки повертається ["BAR", "EVERYTHING_IS_TERRIBLE"]
..
["60", "80", "BAR", "EVERYTHING_IS_TERRIBLE"]
Я знайшов це питання за допомогою пошуку "TypeScript ітерації за перерахуванням ключів". Тому я просто хочу розмістити рішення, яке працює для мене в моєму випадку. Можливо, це теж допоможе комусь.
Моя справа така: я хочу повторити кожну клавішу перерахунку, потім відфільтрувати деякі клавіші, а потім отримати доступ до деякого об'єкта, у якого є ключі як обчислені значення з enum. Так це я роблю, не маючи жодної помилки 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]
}))
Я написав клас EnumUtil, який здійснює перевірку типу за значенням enum:
export class EnumUtils {
/**
* Returns the enum keys
* @param enumObj enum object
* @param enumType the enum type
*/
static getEnumKeys(enumObj: any, enumType: EnumType): any[] {
return EnumUtils.getEnumValues(enumObj, enumType).map(value => enumObj[value]);
}
/**
* Returns the enum values
* @param enumObj enum object
* @param enumType the enum type
*/
static getEnumValues(enumObj: any, enumType: EnumType): any[] {
return Object.keys(enumObj).filter(key => typeof enumObj[key] === enumType);
}
}
export enum EnumType {
Number = 'number',
String = 'string'
}
Як ним користуватися:
enum NumberValueEnum{
A= 0,
B= 1
}
enum StringValueEnum{
A= 'A',
B= 'B'
}
EnumUtils.getEnumKeys(NumberValueEnum, EnumType.number);
EnumUtils.getEnumValues(NumberValueEnum, EnumType.number);
EnumUtils.getEnumKeys(StringValueEnum, EnumType.string);
EnumUtils.getEnumValues(StringValueEnum, EnumType.string);
Результат для клавіш NumberValueEnum: ["A", "B"]
Результат для значень NumberValueEnum: [0, 1]
Результат для StringValueEnumkeys: ["A", "B"]
Результат для StringValueEnumvalues: ["A", "B"]
Я вважаю це рішення більш елегантним:
for (let val in myEnum ) {
if ( isNaN( parseInt( val )) )
console.log( val );
}
На ньому відображаються:
bar
foo
Мій Енум такий:
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]
Щоб вирішити цю проблему, я вибираю інший спосіб зробити це за допомогою Труби:
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]);
Якщо у вас є перерахунки
enum Diet {
KETO = "Ketogenic",
ATKINS = "Atkins",
PALEO = "Paleo",
DGAF = "Whatever"
}
Тоді ви можете отримати ключ і значення, такі як:
Object.keys(Diet).forEach((d: Diet) => {
console.log(d); // KETO
console.log(Diet[d]) // Ketogenic
});
Argument of type '(d: Diet) => void' is not assignable to parameter of type '(value: string, index: number, array: string[]) => void'. Types of parameters 'd' and 'value' are incompatible. Type 'string' is not assignable to type 'MyEnum'.(2345)
Я написав функцію помічника для перерахування переліку:
static getEnumValues<T extends number>(enumType: {}): T[] {
const values: T[] = [];
const keys = Object.keys(enumType);
for (const key of keys.slice(0, keys.length / 2)) {
values.push(<T>+key);
}
return values;
}
Використання:
for (const enumValue of getEnumValues<myEnum>(myEnum)) {
// do the thing
}
Функція повертає те, що можна легко перерахувати, а також передає типу enum.
Використовуючи поточну версію TypeScript, ви можете використовувати такі функції, як мапа Enum для запису на ваш вибір. Зауважте, що ви не можете визначити значення рядків за допомогою цих функцій, коли вони шукають ключі зі значенням, яке є числом.
enum STATES {
LOGIN,
LOGOUT,
}
export const enumToRecordWithKeys = <E extends any>(enumeration: E): E => (
Object.keys(enumeration)
.filter(key => typeof enumeration[key] === 'number')
.reduce((record, key) => ({...record, [key]: key }), {}) as E
);
export const enumToRecordWithValues = <E extends any>(enumeration: E): E => (
Object.keys(enumeration)
.filter(key => typeof enumeration[key] === 'number')
.reduce((record, key) => ({...record, [key]: enumeration[key] }), {}) as E
);
const states = enumToRecordWithKeys(STATES)
const statesWithIndex = enumToRecordWithValues(STATES)
console.log(JSON.stringify({
STATES,
states,
statesWithIndex,
}, null ,2));
// Console output:
{
"STATES": {
"0": "LOGIN",
"1": "LOGOUT",
"LOGIN": 0,
"LOGOUT": 1
},
"states": {
"LOGIN": "LOGIN",
"LOGOUT": "LOGOUT"
},
"statesWithIndex": {
"LOGIN": 0,
"LOGOUT": 1
}
}
Тут вже багато відповідей, але я думаю, що я все-таки кину своє рішення на стек.
enum AccountType {
Google = 'goo',
Facebook = 'boo',
Twitter = 'wit',
}
type Key = keyof typeof AccountType // "Google" | "Facebook" | "Twitter"
// this creates a POJO of the enum "reversed" using TypeScript's Record utility
const reversed = (Object.keys(AccountType) as Key[]).reduce((acc, key) => {
acc[AccountType[key]] = key
return acc
}, {} as Record<AccountType, string>)
Для ясності:
/*
* reversed == {
* "goo": "Google",
* "boo": "Facebook",
* "wit": "Twitter",
* }
* reversed[AccountType.Google] === "Google" 👍
*/
Довідка для запису TypeScript
Приємна помічна функція:
const getAccountTypeName = (type: AccountType) => {
return reversed[type]
};
// getAccountTypeName(AccountType.Twitter) === 'Twitter'
Це не зовсім відповідь на ваше запитання, але це хитрість вирішити вашу проблему.
export module Gender {
export enum Type {
Female = 1,
Male = 2
};
export const List = Object.freeze([
Type[Type.Female] ,
Type[Type.Male]
]);
}
Ви можете розширити модель списку потрібним чином.
export const List = Object.freeze([
{ name: Type[Type.Female], value: Type.Female } ,
{ name: Type[Type.Male], value: Type.Male }
]);
Тепер ви можете використовувати його таким чином:
for(const gender of Gender.List){
console.log(gender.name);
console.log(gender.value);
}
або:
if(i === Gender.Type.Male){
console.log("I am a man.");
}
getAllEnumValues
іgetAllEnumKeys
для вашої мети