Kiểm tra xem giá trị có tồn tại trong enum trong TypeScript không


163

Tôi nhận được một số type = 3và phải kiểm tra xem nó có tồn tại trong enum này không:

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

Cách tốt nhất tôi tìm thấy là lấy tất cả các giá trị Enum dưới dạng một mảng và sử dụng indexOf trên đó. Nhưng mã kết quả không phải là rất dễ đọc:

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

Có cách nào đơn giản hơn để làm điều này?


if(Object.values(MESSAGE_TYPE).includes(+type)? Bạn không thể làm được gì nhiều.
Andrew Li

1
Điều này hoạt động trong ES6 nhưng không may trong ES5
Tim Schoch

@TimSchoch Bạn chỉ có thể làm !!MESSAGE_TYPE[type]để kiểm tra nếu một giá trị tồn tại. MESSAGE_TYPE[type]sẽ trả về không xác định nếu giá trị của typekhông tồn tại vàoMESSAGE_TYPE
Kevin Babcock

1
@Kevin Babcock Điều đó sẽ thất bại với một trong những bản đồ giá trị enum 0.
Ingo Bürk

@Ingo Bürk Điểm tuyệt vời! Tôi đoán một kiểm tra rõ ràng có thể được thực hiệnMESSAGE_TYPE[type] !== undefined
Kevin Babcock

Câu trả lời:


211

Nếu bạn muốn điều này hoạt động với enum chuỗi, bạn cần sử dụng Object.values(ENUM).includes(ENUM.value)vì enum chuỗi không được ánh xạ ngược, theo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html :

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

trở thành:

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

Vì vậy, bạn chỉ cần làm:

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

Nếu bạn gặp lỗi cho : Property 'values' does not exist on type 'ObjectConstructor', thì bạn không nhắm mục tiêu ES2017. Bạn có thể sử dụng cấu hình tsconfig.json này:

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

Hoặc bạn có thể thực hiện bất kỳ diễn viên nào:

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

7
JSONLint đang hiển thị Property 'values' does not exist on type 'ObjectConstructor'.
BBaysinger

5
@BBaysinger trong bản đánh máy hãy thử điều này thay vào đó:(<any>Object).values(Vehicle).includes(Vehicle.car)
Salem Ouerdani

1
Thông minh. Đây phải là câu trả lời được chấp nhận. Câu trả lời được chấp nhận sẽ không hoạt động nếu các khóa và giá trị enum của tôi khác nhau
Pratap AK

2
Điều này không hoạt động trong bản thảo. Ngoài ra, công việc xoay quanh các lần nghỉ được cung cấp trong IE
Jerin Joseph

3
Tôi tin rằng đây không phải là một câu trả lời cho câu hỏi này. Giải pháp của bạn (Object.values(Vehicle).includes(Vehicle.car))sẽ luôn đúng, nhưng câu hỏi là làm thế nào kiểm tra xem giá trị đã cho có được bao gồm trong enum hay không, ví dụ (Object.values(Vehicle).includes('car'))sẽ trả về truenhưng (Object.values(Vehicle).includes('plane'))sẽ trả về false.
tommybernaciak

140

Nếu bạn đang sử dụng TypeScript, bạn có thể sử dụng một enum thực tế . Sau đó, bạn có thể kiểm tra nó bằng cách sử dụng in.

Điều này chỉ hoạt động nếu enum của bạn dựa trên số và không được đánh dấu const:

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

var type = 3;

if (type in MESSAGE_TYPE) {

}

Điều này hoạt động bởi vì khi bạn biên dịch enum ở trên, nó sẽ tạo ra đối tượng bên dưới:

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

Điều này chỉ hoạt động với enums thích hợp, phải không? hiện tại nó được định nghĩa như sau:export const MESSAGE_TYPE = { ... }
Tim Schoch

Đúng. Chỉ với enums thích hợp.
Saravana

ok, cảm ơn đã giải thích. Tôi sẽ kiểm tra lý do tại sao chúng tôi không sử dụng một enum thích hợp và xem liệu chúng tôi có thể thay đổi nó không.
Tim Schoch

Chúng tôi đã thay đổi MESSAGE_TYPEthành một enum thực tế như bạn đề xuất và bây giờ giải pháp của bạn hoạt động như một cơ duyên. Cảm ơn @Saravana
Tim Schoch

71
Đây không phải làm việc với enums chuỗi bởi vì họ không được ánh xạ ngược lại: 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
Tôi thích điều này nhất
Ashley Coolman

3
Vì vậy, ví dụ này chỉ sử dụng key == value và đó là lý do nó hoạt động, phải không? Nếu khóa! = Value, nó sẽ kiểm tra theo khóa.
Konstantin Pelepelin

13
Trên thực tế trường hợp này chỉ hoạt động vì một sự trùng hợp. 'enum1' sẽ chỉ được tìm thấy vì nó có cùng giá trị với khóa. Nhưng nếu các khóa khác với các giá trị thì nó không hoạt động.
lukas_o

3
@lukas_o nói đúng về điều đó. Giải pháp này thoạt nhìn có vẻ rõ ràng nhưng nó chắc chắn dễ bị lỗi.
piotros

14

Có một giải pháp rất đơn giản và dễ dàng cho câu hỏi của bạn:

var districtId = 210;

if (DistrictsEnum[districtId] != null) {

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

Cảm ơn bạn Ester cho câu trả lời của bạn. Vì tôi đã chuyển từ lập trình sang Thiết kế UX toàn thời gian, tôi không thể xác minh điều này nữa. @crowd, hãy cho tôi biết nếu tôi câu trả lời được chấp nhận vẫn là con đường để đi vào năm 2019! Chúc mừng
Tim Schoch

2
@TimSchoch Tôi có thể xác nhận điều này hoạt động rất tốt ít nhất là đối với các số điện thoại. Đây là giải pháp thanh lịch nhất imho.
Patrick P.

@PatrickP. bạn có thể xác nhận rằng giải pháp được đề xuất bởi Ester cũng hoạt động cho enum chuỗi không?
Tim Schoch

1
@TimSchoch Vâng! Nó hoạt động cho chuỗi quá. như một từ điển - bạn có thể sử dụng bất kỳ loại nào cho các phím trong từ điển.
Ester Kaufman

9
Lưu ý rằng điều này KHÔNG hoạt động đối với enum chuỗi nếu enum sử dụng bộ khởi tạo chuỗi với các giá trị khác với tên thành viên enum. Xem câu trả lời của @ Xiv bên dưới: stackoverflow.com/a/47755096/4752920
kcstricks

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

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

Kết quả khác biệt trong nhật ký:

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

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

Giải pháp, chúng ta cần xóa khóa dưới dạng số.

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

Sử dụng

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