列挙型エントリの名前を取得するにはどうすればよいですか?


314

TypeScriptとenumタイプを反復処理して、列挙された各シンボル名を取得します。例:

enum myEnum { entry1, entry2 }

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

この小さな列挙-のためのパッケージがありgetAllEnumValuesgetAllEnumKeysあなたの目的のために
transang

回答:


256

投稿したコードは機能します。列挙型メンバーの値を含む、列挙型のすべてのメンバーを出力します。たとえば、次のコード:

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

名前だけが出力されます。

列挙型メンバー:bar

列挙型メンバー:foo

警告:これは実装の詳細にわずかに依存しています:TypeScriptは列挙型をJSオブジェクトにコンパイルし、列挙型の値はオブジェクトのメンバーです。TSが将来的に別の方法で実装することを決定した場合、上記の手法は失敗する可能性があります。


23
明確にするために、上記の回答はTS 2.3でも機能します。ただし、単に「enum」ではなく「const enum」を使用すると、それだけでは機能しません。const enumを使用することは、基本的にTSに検索と置換を行うように指示することです。MyEnum.Fooを使用するすべての場所で、対応する数値に置き換えられます。
ユダガブリエルヒマンゴ2017年

負の値または浮動小数点値も逆マッピングさ+enumMember >= 0れるisFinite(+enumMember)ため、これは正しいと思います。(プレイグラウンド
spenceryue '11

342

答えはすでに提供されていますが、ほとんど誰もドキュメントを指さしていません

これがスニペットです

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

文字列列挙型メンバーは、逆マッピングをまったく生成しないことに注意してください。


38
また、「文字列列挙型メンバーは、逆マッピングが生成されないことを覚えておいてください」とも書かれています。
jbojcic 2017年

1
この列挙型から、0または1この列挙型からどうですか?export enum Octave { ZERO = 0, ONE = 1 }
ステファン

@jbojcicそれは状況についてenum Enum {"A"}; let nameOfA = Enum[Enum.A];ですか?typescript@2.9.2以降は、私にとっては問題なく動作します...
ellockie

値をループするのはどうですか?
しおこ

55

規則を守り、数値の列挙のみを生成すると仮定すると、このコードを使用できます。これは、偶然に有効な番号である名前がある場合を正しく処理します

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

警告最新のタイプスクリプト(tsc 2.5.2 atm)では、数値文字列をキーとして使用することもできません。そのため、Himangoの答えは、すべてのケースをカバーし、欠点がないため、より優れています。
srcspider 2017年

53

私にとって、何が起こっているのかを理解するためのより簡単で実用的で直接的な方法は、次の列挙です。

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

上記の2つの状況ははるかに一般的な状況です。通常、特定の値の名前と一般的な方法で値をシリアル化することにはるかに関心があるためです。


49

名前のみを検索して後で繰り返す場合は、次のようにします。

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

13
または、ES2017 libを使用: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 }; });
Fejs

25

現在のTypeScriptバージョン1.8.9では、型付きのEnumを使用します。

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" ];


17

このソリューションも機能します。

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

var type: ScreenType = ScreenType.Edit;

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

14

ここにあるもう1つの興味深い解決策は、ES6マップを使用することです

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

10

Let ts-enum-utilgithubnpm)あなたのための作業を行うと、追加型安全なユーティリティの多くを提供しています。数値列挙の数値インデックス逆ルックアップエントリを適切に無視して、文字列と数値列挙の両方で機能します。

文字列列挙:

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

9

TypeScript 2.4以降では、enumにはキーがメンバーとして含まれなくなりました。TypeScript readmeからのソース

注意点は、文字列で初期化された列挙型を逆マッピングして、元の列挙型メンバー名を取得することはできないということです。つまり、Colors ["RED"]を記述して文字列「Red」を取得することはできません。

私の解決策:

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

8

enum-values同じ問題が発生したときに作成したパッケージを使用できます。

Git:列挙値

var names = EnumValues.getNames(myEnum);

3
あなたは本当に質問に答えているわけではありません、あなたの答えをコードなどで文書化する方が良いでしょうが、私はパッケージが有用だと思いました。
lucuma 2017

7

上記のいくつかの回答に基づいて、このタイプセーフな関数シグネチャを思いつきました。

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'

実際に見る


1
関数はの(keyof T)[]代わりに戻る必要がありkeyof Tます。また、export遊び場が機能しなくなります。
ジョアルド2018

7

strict-modeのstring-enumsでは、ここでの答えはどれも機能しないようです。

列挙型を次のように考えてください:

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]

使用のためのブリリアントソリューションkeyoftypeof!他の解決策はかなり不透明なようですが、結局
Typescript

5

私が考える最良の方法は、必要な列挙値を宣言することです。そのようにしてそれらにアクセスすることは、クリーンできれいです(毎回)。

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

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

生成されます:

VALUE1
VALUE2

5

TypeScriptドキュメントによると、静的関数を使用して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


4

(値が文字列であっても)すべての場合に機能する唯一の解決策は次のとおりです。

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

4

古い質問ですが、なぜ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"].. のみが返されます
Peter

@Peter がtsプレイグラウンドを、コンソールを開いて[run]をクリックします。少なくとも私にとっては、次のように印刷されます["60", "80", "BAR", "EVERYTHING_IS_TERRIBLE"]
Gabriel De Oliveira Rohden

1
それは..あなたが数字からあなたは、私が期待される出力を取得する文字列に変更した場合、私は考え、なぜtypescriptですハンドル列とは異なる列挙型の中の数字を持っていないあなたの権利、楽しいものだ
ピーター

4

「TypeScriptは列挙型キーを反復処理する」を検索してこの質問を見つけました。だから私は私の場合にうまくいく解決策を投稿したいだけです。多分それは誰かにも役立ちます。

私の場合は次のとおりです。各列挙型キーを反復処理し、いくつかのキーをフィルター処理してから、列挙型から計算された値としてキーを持つオブジェクトにアクセスします。これが、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

列挙値によって型チェックを行うEnumUtilクラスを作成しました。

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



2

私の列挙型は次のとおりです:

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

2

列挙型がある場合

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

1

列挙型を列挙するヘルパー関数を書きました:

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
}

この関数は、簡単に列挙できるものを返し、列挙型にキャストします。


0

現在のバージョンの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
  }
}

0

ここにはすでにたくさんの答えがありますが、とにかく自分の解決策をスタックに投入するつもりです。

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

明確にするために:

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

TypeScriptレコードのリファレンス

素晴らしいヘルパー関数:

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

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

0

使用する必要がある列挙値のリストを取得するには:

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

Object.values(AnimalEnum);

-1

それはあなたの質問の正確な答えではありませんが、あなたの問題に取り組むためのトリックです。

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.");
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.