ค้นหาเว็บไซต์

TypeScript - วิธีการดึงชื่อของสมาชิก enum?


ฉันต้องการวนลูปวัตถุ enum ของ TypeScript และรับชื่อสัญลักษณ์ที่ถูกกำหนดในแต่ละรายการ เช่น: enum myEnum { entry1, entry2 }

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

คำตอบ #1

แม้ว่าคำตอบจะถูกให้ไว้แล้ว แทบจะไม่มีใครชี้ไปที่เอกสาร

นี่คือชิ้นส่วนตัวอย่าง

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

โปรดจำไว้ว่าสมาชิกของ enum แบบสตริงจะไม่ได้รับการสร้างการแมปย้อนกลับเลย

คำตอบ #2

โค้ดที่คุณโพสต์จะทำงานได้; มันจะแสดงสมาชิกทั้งหมดของเอนัม รวมถึงค่าของสมาชิกเอนัมด้วย ตัวอย่างเช่น โค้ดต่อไปนี้:

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 = Number(enumMember) >= 0
   if (isValueProperty) {
      console.log("enum member: ", myEnum[enumMember]);
   }
}

นั่นจะพิมพ์เฉพาะชื่อออกมา:

Enum member: bar  
Enum member: foo

คำเตือน: สิ่งนี้พึ่งพารายละเอียดการใช้งานเล็กน้อย: TypeScript จะแปลง enums เป็นวัตถุ JS โดยค่าของ enum จะเป็นสมาชิกของวัตถุ หาก TS ตัดสินใจที่จะใช้งานมันแตกต่างในอนาคต เทคนิคด้านบนนี้อาจใช้ไม่ได้

คำตอบ #3

สำหรับฉัน วิธีที่ง่ายกว่า ใช้งานได้จริง และตรงไปตรงมาในการเข้าใจสิ่งที่กำลังเกิดขึ้น คือการเรียงลำดับดังต่อไปนี้:

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

สองสถานการณ์ข้างต้นเป็นสถานการณ์ที่พบบ่อยมากกว่า เพราะโดยปกติคุณจะสนใจชื่อของค่าที่เฉพาะเจาะจงมากกว่า และการทำให้ค่ามีลำดับในรูปแบบทั่วไป

คำตอบ #4

หากคุณค้นหาเฉพาะชื่อและวนซ้ำในภายหลัง ใช้:

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

คำตอบ #5

สมมติว่าคุณปฏิบัติตามกฎและสร้างเฉพาะ enums ที่มีค่าตัวเลขเท่านั้น คุณสามารถใช้โค้ดนี้ได้ ซึ่งจะจัดการกรณีที่คุณมีชื่อที่บังเอิญเป็นตัวเลขที่ถูกต้องได้อย่างถูกต้อง

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

คำตอบ #6

ดูเหมือนว่าจะไม่มีคำตอบใดที่นี่ที่จะใช้ได้กับ string-enums ในโหมด strict

พิจารณา enum ดังนี้:

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

การเข้าถึงสิ่งนี้ด้วย AnimalEnum["dog"] อาจทำให้เกิดข้อผิดพลาดเช่น:

องค์ประกอบมีประเภท 'any' โดยปริยายเนื่องจากนิพจน์ประเภท 'any' ไม่สามารถใช้เป็นดัชนีสำหรับประเภท 'typeof AnimalEnum'.ts(7053).

วิธีแก้ไขที่เหมาะสมสำหรับกรณีนั้น เขียนเป็นดังนี้:

AnimalEnum["dog" as keyof typeof AnimalEnum]

คำตอบ #7

ตั้งแต่ TypeScript 2.4 เป็นต้นไป, enums สามารถมีตัวกำหนดค่าแบบสตริงได้ https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html

นี่จะช่วยให้คุณเขียนได้:

 enum Order {
      ONE = "First",
      TWO = "Second"
 }

console.log(`One is ${Order.ONE.toString()}`);

และรับผลลัพธ์นี้:

หนึ่งคือคนแรก

คำตอบ #8

ด้วย TypeScript เวอร์ชันปัจจุบัน 1.8.9 ฉันใช้ Enums ที่มีการพิมพ์:

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

