Bagaimana cara mendapatkan nama entri enum?

314

Saya ingin mengulang jenis TypeScript enumdan mendapatkan setiap nama simbol yang disebutkan, misalnya:

enum myEnum { entry1, entry2 }

for (var entry in myEnum) { 
    // use entry's name here, e.g., "entry1"
}
CalvinDale
sumber
paket enum-for mungil ini memiliki getAllEnumValuesdan getAllEnumKeysuntuk tujuan Anda
transang

Jawaban:

256

Kode yang Anda poskan akan berfungsi; itu akan mencetak semua anggota enum, termasuk nilai-nilai anggota enum. Misalnya, kode berikut:

enum myEnum { bar, foo }

for (var enumMember in myEnum) {
   console.log("enum member: ", enumMember);
}

Akan mencetak yang berikut:

Enum member: 0
Enum member: 1
Enum member: bar
Enum member: foo

Jika Anda hanya menginginkan nama anggota saja, dan bukan nilainya, Anda dapat melakukan sesuatu seperti ini:

for (var enumMember in myEnum) {
   var isValueProperty = parseInt(enumMember, 10) >= 0
   if (isValueProperty) {
      console.log("enum member: ", myEnum[enumMember]);
   }
}

Itu akan mencetak hanya nama-nama:

Anggota Enum: bar

Anggota Enum: foo

Peringatan: ini sedikit bergantung pada detail implementasi: TypeScript mengkompilasi enum ke objek JS dengan nilai enum menjadi anggota objek. Jika TS memutuskan untuk menerapkannya secara berbeda di masa depan, teknik di atas bisa pecah.

Yehuda Gabriel Himango
sumber
23
Agar jelas, jawaban di atas masih berfungsi pada TS 2.3. Namun, jika Anda menggunakan "const enum", bukan hanya "enum", maka tidak akan berfungsi. Menggunakan const enum pada dasarnya memberitahu TS untuk melakukan pencarian-dan-ganti; setiap tempat Anda menggunakan MyEnum.Foo, itu akan diganti dengan nilai numerik yang sesuai.
Yehuda Gabriel Himango
Saya pikir +enumMember >= 0seharusnya isFinite(+enumMember)karena nilai negatif atau floating point dipetakan terbalik juga. ( Taman bermain )
spenceryue
342

Meskipun jawabannya sudah disediakan, Hampir tidak ada yang menunjuk ke dokumen

Ini cuplikan

enum Enum {
    A
}
let nameOfA = Enum[Enum.A]; // "A"

Perlu diingat bahwa anggota string enum tidak mendapatkan pemetaan terbalik yang dihasilkan sama sekali.

shakram02
sumber
38
Ia juga mengatakan di sana, "Perlu diingat bahwa anggota string enum tidak mendapatkan pemetaan terbalik yang dihasilkan sama sekali."
jbojcic
1
Bagaimana dengan menampilkan 0atau 1dari enum ini? export enum Octave { ZERO = 0, ONE = 1 }
Stephane
@jbojcic Apakah situasi: enum Enum {"A"}; let nameOfA = Enum[Enum.A];? Pada [email protected] berfungsi dengan baik untuk saya ...
ellockie
Bagaimana dengan pengulangan nilai?
shioko
55

Dengan asumsi Anda mematuhi aturan dan hanya menghasilkan enum dengan nilai numerik, Anda dapat menggunakan kode ini. Ini dengan benar menangani kasus di mana Anda memiliki nama yang secara kebetulan merupakan nomor yang valid

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']
Ryan Cavanaugh
sumber
Peringatan Dalam naskah modern (tsc 2.5.2 atm) Anda bahkan tidak diizinkan memiliki string numerik sebagai kunci untuk memulai. Karena itu jawaban Himango lebih baik, karena mencakup semua kasus dan tidak memiliki kerugian.
srcspider
53

Bagi saya cara yang lebih mudah, praktis dan langsung untuk memahami apa yang sedang terjadi, adalah dengan cara penghitungan berikut:

enum colors { red, green, blue };

Pada dasarnya akan dikonversi menjadi ini:

var colors = { red: 0, green: 1, blue: 2,
               [0]: "red", [1]: "green", [2]: "blue" }

