Numaralandırma girişlerinin adları nasıl alınır?


314

Bir TypeScript bir enumtür yineleme ve her numaralandırılmış sembol adı, örneğin almak istiyorum:

enum myEnum { entry1, entry2 }

for (var entry in myEnum) { 
    // use entry's name here, e.g., "entry1"
}

bu küçük numaralandırma paketi vardır getAllEnumValuesve getAllEnumKeyssizin için
transang

Yanıtlar:


255

Gönderdiğiniz kod çalışır; numaralandırma üyelerinin değerleri de dahil olmak üzere numaralandırmanın tüm üyelerini yazdırır. Örneğin, aşağıdaki kod:

enum myEnum { bar, foo }

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

Aşağıdakileri yazdıracaktır:

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

Bunun yerine değerleri değil yalnızca üye adlarını istiyorsanız, şöyle bir şey yapabilirsiniz:

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

Bu sadece isimleri basacaktır:

Numaralandırma üyesi: bar

Numaralandırma üyesi: foo

Uyarı: bu biraz bir uygulama ayrıntısına dayanır: TypeScript enum değerlerini nesnenin üyeleri olacak şekilde enum değerlerini bir JS nesnesine derler. TS bunları gelecekte farklı uygulamaya karar verirse, yukarıdaki teknik kırılabilir.


23
Açıkçası, yukarıdaki cevap TS 2.3'ten itibaren hala işe yarıyor. Ancak, sadece "enum" yerine "const enum" kullanırsanız, ancak o zaman çalışmaz. Const enum kullanmak temel olarak TS'ye arama ve değiştirme yapmasını söyler; MyEnum.Foo kullandığınız her yer, karşılık gelen bir sayısal değerle değiştirilecektir.
Yahuda Gabriel Himango

Bence +enumMember >= 0olmalı isFinite(+enumMember)negatif ya da kayan nokta değerleri ters çok eşleştirilmemektedir çünkü. ( Oyun alanı )
spenceryue

342

Cevap zaten sağlanmış olmasına rağmen, neredeyse hiç kimse dokümanlara işaret etmedi

İşte bir pasaj

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

Dize numaralandırma üyelerinin hiç bir ters eşleme oluşturulmadığını unutmayın.


38
Ayrıca, "string enum üyelerinin hiç bir ters eşleme elde etmediğini unutmayın."
jbojcic

1
Bu numaralandırmayı görüntülemeye 0veya göstermeye ne dersiniz 1? export enum Octave { ZERO = 0, ONE = 1 }
Stephane

@jbojcic durum hakkında o mi: enum Enum {"A"}; let nameOfA = Enum[Enum.A];?
Typescript@2.9.2 itibariyle

Değerler arasında geçiş yapmaya ne dersiniz?
shioko

55

Kurallara bağlı kaldığınızı ve yalnızca sayısal değerleri olan numaralandırmalar oluşturduğunuzu varsayarsak, bu kodu kullanabilirsiniz. Bu, tesadüfen geçerli bir sayı olan bir adınızın olduğu durumu doğru şekilde işler

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']

Uyarı Modern daktiloda (tsc 2.5.2 atm), başlangıçta anahtar olarak sayısal bir dizeye sahip olmanıza bile izin verilmez. Bu nedenle, Himango'nun cevabı daha iyidir, çünkü tüm vakaları kapsar ve hiçbir dezavantajı yoktur.
srcspider

53

Benim için neler olduğunu anlamanın daha kolay, pratik ve doğrudan bir yolu şu şekildedir:

enum colors { red, green, blue };

Esasen buna dönüştürülecek:

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

Bu nedenle, aşağıdakiler doğru olacaktır:

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

Bu numaralandırılmış bir isim almak için kolay bir yol oluşturur:

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

Ayrıca, bir dizeyi numaralandırılmış bir değere dönüştürmek için güzel bir yol oluşturur.

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

Yukarıdaki iki durum çok daha yaygın bir durumdur, çünkü genellikle belirli bir değerin adı ve jenerik bir şekilde değerleri serileştirmekle daha çok ilgilenirsiniz.


