Làm thế nào để có được tên của mục enum?


314

Tôi muốn lặp lại một TypeScript enumvà nhận từng tên biểu tượng liệt kê, ví dụ:

enum myEnum { entry1, entry2 }

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

gói enum-for nhỏ bé này có getAllEnumValuesgetAllEnumKeyscho mục đích của bạn
transang

Câu trả lời:


255

Mã bạn đã đăng sẽ hoạt động; nó sẽ in ra tất cả các thành viên của enum, bao gồm các giá trị của các thành viên enum. Ví dụ: đoạn mã sau:

enum myEnum { bar, foo }

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

Sẽ in như sau:

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

Thay vào đó, nếu bạn chỉ muốn tên thành viên chứ không phải các giá trị, bạn có thể làm một cái gì đó như thế này:

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

Điều đó sẽ in ra chỉ tên:

Thành viên Enum: thanh

Thành viên Enum: foo

Hãy cẩn thận: điều này hơi phụ thuộc vào một chi tiết triển khai: TypeScript biên dịch enum thành một đối tượng JS với các giá trị enum là thành viên của đối tượng. Nếu TS quyết định thực hiện chúng khác nhau trong tương lai, kỹ thuật trên có thể bị phá vỡ.


23
Để rõ ràng, câu trả lời trên vẫn hoạt động kể từ TS 2.3. Tuy nhiên, nếu bạn sử dụng "const enum", thay vì chỉ "enum", chỉ sau đó nó sẽ không hoạt động. Sử dụng const enum về cơ bản là bảo TS thực hiện tìm kiếm và thay thế; mỗi nơi bạn sử dụng MyEnum.Foo, nó sẽ được thay thế bằng một giá trị số tương ứng.
Judah Gabriel Himango

Tôi nghĩ điều +enumMember >= 0này là isFinite(+enumMember)do các giá trị âm hoặc dấu phẩy động cũng được ánh xạ ngược lại. ( Sân chơi )
spenceryue

342

Mặc dù câu trả lời đã được cung cấp, nhưng hầu như không ai chỉ vào tài liệu

Đây là một đoạn

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

Hãy nhớ rằng các thành viên chuỗi enum hoàn toàn không có được ánh xạ ngược.


38
Nó cũng nói rằng "Hãy nhớ rằng các thành viên chuỗi enum không nhận được một ánh xạ ngược được tạo ra."
jbojcic

1
Làm thế nào về hiển thị 0hoặc 1từ enum này? export enum Octave { ZERO = 0, ONE = 1 }
Stephane

@jbojcic Có phải là về tình huống : enum Enum {"A"}; let nameOfA = Enum[Enum.A];? Kể từ typcript@2.9.2, nó hoạt động tốt với tôi ...
ellockie

Làm thế nào về việc lặp qua các giá trị?
shioko

55

Giả sử bạn tuân thủ các quy tắc và chỉ tạo ra các enum với các giá trị số, bạn có thể sử dụng mã này. Điều này xử lý chính xác trường hợp bạn có một tên trùng hợp là một số hợp lệ

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

Cảnh báo Trong bản thảo hiện đại (tsc 2.5.2 atm), bạn thậm chí không được phép có một chuỗi số làm khóa để bắt đầu. Như vậy, câu trả lời của Himango là tốt hơn, vì nó bao gồm tất cả các trường hợp và không có nhược điểm.
srcspider

53

Đối với tôi một cách dễ dàng, thiết thực và trực tiếp hơn để hiểu những gì đang diễn ra, đó là bảng liệt kê sau:

enum colors { red, green, blue };

Sẽ được chuyển đổi về cơ bản này:

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

Bởi vì điều này, sau đây sẽ là đúng:

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

Điều này tạo ra một cách dễ dàng để có được tên của một liệt kê như sau:

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

Nó cũng tạo ra một cách hay để chuyển đổi một chuỗi thành một giá trị được liệt kê.

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

Hai tình huống trên là tình huống phổ biến hơn nhiều, bởi vì thông thường bạn quan tâm nhiều hơn đến tên của một giá trị cụ thể và tuần tự hóa các giá trị theo cách chung.


49