Karena itu, yang berikut ini akan benar:

colors.red === 0
colors[colors.red] === "red"
colors["red"] === 0

Ini menciptakan cara mudah untuk mendapatkan nama yang disebutkan sebagai berikut:

var color: colors = colors.red;
console.log("The color selected is " + colors[color]);

Itu juga menciptakan cara yang bagus untuk mengonversi string ke nilai yang disebutkan.

var colorName: string = "green";
var color: colors = colors.red;
if (colorName in colors) color = colors[colorName];

Dua situasi di atas adalah situasi yang jauh lebih umum, karena biasanya Anda jauh lebih tertarik pada nama nilai tertentu dan membuat cerita bersambung dengan cara yang umum.

Michael Erickson
sumber
49

Jika Anda hanya mencari nama dan beralih lagi gunakan:

Object.keys(myEnum).map(key => myEnum[key]).filter(value => typeof value === 'string') as string[];
Simon
sumber
13
Atau dengan lib ES2017:Object.values(myEnum).filter(value => typeof value === 'string') as string[];
Tidak ada
Saya perlu membuat dict, dan saya menggunakan jawaban Anda sebagai titik awal. Jika orang lain membutuhkannya,Object.values(myEnum).filter(value => typeof value === 'string').map(key => { return {id: myEnum[key], type: key }; });
Fej
atau hanya Object.values ​​(myEnum) .filter (isNaN) sebagai string [];
ihorbond
25

Dengan TypeScript Versi 1.8.9 yang sekarang saya gunakan mengetikkan Enums:

export enum Option {
    OPTION1 = <any>'this is option 1',
    OPTION2 = <any>'this is option 2'
}

dengan hasil dalam objek Javascript ini:

Option = {
    "OPTION1": "this is option 1",
    "OPTION2": "this is option 2",
    "this is option 1": "OPTION1",
    "this is option 2": "OPTION2"
}

jadi saya harus mencari melalui kunci dan nilai dan hanya mengembalikan nilai:

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]]);
        }
    }
}

Dan saya menerima tombol opsi dalam Array:

optionNames = [ "OPTION1", "OPTION2" ];
Philip
sumber
17

Solusi ini juga berfungsi.

enum ScreenType {
    Edit = 1,
    New = 2,
    View = 4
}

var type: ScreenType = ScreenType.Edit;

console.log(ScreenType[type]); //Edit
Carlinhos
sumber
14

Solusi menarik lain yang ditemukan di sini adalah menggunakan 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']
]);

MENGGUNAKAN

console.log(TypeLabel.get(Type.low)); // Low Season
manzapanza
sumber
10

Biarkan ts-enum-util( github , npm ) melakukan pekerjaan untuk Anda dan menyediakan banyak utilitas tipe-aman tambahan. Bekerja dengan string dan enum numerik, dengan benar mengabaikan entri numerik indeks pencarian terbalik untuk enum numerik:

String enum:

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();

Angka numerik:

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();
Jeff Lau
sumber
9

Mulai dari TypeScript 2.4, enum tidak akan berisi kunci sebagai anggota lagi. sumber dari readScript TypeScript

Peringatannya adalah bahwa enum yang diinisialisasi string tidak dapat dipetakan terbalik untuk mendapatkan nama anggota enum yang asli. Dengan kata lain, Anda tidak dapat menulis Warna ["RED"] untuk mendapatkan string "Merah".

Solusi saya:

export const getColourKey = (value: string ) => {
    let colourKey = '';
    for (const key in ColourEnum) {
        if (value === ColourEnum[key]) {
            colourKey = key;
            break;
        }
    }
    return colourKey;
};
kitko112
sumber
8

Anda dapat menggunakan enum-valuespaket yang saya tulis ketika saya memiliki masalah yang sama:

Git: enum-values

var names = EnumValues.getNames(myEnum);
Slava Shpitalny
sumber
3
Anda tidak benar-benar menjawab pertanyaan, akan lebih baik untuk mendokumentasikan jawaban Anda dengan kode / etc tetapi saya menemukan paket itu berguna.
lucuma
7

Berdasarkan beberapa jawaban di atas, saya menemukan tanda tangan fungsi aman-jenis ini:

