Chciałbym powtórzyć TypeScript enum
typ i uzyskać nazwę każdego wyliczonego symbolu, np .:
enum myEnum { entry1, entry2 }
for (var entry in myEnum) {
// use entry's name here, e.g., "entry1"
}
Chciałbym powtórzyć TypeScript enum
typ i uzyskać nazwę każdego wyliczonego symbolu, np .:
enum myEnum { entry1, entry2 }
for (var entry in myEnum) {
// use entry's name here, e.g., "entry1"
}
Odpowiedzi:
Kod, który opublikowałeś, będzie działał; wydrukuje wszystkich członków wyliczenia, w tym wartości członków wyliczenia. Na przykład następujący kod:
enum myEnum { bar, foo }
for (var enumMember in myEnum) {
console.log("enum member: ", enumMember);
}
Wydrukuje następujące:
Enum member: 0
Enum member: 1
Enum member: bar
Enum member: foo
Jeśli zamiast tego chcesz tylko nazwy członków, a nie wartości, możesz zrobić coś takiego:
for (var enumMember in myEnum) {
var isValueProperty = parseInt(enumMember, 10) >= 0
if (isValueProperty) {
console.log("enum member: ", myEnum[enumMember]);
}
}
Spowoduje to wydrukowanie tylko nazw:
Członek Enum: bar
Członek Enum: foo
Zastrzeżenie: to w niewielkim stopniu opiera się na szczegółach implementacji: TypeScript kompiluje wyliczenia do obiektu JS z wartościami wyliczania będącymi elementami tego obiektu. Jeśli TS zdecyduje się zastosować je w przyszłości inaczej, powyższa technika może się złamać.
+enumMember >= 0
powinno być, isFinite(+enumMember)
ponieważ wartości ujemne lub zmiennoprzecinkowe również są odwzorowywane odwrotnie. ( Plac zabaw )
Chociaż odpowiedź jest już udzielona, prawie nikt nie wskazał na dokumenty
Oto fragment
enum Enum {
A
}
let nameOfA = Enum[Enum.A]; // "A"
Należy pamiętać, że członkowie wyliczania ciągów w ogóle nie generują odwrotnego odwzorowania.
0
lub 1
z tego wyliczenia? export enum Octave { ZERO = 0, ONE = 1 }
enum Enum {"A"}; let nameOfA = Enum[Enum.A];
? Od maszynopis@2.9.2 działa dla mnie dobrze ...
Zakładając, że trzymasz się zasad i tworzysz wyliczenia tylko z wartościami liczbowymi, możesz użyć tego kodu. To poprawnie obsługuje przypadek, w którym masz przypadkowo prawidłową liczbę
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']
Dla mnie łatwiejszym, praktycznym i bezpośrednim sposobem zrozumienia tego, co się dzieje, jest następujące wyliczenie:
enum colors { red, green, blue };
Zostaną zasadniczo przekonwertowane na to:
var colors = { red: 0, green: 1, blue: 2,
[0]: "red", [1]: "green", [2]: "blue" }
Z tego powodu będą spełnione następujące warunki:
colors.red === 0
colors[colors.red] === "red"
colors["red"] === 0
W ten sposób można łatwo uzyskać nazwę wyliczenia w następujący sposób:
var color: colors = colors.red;
console.log("The color selected is " + colors[color]);
Daje to również dobry sposób na konwersję łańcucha na wartość wyliczoną.
var colorName: string = "green";
var color: colors = colors.red;
if (colorName in colors) color = colors[colorName];
Dwie powyższe sytuacje są znacznie częstszą sytuacją, ponieważ zwykle bardziej interesuje Cię nazwa konkretnej wartości i szeregowanie wartości w ogólny sposób.
Jeśli szukasz tylko nazw i iterujesz później, użyj:
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 }; });
W obecnej wersji 1.8.9 TypeScript używam wpisywanych wyliczeń:
export enum Option {
OPTION1 = <any>'this is option 1',
OPTION2 = <any>'this is option 2'
}
z wynikami w tym obiekcie Javascript:
Option = {
"OPTION1": "this is option 1",
"OPTION2": "this is option 2",
"this is option 1": "OPTION1",
"this is option 2": "OPTION2"
}
więc muszę wyszukiwać klucze i wartości i zwracać tylko wartości:
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]]);
}
}
}
I otrzymuję klucze opcji w tablicy:
optionNames = [ "OPTION1", "OPTION2" ];
Począwszy od TypeScript 2.4, wyliczenia mogą zawierać inicjatory ciągów https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html
To pozwala napisać:
enum Order {
ONE = "First",
TWO = "Second"
}
console.log(`One is ${Order.ONE.toString()}`);
i uzyskaj ten wynik:
Jeden jest pierwszy
Innym ciekawym rozwiązaniem znalezionym tutaj jest użycie 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']
]);
POSŁUGIWAĆ SIĘ
console.log(TypeLabel.get(Type.low)); // Low Season
Niech ts-enum-util
( github , npm ) wykona pracę za Ciebie i zapewni wiele dodatkowych narzędzi bezpiecznych dla danego typu. Działa zarówno z ciągami znaków, jak i numerycznymi, poprawnie ignorując wpisy wyszukiwania wstecznego indeksu liczbowego dla liczbowych:
Wyliczenie ciągu:
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();
Wyliczenie numeryczne:
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();
Począwszy od TypeScript 2.4, wyliczenie nie zawierałoby już klucza jako członka. źródło z Readme TypeScript
Zastrzeżenie polega na tym, że nie można odwzorować odwrotnie zainicjowanych ciągów znaków w celu uzyskania oryginalnej nazwy członka wyliczenia. Innymi słowy, nie można napisać Kolory [„CZERWONY”], aby uzyskać ciąg „Czerwony”.
Moje rozwiązanie:
export const getColourKey = (value: string ) => {
let colourKey = '';
for (const key in ColourEnum) {
if (value === ColourEnum[key]) {
colourKey = key;
break;
}
}
return colourKey;
};
Możesz użyć enum-values
pakietu, który napisałem, gdy miałem ten sam problem:
var names = EnumValues.getNames(myEnum);
Na podstawie niektórych powyższych odpowiedzi wymyśliłem podpis funkcji bezpiecznej dla typu:
export function getStringValuesFromEnum<T>(myEnum: T): keyof T {
return Object.keys(myEnum).filter(k => typeof (myEnum as any)[k] === 'number') as any;
}
Stosowanie:
enum myEnum { entry1, entry2 };
const stringVals = getStringValuesFromEnum(myEnum);
rodzaj stringVals
jest'entry1' | 'entry2'
(keyof T)[]
zamiast keyof T
. Ponadto export
zatrzymuje działanie Twojego placu zabaw.
Wygląda na to, że żadna z odpowiedzi tutaj nie będzie działać z strict
wyliczeniami ciągów w trybie -mode.
Rozważ enum jako:
enum AnimalEnum {
dog = "dog", cat = "cat", mouse = "mouse"
}
Dostęp do tego za pomocą AnimalEnum["dog"]
może spowodować błąd:
Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'typeof AnimalEnum'.ts(7053)
.
Odpowiednie rozwiązanie dla tego przypadku, napisz je jako:
AnimalEnum["dog" as keyof typeof AnimalEnum]
keyof
z typeof
! Inne rozwiązanie wydaje się dość nieprzejrzyste, ale mimo wszystko myślę, że maszynopis musi ciągle poprawiać DX - Doświadczenie programistyczne dla Enum
Myślę, że najlepszym sposobem jest po prostu zadeklarowanie pożądanych wartości wyliczeniowych. W ten sposób dostęp do nich jest czysty i ładny (za każdym razem).
enum myEnum { entry1 = 'VALUE1', entry2 = 'VALUE2' }
for (var entry in myEnum) {
console.log(entry);
}
będzie produkować:
VALUE1
VALUE2
Zgodnie z dokumentacją TypeScript możemy to zrobić za pomocą Enum z funkcjami statycznymi.
Uzyskaj nazwę enum z funkcjami statycznymi
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
Aby przeczytać więcej o Enum z funkcją statyczną, skorzystaj z poniższego linku https://basarat.gitbooks.io/typescript/docs/enums.html
Jedyne rozwiązanie, które działa dla mnie we wszystkich przypadkach (nawet jeśli wartości są łańcuchami), jest następujące:
var enumToString = function(enumType, enumValue) {
for (var enumMember in enumType) {
if (enumType[enumMember]==enumValue) return enumMember
}
}
Stare pytanie, ale dlaczego nie korzystać z const
mapy obiektów?
Zamiast tego:
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]
Zrób to (zwróć uwagę na as const
obsadę):
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))
w pierwszym przykładzie powraca tylko ["BAR", "EVERYTHING_IS_TERRIBLE"]
...
["60", "80", "BAR", "EVERYTHING_IS_TERRIBLE"]
Znalazłem to pytanie, wyszukując „Iteracja TypeScript po kluczach wyliczeniowych”. Chcę tylko opublikować rozwiązanie, które działa w moim przypadku. Może to też komuś pomoże.
Mój przypadek jest następujący: chcę iterować po każdym kluczu wyliczającym, następnie filtrować niektóre klucze, a następnie uzyskać dostęp do obiektu, który ma klucze jako wyliczone wartości z wyliczenia. Tak właśnie to robię bez żadnego błędu 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]
}))
Napisałem klasę EnumUtil, która sprawdza typ według wartości wyliczeniowej:
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'
}
Jak tego użyć:
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);
Wynik dla kluczy NumberValueEnum: [„A”, „B”]
Wynik dla wartości NumberValueEnum: [0, 1]
Wynik dla StringValueEnumkeys: [„A”, „B”]
Wynik dla StringValueEnumvalues: [„A”, „B”]
Uważam to rozwiązanie za bardziej eleganckie:
for (let val in myEnum ) {
if ( isNaN( parseInt( val )) )
console.log( val );
}
To pokazuje:
bar
foo
Moje Enum jest takie:
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",
}
więc wykonanie tego zwrotu jest niezdefiniowane :
UserSorting[UserSorting.SortByUpdatedAt]
Aby rozwiązać ten problem, wybieram inny sposób, aby to zrobić za pomocą potoku:
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;
}
}
I aby go użyć:
return this.enumKeyPipe.transform(UserSorting, [UserSorting.SortByUpdatedAt]);
Jeśli masz wyliczenie
enum Diet {
KETO = "Ketogenic",
ATKINS = "Atkins",
PALEO = "Paleo",
DGAF = "Whatever"
}
Następnie możesz uzyskać klucz i wartości, takie jak:
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)
Napisałem funkcję pomocnika do wyliczenia wyliczenia:
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;
}
Stosowanie:
for (const enumValue of getEnumValues<myEnum>(myEnum)) {
// do the thing
}
Funkcja zwraca coś, co można łatwo wyliczyć, a także rzutuje na typ wyliczeniowy.
Korzystając z bieżącej wersji TypeScript, możesz użyć funkcji takich jak te, aby zamapować Enum na wybrany rekord. Zauważ, że nie możesz zdefiniować wartości ciągu za pomocą tych funkcji, ponieważ szukają kluczy o wartości, która jest liczbą.
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
}
}
Jest już wiele odpowiedzi, ale myślę, że i tak wrzucę swoje rozwiązanie na stos.
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>)
Dla jasności:
/*
* reversed == {
* "goo": "Google",
* "boo": "Facebook",
* "wit": "Twitter",
* }
* reversed[AccountType.Google] === "Google" 👍
*/
Referencje dla rekordu TypeScript
Fajna funkcja pomocnika:
const getAccountTypeName = (type: AccountType) => {
return reversed[type]
};
// getAccountTypeName(AccountType.Twitter) === 'Twitter'
To nie jest dokładnie odpowiedź na twoje pytanie, ale jest to sztuczka, aby rozwiązać swój problem.
export module Gender {
export enum Type {
Female = 1,
Male = 2
};
export const List = Object.freeze([
Type[Type.Female] ,
Type[Type.Male]
]);
}
Możesz rozszerzyć swój model listy w dowolny sposób.
export const List = Object.freeze([
{ name: Type[Type.Female], value: Type.Female } ,
{ name: Type[Type.Male], value: Type.Male }
]);
Teraz możesz go używać w następujący sposób:
for(const gender of Gender.List){
console.log(gender.name);
console.log(gender.value);
}
lub:
if(i === Gender.Type.Male){
console.log("I am a man.");
}
getAllEnumValues
igetAllEnumKeys
dla twojego celu