คำตอบ #9

วิธีแก้นี้ใช้ได้เช่นกัน

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

var type: ScreenType = ScreenType.Edit;

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

คำตอบ #10

โดยย่อ

ถ้า enums ของคุณเป็นดังนี้:

export enum Colors1 {
  Red = 1,
  Green = 2,
  Blue = 3
}

เพื่อให้ได้ข้อความและค่าที่เฉพาะเจาะจง:

console.log(Colors1.Red); // 1 
console.log(Colors1[Colors1.Red]); // Red

เพื่อรับรายการของค่าและข้อความ:

public getTextAndValues(e: { [s: number]: string }) {
  for (const enumMember in e) {
    if (parseInt(enumMember, 10) >= 0) {
      console.log(e[enumMember]) // Value, such as 1,2,3
      console.log(parseInt(enumMember, 10)) // Text, such as Red,Green,Blue
    }
  }
}
this.getTextAndValues(Colors1)

ถ้า enums ของคุณเป็นดังนี้:

export enum Colors2 {
  Red = "Red",
  Green = "Green",
  Blue = "Blue"
}

เพื่อรับข้อความและค่าที่เฉพาะเจาะจง:

console.log(Colors2.Red); // Red
console.log(Colors2["Red"]); // Red

เพื่อรับรายการของค่าและข้อความ:

public getTextAndValues(e: { [s: string]: string }) {
  for (const enumMember in e) {
    console.log(e[enumMember]);// Value, such as Red,Green,Blue
    console.log(enumMember); //  Text, such as Red,Green,Blue
  }
}
this.getTextAndValues(Colors2)

คำตอบ #11

อีกวิธีแก้ปัญหาที่น่าสนใจที่พบที่นี่คือการใช้ 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']
]);

ใช้

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


TypeLabel.forEach((label, value) => {
  console.log(label, value);
});

// Low Season 0
// Mid Season 1
// High Season 2    

คำตอบ #12

ให้ ts-enum-util (github, npm) ทำงานให้คุณและให้ยูทิลิตี้แบบ type-safe เพิ่มเติมมากมาย ใช้ได้กับทั้ง enum แบบสตริงและตัวเลข โดยละเว้นรายการค้นหากลับตามดัชนีตัวเลขสำหรับ enum แบบตัวเลขอย่างถูกต้อง:

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

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

คำตอบ #13

ฉันรู้สึกเหนื่อยจากการดูคำตอบที่ผิด ๆ เลยทำเอง

  • อันนี้มีการทดสอบ
  • ทำงานกับประเภทการนับทั้งหมด
  • พิมพ์ถูกต้อง
type EnumKeys<Enum> = Exclude<keyof Enum, number>

const enumObject = <Enum extends Record<string, number | string>>(e: Enum) => {
    const copy = {...e} as { [K in EnumKeys<Enum>]: Enum[K] };
    Object.values(e).forEach(value => typeof value === 'number' && delete copy[value]);
    return copy;
};

const enumKeys = <Enum extends Record<string, number | string>>(e: Enum) => {
    return Object.keys(enumObject(e)) as EnumKeys<Enum>[];
};

const enumValues = <Enum extends Record<string, number | string>>(e: Enum) => {
    return [...new Set(Object.values(enumObject(e)))] as Enum[EnumKeys<Enum>][];
};

enum Test1 { A = "C", B = "D"}
enum Test2 { A, B }
enum Test3 { A = 0, B = "C" }
enum Test4 { A = "0", B = "C" }
enum Test5 { undefined = "A" }
enum Test6 { A = "undefined" }
enum Test7 { A, B = "A" }
enum Test8 { A = "A", B = "A" }
enum Test9 { A = "B", B = "A" }

console.log(enumObject(Test1)); // {A: "C", B: "D"}
console.log(enumObject(Test2)); // {A: 0, B: 1}
console.log(enumObject(Test3)); // {A: 0, B: "C"}
console.log(enumObject(Test4)); // {A: "0", B: "C"}
console.log(enumObject(Test5)); // {undefined: "A"}
console.log(enumObject(Test6)); // {A: "undefined"}
console.log(enumObject(Test7)); // {A: 0,B: "A"}
console.log(enumObject(Test8)); // {A: "A", B: "A"}
console.log(enumObject(Test9)); // {A: "B", B: "A"}