Nếu bạn chỉ tìm kiếm tên và lặp lại sau, sử dụng:

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

13
Hoặc với lib ES2017:Object.values(myEnum).filter(value => typeof value === 'string') as string[];
Không

Tôi cần phải tạo ra một câu lệnh và tôi đã sử dụng câu trả lời của bạn làm điểm bắt đầu. Nếu ai đó cần nó,Object.values(myEnum).filter(value => typeof value === 'string').map(key => { return {id: myEnum[key], type: key }; });
Fejs

25

Với TypeScript Phiên bản 1.8.9 hiện tại, tôi sử dụng Enums gõ:

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

với kết quả trong đối tượng Javascript này:

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

vì vậy tôi phải truy vấn thông qua các khóa và giá trị và chỉ trả về giá trị:

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

Và tôi nhận được các phím tùy chọn trong một mảng:

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


17

Giải pháp này hoạt động quá.

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

var type: ScreenType = ScreenType.Edit;

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

14

Một giải pháp thú vị khác được tìm thấy ở đây là sử dụng 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']
]);

SỬ DỤNG

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

10

Hãy để ts-enum-util( github , npm ) thực hiện công việc cho bạn và cung cấp rất nhiều tiện ích an toàn loại bổ sung. Hoạt động với cả enum chuỗi và số, bỏ qua đúng các mục tra cứu ngược chỉ mục số cho enum số:

Chuỗi 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();

Số enum:

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

Bắt đầu từ TypeScript 2.4, enum sẽ không chứa khóa làm thành viên nữa. nguồn từ readScript Typeme

Thông báo trước là các enum khởi tạo chuỗi không thể được ánh xạ ngược để lấy tên thành viên enum ban đầu. Nói cách khác, bạn không thể viết Màu ["ĐỎ"] để lấy chuỗi "Đỏ".

Giải pháp của tôi:

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

8

Bạn có thể sử dụng enum-valuesgói tôi đã viết khi tôi gặp vấn đề tương tự:

Git: enum-giá trị

var names = EnumValues.getNames(myEnum);

3
Bạn không thực sự trả lời câu hỏi, tốt hơn là ghi lại câu trả lời của bạn bằng mã / vv nhưng tôi đã tìm thấy gói hữu ích.
lucuma

7

Dựa trên một số câu trả lời ở trên, tôi đã đưa ra chữ ký hàm an toàn loại này:

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

Sử dụng:

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

loại stringVals'entry1' | 'entry2'

Xem nó trong hành động


1
Các chức năng sẽ trở lại (keyof T)[]thay vì keyof T. Ngoài ra, các exportsân chơi của bạn dừng hoạt động.
Joald

7

Dường như không có câu trả lời nào ở đây sẽ hoạt động với chuỗi-enums trong strict-mode.

Hãy xem xét enum như:

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

Truy cập này có AnimalEnum["dog"]thể dẫn đến một lỗi như:

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

Giải pháp thích hợp cho trường hợp đó, viết nó như sau:

AnimalEnum["dog" as keyof typeof AnimalEnum]

Giải pháp tuyệt vời cho việc sử dụng keyofvới typeof! Giải pháp khác có vẻ khá mờ nhạt, nhưng sau tất cả, tôi nghĩ rằng Typecript cần tiếp tục cải thiện trên DX - Trải nghiệm dành cho nhà phát triển cho Enum
Shaung Cheng

5

Cách tốt nhất tôi nghĩ là chỉ cần khai báo các giá trị enum mong muốn. Cách đó truy cập chúng là sạch sẽ và đẹp (mọi lúc).

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

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

sẽ sản xuất:

VALUE1
VALUE2

5

Theo tài liệu của TypeScript, chúng ta có thể thực hiện điều này thông qua Enum với các hàm tĩnh.

Nhận tên Enum với các hàm tĩnh

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 

để đọc thêm về Enum với chức năng tĩnh, hãy theo liên kết dưới đây https://basarat.gitbooks.io/typescript/docs/enums.html


4

Giải pháp duy nhất phù hợp với tôi trong mọi trường hợp (ngay cả khi giá trị là chuỗi) là:

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