export function getStringValuesFromEnum<T>(myEnum: T): keyof T {
  return Object.keys(myEnum).filter(k => typeof (myEnum as any)[k] === 'number') as any;
}

Pemakaian:

enum myEnum { entry1, entry2 };
const stringVals = getStringValuesFromEnum(myEnum);

jenis stringValsyaitu'entry1' | 'entry2'

Lihat itu dalam aksi

Dmitry Efimenko
sumber
1
Fungsi seharusnya kembali (keyof T)[]sebagai ganti keyof T. Juga, exportberhenti bermain Anda dari bekerja.
Joald
7

Tampaknya tidak ada jawaban di sini yang akan bekerja dengan string-enums di strict-mode.

Pertimbangkan enum sebagai:

enum AnimalEnum {
  dog = "dog", cat = "cat", mouse = "mouse"
}

Mengakses ini dengan AnimalEnum["dog"]dapat mengakibatkan kesalahan seperti:

Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'typeof AnimalEnum'.ts(7053).

Solusi yang tepat untuk kasus itu, tulis sebagai:

AnimalEnum["dog" as keyof typeof AnimalEnum]
lebih tenang
sumber
Solusi brilian untuk menggunakan keyofdengan typeof! Solusi lain tampaknya cukup buram, tetapi bagaimanapun juga saya pikir Typescript perlu terus meningkatkan DX - Pengalaman Pengembang untuk Enum
Shaung Cheng
5

Cara terbaik yang saya pikirkan adalah dengan mendeklarasikan nilai enum yang diinginkan. Dengan cara mengaksesnya bersih dan cantik (setiap saat).

enum myEnum { entry1 = 'VALUE1', entry2 = 'VALUE2' }

for (var entry in myEnum) { 
    console.log(entry);
}

akan menghasilkan:

VALUE1
VALUE2
stemadsen
sumber
5

Menurut dokumentasi TypeScript, kita dapat melakukan ini melalui Enum dengan fungsi statis.

Dapatkan Nama Enum dengan fungsi statis

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 

untuk membaca lebih lanjut tentang Enum dengan fungsi statis ikuti tautan di bawah ini https://basarat.gitbooks.io/typescript/docs/enums.html

Shahid Ahmad
sumber
4

Satu-satunya solusi yang bekerja untuk saya dalam semua kasus (meskipun nilai adalah string) adalah sebagai berikut:

var enumToString = function(enumType, enumValue) {
    for (var enumMember in enumType) {
        if (enumType[enumMember]==enumValue) return enumMember
    }
}
pengguna2080105
sumber
4

Pertanyaan lama, tetapi, mengapa tidak menggunakan constpeta objek?

Alih-alih melakukan ini:

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]

Lakukan ini (perhatikan para as constpemain):

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]
Gabriel De Oliveira Rohden
sumber
Koreksi saya jika saya salah tetapi console.log(Object.keys(Foo))dalam contoh pertama hanya mengembalikan ["BAR", "EVERYTHING_IS_TERRIBLE"]..
Peter
@Peter lihat di sini di taman bermain ts , cukup buka konsol dan klik di jalankan. Setidaknya bagi saya, itu mencetak["60", "80", "BAR", "EVERYTHING_IS_TERRIBLE"]
Gabriel De Oliveira Rohden
1
tampaknya hak Anda, hal yang menyenangkan jika Anda mengubah dari angka ke string Anda mendapatkan output yang saya harapkan, saya tidak tahu mengapa naskah skrip menangani string dan angka berbeda dalam enum ..
Peter
4

Saya menemukan pertanyaan ini dengan mencari "TypeScript iterate over enum keys". Jadi saya hanya ingin memposting solusi yang cocok untuk saya dalam kasus saya. Mungkin itu akan membantu seseorang juga.

Kasus saya adalah sebagai berikut: Saya ingin mengulangi setiap kunci enum, lalu menyaring beberapa kunci, lalu mengakses beberapa objek yang memiliki kunci sebagai nilai yang dihitung dari enum. Jadi ini adalah bagaimana saya melakukannya tanpa ada kesalahan 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]
    }))
Alendorff
sumber
3