49

Yalnızca adları arar ve daha sonra tekrarlarsanız:

Object.keys(myEnum).map(key => myEnum[key]).filter(value => typeof value === 'string') as string[];

13
Veya ES2017 lib ile:Object.values(myEnum).filter(value => typeof value === 'string') as string[];
Hiçbiri

Bir diksiyon oluşturmam gerekiyordu ve cevabınızı bir başlangıç ​​noktası olarak kullandım. Başka birinin ihtiyacı varsa,Object.values(myEnum).filter(value => typeof value === 'string').map(key => { return {id: myEnum[key], type: key }; });
Fejs

25

Geçerli TypeScript Sürüm 1.8.9 ile ben yazılan Numaralandırmalar kullanıyorum:

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

bu Javascript nesnesindeki sonuçlarla:

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

böylece anahtarlar ve değerler ile sorgulamak ve sadece değerleri döndürmek zorunda:

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

Ve bir Array'da seçenek tuşlarını alıyorum:

optionNames = [ "OPTION1", "OPTION2" ];


17

Bu çözüm de işe yarıyor.

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

var type: ScreenType = ScreenType.Edit;

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

14

Burada bulunan bir başka ilginç çözüm de ES6 Haritasını kullanmaktır:

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

KULLANIM

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

10

Let ts-enum-util( github , npm ) sizin için işi yapmak ve ek tip-güvenli yarar bir sürü sağlar. Hem dize hem de sayısal numaralandırmalarla çalışır, sayısal numaralandırmalar için sayısal dizin ters arama girişlerini düzgün yok sayar:

Dize sıralaması:

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

Sayısal numaralandırma:

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

9

TypeScript 2.4'ten başlayarak, numaralandırma anahtarı artık üye olarak içermez. TypeScript benioku kaynağından

Uyarı, dize ile başlatılan numaralandırmaların özgün numaralandırma üyesi adını almak için ters eşlenememesidir. Başka bir deyişle, "Kırmızı" dizesini almak için Renkler ["KIRMIZI" yazamazsınız.

Çözümüm:

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

8

enum-valuesAynı sorunu yaşadığımda yazdığım paketi kullanabilirsiniz :

Git: enum-değerleri

var names = EnumValues.getNames(myEnum);

3
Soruyu gerçekten cevaplamıyorsunuz, cevabınızı kod / vb ile belgelemek daha iyi olurdu, ancak paketi faydalı buldum.
lucuma

7

Yukarıdaki bazı cevaplara dayanarak, bu tür güvenli işlev imzasını buldum:

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

Kullanımı:

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

tipi stringValsIS'entry1' | 'entry2'

Hareket halindeyken görün


1
İşlev (keyof T)[]yerine dönmelidir keyof T. Ayrıca, exportoyun alanınızın çalışmasını durdurur.
Joald

7

Buradaki cevapların hiçbiri strict-mode'de string-enums ile çalışmayacak gibi görünüyor .

Enum'u şu şekilde düşünün:

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

Buna ile erişmek AnimalEnum["dog"]aşağıdaki gibi bir hataya neden olabilir:

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

Bu dava için uygun çözüm, şöyle yazın:

AnimalEnum["dog" as keyof typeof AnimalEnum]

Kullanmak için Parlak çözüm keyofile typeof! Diğer çözüm oldukça opak görünüyor, ama sonuçta bence
Typescript'in

5

Bence en iyi yol sadece istenen numaralandırma değerlerini bildirmektir. Bu şekilde onlara erişmek temiz ve güzel (her seferinde).

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

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

üretecek:

VALUE1
VALUE2

5

TypeScript belgelerine göre, bunu statik işlevlerle Enum üzerinden yapabiliriz.

Statik işlevlerle Enum Adını alın

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 

statik işlevli Enum hakkında daha fazla bilgi için aşağıdaki bağlantıyı takip edin https://basarat.gitbooks.io/typescript/docs/enums.html


4

Her durumda benim için çalışan tek çözüm (değerler dizeler olsa bile) şudur:

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

4

Eski soru, ama neden constnesne haritası kullanmıyorsunuz ?

Bunu yapmak yerine:

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]