console.log(enumKeys(Test1)); // ["A", "B"]
console.log(enumKeys(Test2)); // ["A", "B"]
console.log(enumKeys(Test3)); // ["A", "B"]
console.log(enumKeys(Test4)); // ["A", "B"]
console.log(enumKeys(Test5)); // ["undefined"]
console.log(enumKeys(Test6)); // ["A"]
console.log(enumKeys(Test7)); // ["A", "B"]
console.log(enumKeys(Test8)); // ["A", "B"]
console.log(enumKeys(Test9)); // ["A", "B"]

console.log(enumValues(Test1)); // ["C", "D"]
console.log(enumValues(Test2)); // [0, 1]
console.log(enumValues(Test3)); // [0, "C"]
console.log(enumValues(Test4)); // ["0", "C"]
console.log(enumValues(Test5)); // ["A"] 
console.log(enumValues(Test6)); // ["undefined"] 
console.log(enumValues(Test7)); // [0, "A"]
console.log(enumValues(Test8)); // ["A"]
console.log(enumValues(Test9)); // ["B", "A"]

เวอร์ชันออนไลน์

คำตอบ #14

ใน TypeScript, enum จะถูกรวมเป็นแผนที่ (เพื่อให้ได้ค่าจากคีย์) ใน JavaScript:

enum MyEnum {
  entry0,
  entry1,
}

console.log(MyEnum['entry0']); // 0
console.log(MyEnum['entry1']); // 1

นอกจากนี้ยังสร้างแผนที่กลับด้าน (เพื่อหาคีย์จากค่า):

console.log(MyEnum[0]); // 'entry0'
console.log(MyEnum[0]); // 'entry1'

ดังนั้นคุณสามารถเข้าถึงชื่อของรายการได้โดยทำดังนี้:

console.log(MyEnum[MyEnum.entry0]); // 'entry0'
console.log(MyEnum[MyEnum.entry1]); // 'entry1'

อย่างไรก็ตาม enum แบบสตริงไม่มีแผนที่ย้อนกลับตามการออกแบบ (ดูความคิดเห็นและคำขอ pull) เนื่องจากสิ่งนี้อาจทำให้เกิดความขัดแย้งระหว่างคีย์และค่าภายในออบเจ็กต์แผนที่ได้

enum MyEnum {
  entry0 = 'value0',
  entry1 = 'value1',
}

console.log(MyEnum['value0']); // undefined
console.log(MyEnum['value1']); // undefined

ถ้าคุณต้องการบังคับให้ enum ของสตริงของคุณคอมไพล์แผนที่กลับด้าน (คุณต้องมั่นใจว่าคีย์และค่าทั้งหมดต่างกัน) คุณสามารถใช้กลเม็ดนี้ได้:

enum MyEnum {
  entry0 = <any>'value0',
  entry1 = <any>'value1',
}

console.log(MyEnum['value0']); // 'entry0'
console.log(MyEnum['value1']); // 'entry1'
console.log(MyEnum[MyEnum.entry0]); // 'entry0'
console.log(MyEnum[MyEnum.entry1]); // 'entry1'

คำตอบ #15

สมมติว่าคุณมี enum

export enum SCROLL_LABEL_OFFSET {
  SMALL = 48,
  REGULAR = 60,
  LARGE = 112
}

และคุณต้องการสร้างประเภทจาก enum แต่ไม่ใช่แค่คัดลอกและวาง คุณสามารถใช้ enum เพื่อสร้าง type ของคุณได้แบบนี้:

export type ScrollLabelOffset = keyof typeof SCROLL_LABEL_OFFSET;

ในผลลัพธ์คุณจะได้รับ type ที่มีค่าที่เป็นไปได้ดังนี้ 'SMALL' | 'REGULAR' | 'LARGE'

บทความที่เกี่ยวข้อง