Saya menulis kelas EnumUtil yang membuat pemeriksaan tipe dengan nilai 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'
}

Bagaimana cara menggunakannya:

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);

Hasil untuk kunci NumberValueEnum: ["A", "B"]

Hasil untuk nilai-nilai NumberValueEnum: [0, 1]

Hasil untuk StringValueEnumkeys: ["A", "B"]

Hasil untuk StringValueEnumvalues: ["A", "B"]

Arnold Vakaria
sumber
2

Saya menemukan solusi itu lebih elegan:

for (let val in myEnum ) {

 if ( isNaN( parseInt( val )) )
     console.log( val );
}

Ini menampilkan:

bar 
foo
Anthony Brenelière
sumber
2

Enum saya seperti ini:

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", 
}

jadi pengembalian ini tidak ditentukan :

UserSorting[UserSorting.SortByUpdatedAt]

Untuk mengatasi masalah ini, saya memilih cara lain untuk melakukannya menggunakan Pipa:

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;
    }
}

Dan untuk menggunakannya:

return this.enumKeyPipe.transform(UserSorting, [UserSorting.SortByUpdatedAt]);
Cedric Arnould
sumber
2

Jika Anda memiliki enum

enum Diet {
  KETO = "Ketogenic",
  ATKINS = "Atkins",
  PALEO = "Paleo",
  DGAF = "Whatever"
}

Maka Anda bisa mendapatkan kunci dan nilai-nilai seperti:

Object.keys(Diet).forEach((d: Diet) => {
  console.log(d); // KETO
  console.log(Diet[d]) // Ketogenic
});
clu
sumber
Ini menyebabkan kesalahan: 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)
jrheling
1

Saya menulis fungsi pembantu untuk menyebutkan enum:

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;
}

Pemakaian:

for (const enumValue of getEnumValues<myEnum>(myEnum)) {
  // do the thing
}

Fungsi mengembalikan sesuatu yang dapat dengan mudah disebutkan, dan juga dilemparkan ke tipe enum.

Russell Phillips
sumber
0

Menggunakan versi saat ini TypeScript Anda dapat menggunakan fungsi seperti ini untuk memetakan Enum ke catatan pilihan Anda. Perhatikan bahwa Anda tidak dapat menentukan nilai string dengan fungsi-fungsi ini karena mereka mencari kunci dengan nilai yang merupakan angka.

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
  }
}
geschwe1
sumber
0

Sudah ada banyak jawaban di sini, tetapi saya kira saya akan membuang solusi saya ke tumpukan.

TypeScript Playground

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>)

Untuk kejelasan:

/*
 * reversed == {
 *   "goo": "Google",
 *   "boo": "Facebook",
 *   "wit": "Twitter",
 * }
 * reversed[AccountType.Google] === "Google" 👍
 */

Referensi untuk Record TypeScript

Fungsi pembantu yang bagus:

const getAccountTypeName = (type: AccountType) => {
  return reversed[type]
};

// getAccountTypeName(AccountType.Twitter) === 'Twitter'
Kesempatan
sumber
0

Untuk mendapatkan daftar nilai enum yang harus Anda gunakan:

enum AnimalEnum {
  DOG = "dog", 
  CAT = "cat", 
  MOUSE = "mouse"
}

Object.values(AnimalEnum);
Radu Linu
sumber
-1

Ini bukan jawaban tepat atas pertanyaan Anda, tetapi itu adalah trik untuk mengatasi masalah Anda.

export module Gender {

  export enum Type {
    Female = 1,
    Male = 2
  };

  export const List = Object.freeze([
    Type[Type.Female] ,
    Type[Type.Male]
  ]);

}

Anda dapat memperluas model daftar dengan cara yang Anda inginkan.

export const List = Object.freeze([
    { name: Type[Type.Female], value: Type.Female } ,
    { name: Type[Type.Male], value: Type.Male }
  ]);

Sekarang, Anda dapat menggunakannya dengan cara ini:

for(const gender of Gender.List){
  console.log(gender.name);
  console.log(gender.value);
}

atau:

if(i === Gender.Type.Male){
  console.log("I am a man.");
}
Pedram Ahmadpour
sumber