Bunu yapın ( as constoyuncu kadrosuna dikkat edin ):

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]

Eğer yanlışsam beni düzeltin ama console.log(Object.keys(Foo))ilk örnekte sadece döner ["BAR", "EVERYTHING_IS_TERRIBLE"]..
Peter

@Peter ts oyun alanına bir göz atın , sadece konsolu açın ve koşmaya tıklayın. En azından benim için, yazdırıyor["60", "80", "BAR", "EVERYTHING_IS_TERRIBLE"]
Gabriel De Oliveira Rohden

1
bu doğru görünüyor, eğlenceli bir şey beklediğiniz çıktı olsun dizeleri değiştirmek eğer dizeleri, dizgiler dizeleri ve numaralar farklı numaralar neden farklı bir fikrim yok ..
Peter

4

Bu soruyu "numaralandırma anahtarları üzerinde TypeScript yinelemesini" arayarak buldum. Bu yüzden benim durumumda işe yarayan bir çözüm göndermek istiyorum. Belki de birine yardım eder.

Benim durumum şudur: Her numaralandırma anahtarı üzerinde yineleme yapmak, sonra bazı anahtarları filtrelemek, sonra numaralandırmadan hesaplanan değerleri olarak anahtarları olan bazı nesneye erişmek istiyorum. Bu yüzden herhangi bir TS hatası olmadan bunu nasıl yaparım.

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

3

Enum değeri tarafından tür denetimi yapan bir EnumUtil sınıfı yazdım:

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

Bu nasıl kullanılır:

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 anahtarlarının sonucu: ["A", "B"]

NumberValueEnum değerleri için sonuç: [0, 1]

StringValueEnumkeys için sonuç: ["A", "B"]

StringValueEnumvalues ​​için sonuç: ["A", "B"]


2

Bu çözümü daha zarif buluyorum:

for (let val in myEnum ) {

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

Görüntüleniyor:

bar 
foo

2

Benim Numaram şöyle:

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

yani bu dönüşü tanımsız yapmak :

UserSorting[UserSorting.SortByUpdatedAt]

Bu sorunu çözmek için, bir Pipe kullanarak yapmanın başka bir yolunu seçiyorum:

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

Ve kullanmak için:

return this.enumKeyPipe.transform(UserSorting, [UserSorting.SortByUpdatedAt]);

2

Numaralandırmanız varsa

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

Sonra anahtar ve değerleri alabilirsiniz:

Object.keys(Diet).forEach((d: Diet) => {
  console.log(d); // KETO
  console.log(Diet[d]) // Ketogenic
});

Bu bir hataya neden olur: 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

Bir numaralandırma numaralandırmak için yardımcı bir işlev yazdım:

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

Kullanımı:

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

İşlev, kolayca numaralandırılabilecek bir şey döndürür ve ayrıca numaralandırma türüne yayın yapar.


0

Geçerli sürüm TypeScript kullanarak, Numaralandırma'yı istediğiniz bir kayıtla eşleştirmek için bu gibi işlevleri kullanabilirsiniz. Sayı olan bir değere sahip anahtarlar ararken dize değerlerini bu işlevlerle tanımlayamayacağınızı unutmayın.

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

0

Burada zaten birçok cevap var ama çözümümü yine de yığına atacağım.

TypeScript Oyun Alanı

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

Açıklık için:

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

TypeScript Kaydı için Referans

Güzel bir yardımcı işlevi:

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

// getAccountTypeName(AccountType.Twitter) === 'Twitter'

0

Kullanmanız gereken numaralandırma değerlerinin listesini almak için:

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

Object.values(AnimalEnum);

-1

Sorunuzun tam cevabı değil, probleminizi çözmek için bir numara.

export module Gender {

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

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

}

Liste modelinizi istediğiniz şekilde genişletebilirsiniz.

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

Şimdi, bu şekilde kullanabilirsiniz:

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

veya:

if(i === Gender.Type.Male){
  console.log("I am a man.");
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.