ตรวจสอบว่ามีค่าอยู่ใน enum ใน TypeScript


163

ฉันได้รับหมายเลขtype = 3และต้องตรวจสอบว่ามีอยู่ใน enum นี้:

export const MESSAGE_TYPE = {
    INFO: 1,
    SUCCESS: 2,
    WARNING: 3,
    ERROR: 4,
};

วิธีที่ดีที่สุดที่ฉันพบคือการรับค่า Enum ทั้งหมดเป็นอาร์เรย์และใช้ indexOf กับมัน แต่โค้ดผลลัพธ์ไม่ชัดเจนมาก:

if( -1 < _.values( MESSAGE_TYPE ).indexOf( _.toInteger( type ) ) ) {
    // do stuff ...
}

มีวิธีที่ง่ายกว่าในการทำเช่นนี้?


if(Object.values(MESSAGE_TYPE).includes(+type)? มีไม่มากที่คุณสามารถทำได้
Andrew Li

1
สิ่งนี้ใช้ได้ใน ES6 แต่ไม่ใช่ใน ES5 น่าเสียดาย
Tim Schoch

@TimSchoch คุณสามารถทำได้!!MESSAGE_TYPE[type]เพื่อตรวจสอบว่ามีค่าอยู่ MESSAGE_TYPE[type]จะกลับมาไม่ได้กำหนดหากไม่มีค่าtypeอยู่ในMESSAGE_TYPE
Babcock

1
@ เควินแบ็บค้อกที่จะล้มเหลวของหนึ่งในค่า enum แผนที่ไป0แม้ว่า
Ingo Bürk

@Ingo Bürkเยี่ยมมาก! ฉันเดาว่าสามารถตรวจสอบได้อย่างชัดเจนMESSAGE_TYPE[type] !== undefined
Kevin Babcock

คำตอบ:


213

หากคุณต้องการให้สิ่งนี้ทำงานกับ string enums คุณต้องใช้Object.values(ENUM).includes(ENUM.value)เพราะ string enums ไม่ได้ถูกแมปกลับกันตามhttps://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html :

Enum Vehicle {
    Car = 'car',
    Bike = 'bike',
    Truck = 'truck'
}

กลายเป็น:

{
    Car: 'car',
    Bike: 'bike',
    Truck: 'truck'
}

ดังนั้นคุณต้องทำ:

if (Object.values(Vehicle).includes('car')) {
    // Do stuff here
}

หากคุณได้รับข้อผิดพลาดสำหรับ: แสดงProperty 'values' does not exist on type 'ObjectConstructor'ว่าคุณไม่ได้กำหนดเป้าหมาย ES2017 คุณสามารถใช้การกำหนดค่า tsconfig.json นี้:

"compilerOptions": {
    "lib": ["es2017"]
}

หรือคุณสามารถเลือกนักแสดง:

if ((<any>Object).values(Vehicle).includes('car')) {
    // Do stuff here
}

7
JSONLint Property 'values' does not exist on type 'ObjectConstructor'มีการแสดง
BBaysinger

5
@BBaysinger ใน typescript ลองใช้แทน:(<any>Object).values(Vehicle).includes(Vehicle.car)
Salem Ouerdani

1
ยอดเยี่ยม นี่ควรเป็นคำตอบที่ยอมรับได้ คำตอบที่ยอมรับจะไม่ทำงานหากคีย์และค่า enum ของฉันแตกต่างกัน
Pratap AK

2
สิ่งนี้ไม่ทำงานใน typescript นอกจากนี้การแก้ไขยังมีการหยุดพักใน IE
Jerin Joseph

3
ฉันเชื่อว่านี่ไม่ใช่คำตอบสำหรับคำถามนี้ โซลูชันของคุณ(Object.values(Vehicle).includes(Vehicle.car))จะเป็นจริงเสมอ แต่คำถามคือวิธีการตรวจสอบว่าค่าที่กำหนดรวมอยู่ใน enum ตัวอย่างเช่น(Object.values(Vehicle).includes('car'))ควรส่งคืนtrueแต่(Object.values(Vehicle).includes('plane'))ควรส่งคืนค่าเท็จ
tommybernaciak

140

หากคุณใช้ TypeScript คุณสามารถใช้enum จริงได้ inจากนั้นคุณสามารถตรวจสอบได้โดยใช้

สิ่งนี้จะทำงานได้เฉพาะเมื่อ enum ของคุณเป็นตัวเลขและไม่ได้ทำเครื่องหมายconst:

export enum MESSAGE_TYPE {
    INFO = 1,
    SUCCESS = 2,
    WARNING = 3,
    ERROR = 4,
};

var type = 3;

if (type in MESSAGE_TYPE) {

}

สิ่งนี้ทำงานได้เพราะเมื่อคุณคอมไพล์ enum ด้านบนมันจะสร้างวัตถุด้านล่าง:

{
    '1': 'INFO',
    '2': 'SUCCESS',
    '3': 'WARNING',
    '4': 'ERROR',
    INFO: 1,
    SUCCESS: 2,
    WARNING: 3,
    ERROR: 4
}

ใช้ได้กับ enums ที่ถูกต้องเท่านั้น ขณะนี้มันถูกกำหนดเป็นเช่นนี้:export const MESSAGE_TYPE = { ... }
ทิม Schoch

ใช่. เฉพาะกับจำนวนที่เหมาะสม
Saravana

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

เราเปลี่ยนMESSAGE_TYPEเป็น enum จริงตามที่คุณแนะนำและตอนนี้โซลูชันของคุณใช้งานได้อย่างมีเสน่ห์ ขอบคุณ @Saravana
Tim Schoch

71
สิ่งนี้ไม่ทำงานกับ enums สตริงเนื่องจากไม่ได้ถูกแมปกลับกัน: typescriptlang.org/docs/handbook/release-notes/ …
Xiv

20

TypeScript v3.7.3

export enum YourEnum {
   enum1 = 'enum1',
   enum2 = 'enum2',
   enum3 = 'enum3',
}

const status = 'enumnumnum';

if (!(status in YourEnum)) {
     throw new UnprocessableEntityResponse('Invalid enum val');
}

3
ฉันชอบสิ่งนี้มากที่สุด
Ashley Coolman

3
ตัวอย่างนี้ใช้ค่าคีย์ == เท่านั้นและนั่นคือเหตุผลที่ใช้งานใช่ไหม ถ้า key! = value มันจะตรวจสอบโดยคีย์
Konstantin Pelepelin

14
ที่จริงกรณีนี้ใช้งานได้เพราะบังเอิญเท่านั้น จะพบ 'enum1' เท่านั้นเนื่องจากเป็นค่าเดียวกับคีย์ แต่ถ้าปุ่มแตกต่างจากค่ามันไม่ทำงาน
lukas_o

3
@lukas_o พูดถูก วิธีการแก้ปัญหานี้ดูชัดเจนตั้งแต่แรกเห็น แต่แน่นอนว่ามันจะบั๊กได้ง่าย
piotros

14

มีวิธีแก้ปัญหาที่ง่ายและง่ายสำหรับคำถามของคุณ:

var districtId = 210;

if (DistrictsEnum[districtId] != null) {

// Returns 'undefined' if the districtId not exists in the DistrictsEnum 
    model.handlingDistrictId = districtId;
}

ขอบคุณ Ester สำหรับคำตอบของคุณ เนื่องจากฉันเปลี่ยนจากการเขียนโปรแกรมไปเป็น UX Design เต็มเวลาฉันไม่สามารถยืนยันได้อีกต่อไป @ แถว, ให้ฉันรู้ว่าถ้าคำตอบที่ยอมรับยังคงเป็นวิธีที่จะไปในปี 2019! ไชโย
Tim Schoch

2
@TimSchoch ฉันสามารถยืนยันได้ว่าทำงานได้ดีอย่างน้อยสำหรับ enums ตัวเลข นี่เป็นคำตอบที่หรูหราที่สุด
Patrick P.

@PatrickP คุณสามารถยืนยันได้หรือไม่ว่าโซลูชันที่เสนอโดย Ester นั้นสามารถใช้งานกับ enums ได้เช่นกัน?
Tim Schoch

1
@TimSchoch ใช่! มันใช้งานได้กับสตริงด้วย เช่นพจนานุกรม - คุณสามารถใช้ปุ่มใดก็ได้ในพจนานุกรม
Ester Kaufman

9
โปรดทราบว่าสิ่งนี้ไม่ได้ผลสำหรับ string enums หาก enum ใช้สตริง initializers ที่มีค่าต่างจากชื่อสมาชิก enum ดูคำตอบของ @ Xiv ด้านล่าง: stackoverflow.com/a/47755096/4752920
kcstricks

5
export enum UserLevel {
  Staff = 0,
  Leader,
  Manager,
}

export enum Gender {
  None = "none",
  Male = "male",
  Female = "female",
}

ผลต่างในบันทึก:

log(Object.keys(Gender))
=>
[ 'None', 'Male', 'Female' ]

log(Object.keys(UserLevel))
=>
[ '0', '1', '2', 'Staff', 'Leader', 'Manager' ]

การแก้ปัญหาเราจำเป็นต้องลบคีย์เป็นตัวเลข

export class Util {
  static existValueInEnum(type: any, value: any): boolean {
    return Object.keys(type).filter(k => isNaN(Number(k))).filter(k => type[k] === value).length > 0;
  }
}

การใช้

// For string value
if (!Util.existValueInEnum(Gender, "XYZ")) {
  //todo
}

//For number value, remember cast to Number using Number(val)
if (!Util.existValueInEnum(UserLevel, 0)) {
  //todo
}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.