4

Câu hỏi cũ, nhưng, tại sao không sử dụng constbản đồ đối tượng?

Thay vì làm điều này:

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]

Làm điều này (chú ý đến các as constdiễn viên):

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]

Sửa lỗi cho tôi nếu tôi sai nhưng console.log(Object.keys(Foo))trong ví dụ đầu tiên chỉ trả về ["BAR", "EVERYTHING_IS_TERRIBLE"]..
Peter

@Peter hãy xem ở đây tại sân chơi ts , chỉ cần mở bàn điều khiển và nhấp vào chạy. Ít nhất là đối với tôi, nó được in["60", "80", "BAR", "EVERYTHING_IS_TERRIBLE"]
Gabriel De Oliveira Rohden

1
Có vẻ như bạn đúng, điều thú vị nếu bạn thay đổi từ số sang chuỗi bạn nhận được đầu ra mà tôi mong đợi, tôi không biết tại sao bản in lại xử lý chuỗi và số khác nhau trong enums ..
Peter

4

Tôi tìm thấy câu hỏi này bằng cách tìm kiếm "TypeScript lặp qua các khóa enum". Vì vậy, tôi chỉ muốn đăng giải pháp phù hợp với tôi trong trường hợp của tôi. Có lẽ nó cũng sẽ giúp được ai đó.

Trường hợp của tôi là như sau: Tôi muốn lặp lại từng khóa enum, sau đó lọc một số khóa, sau đó truy cập một số đối tượng có các khóa là giá trị được tính từ enum. Vì vậy, đây là cách tôi làm mà không có bất kỳ lỗi 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]
    }))

3

Tôi đã viết một lớp EnumUtil đang thực hiện kiểm tra kiểu theo giá trị 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'
}

Làm thế nào để sử dụng nó:

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

Kết quả cho các khóa NumberValueEnum: ["A", "B"]

Kết quả cho các giá trị NumberValueEnum: [0, 1]

Kết quả cho StringValueEnumkeys: ["A", "B"]

Kết quả cho StringValueEnumvalues: ["A", "B"]


2

Tôi thấy giải pháp đó thanh lịch hơn:

for (let val in myEnum ) {

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

Nó sẽ hiển thị:

bar 
foo

2

Enum của tôi là như thế này:

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

Vì vậy, làm điều này trở lại không xác định :

UserSorting[UserSorting.SortByUpdatedAt]

Để giải quyết vấn đề này, tôi chọn một cách khác để thực hiện bằng cách sử dụng ống:

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

Và để sử dụng nó:

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

2

Nếu bạn có enum

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

Sau đó, bạn có thể nhận khóa và giá trị như:

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

Điều này gây ra lỗi: 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)
16:30

1

Tôi đã viết một hàm trợ giúp để liệt kê một 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;
}

Sử dụng:

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

Hàm trả về một cái gì đó có thể dễ dàng liệt kê, và cũng chuyển sang loại enum.


0

Sử dụng TypeScript phiên bản hiện tại, bạn có thể sử dụng các hàm như thế này để ánh xạ Enum tới bản ghi bạn chọn. Lưu ý rằng bạn không thể xác định các giá trị chuỗi với các hàm này khi chúng tìm các khóa có giá trị là một số.

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

Đã có rất nhiều câu trả lời ở đây nhưng tôi nghĩ rằng tôi sẽ ném giải pháp của mình lên ngăn xếp.

Sân chơi TypeScript

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

Cho rõ ràng:

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

Tham chiếu cho bản ghi TypeScript

Một chức năng trợ giúp tốt đẹp:

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

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

0

Để có được danh sách các giá trị enum bạn phải sử dụng:

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

Object.values(AnimalEnum);

-1

Nó không phải là câu trả lời chính xác cho câu hỏi của bạn nhưng nó là một mẹo để giải quyết vấn đề của bạn.

export module Gender {

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

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

}

Bạn có thể mở rộng mô hình danh sách của bạn theo cách bạn muốn.

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

Bây giờ, bạn có thể sử dụng nó theo cách này:

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

hoặc là:

if(i === Gender.Type.Male){
  console.log("I am a man.");
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.