Periksa apakah ada nilai di enum di TypeScript

163

Saya menerima nomor type = 3dan harus memeriksa apakah ada di enum ini:

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

Cara terbaik yang saya temukan adalah dengan mendapatkan semua Nilai Enum sebagai array dan menggunakan indexOf di atasnya. Tetapi kode yang dihasilkan tidak terlalu terbaca:

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

Apakah ada cara yang lebih sederhana untuk melakukan ini?

Tim Schoch
sumber
if(Object.values(MESSAGE_TYPE).includes(+type)? Tidak banyak yang bisa Anda lakukan.
Andrew Li
1
Ini bekerja di ES6 tetapi tidak di ES5 sayangnya
Tim Schoch
@TimSchoch Anda hanya dapat melakukan !!MESSAGE_TYPE[type]untuk memeriksa apakah ada nilai. MESSAGE_TYPE[type]akan kembali tidak terdefinisi jika nilai typetidak ada padaMESSAGE_TYPE
Kevin Babcock
1
@Kevin Babcock Itu akan gagal dari salah satu peta nilai enum untuk 0, meskipun.
Ingo Bürk
@Ingo Bürk Poin bagus! Saya kira pemeriksaan eksplisit dapat dilakukanMESSAGE_TYPE[type] !== undefined
Kevin Babcock

Jawaban:

213

Jika Anda ingin ini berfungsi dengan string enums, Anda perlu menggunakan Object.values(ENUM).includes(ENUM.value)karena string enums tidak dipetakan secara terbalik, menurut https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html :

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

menjadi:

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

Jadi, Anda hanya perlu melakukan:

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

Jika Anda mendapatkan kesalahan untuk Property 'values' does not exist on type 'ObjectConstructor':, maka Anda tidak menargetkan ES2017. Anda dapat menggunakan konfigurasi tsconfig.json ini:

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

Atau Anda bisa melakukan pemeran:

if ((<any>Object).values(Vehicle).includes('car')) {
    // Do stuff here
}
Xiv
sumber
7
JSONLint ditampilkan Property 'values' does not exist on type 'ObjectConstructor'.
BBaysinger
5
@BBaysinger dalam naskah coba ini sebagai gantinya:(<any>Object).values(Vehicle).includes(Vehicle.car)
Salem Ouerdani
1
Luar biasa. Ini harus menjadi jawaban yang diterima. Jawaban yang diterima tidak akan berfungsi jika kunci dan nilai enum saya berbeda
Pratap AK
2
Ini tidak berfungsi dalam naskah. Juga pekerjaan di sekitar memberikan istirahat di IE
Jerin Joseph
3
Saya percaya bahwa ini bukan jawaban untuk pertanyaan ini. Solusi Anda (Object.values(Vehicle).includes(Vehicle.car))akan selalu benar, tetapi pertanyaannya adalah bagaimana memeriksa bahwa nilai yang diberikan termasuk dalam enum, misalnya (Object.values(Vehicle).includes('car'))harus kembali truetetapi (Object.values(Vehicle).includes('plane'))harus kembali salah.
tommybernaciak
140

Jika Anda menggunakan TypeScript, Anda dapat menggunakan enum yang sebenarnya . Kemudian Anda bisa memeriksanya menggunakan in.

Ini hanya berfungsi jika enum Anda berbasis angka dan tidak ditandai const:

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

var type = 3;

if (type in MESSAGE_TYPE) {

}

Ini berfungsi karena ketika Anda mengkompilasi enum di atas, ia menghasilkan objek di bawah ini:

{
    '1': 'INFO',
    '2': 'SUCCESS',
    '3': 'WARNING',
    '4': 'ERROR',
    INFO: 1,
    SUCCESS: 2,
    WARNING: 3,
    ERROR: 4
}
Saravana
sumber
ini hanya bekerja dengan enum yang tepat, bukan? saat ini didefinisikan sebagai berikut:export const MESSAGE_TYPE = { ... }
Tim Schoch
Iya. Hanya dengan enum yang tepat.
Saravana
ok terima kasih untuk penjelasannya. Saya akan memeriksa mengapa kita tidak menggunakan enum yang tepat dan melihat apakah kita dapat mengubahnya.
Tim Schoch
Kami mengubah MESSAGE_TYPEke enum yang sebenarnya seperti yang Anda sarankan dan sekarang solusi Anda bekerja seperti pesona. Terima kasih @Saravana
Tim Schoch
71
Ini tidak berfungsi dengan string enums karena mereka tidak dipetakan secara terbalik: typescriptlang.org/docs/handbook/release-notes/…
Xiv
19

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');
}
Jayson SA
sumber
3
Saya paling suka ini
Ashley Coolman
3
Jadi contoh ini hanya menggunakan kunci == nilai dan itulah alasan kerjanya, kan? Jika kunci! = Nilai, itu akan memeriksa dengan kunci.
Konstantin Pelepelin
14
Sebenarnya kasus ini hanya berfungsi karena kebetulan. 'enum1' hanya akan ditemukan karena nilainya sama dengan kunci. Tetapi jika kunci berbeda dari nilai-nilai itu tidak berfungsi.
lukas_o
3
@lukas_o benar tentang itu. Solusi ini terlihat jelas pada pandangan pertama tetapi pasti rawan bug.
piotros
14

Ada solusi yang sangat sederhana dan mudah untuk pertanyaan Anda:

var districtId = 210;

if (DistrictsEnum[districtId] != null) {

// Returns 'undefined' if the districtId not exists in the DistrictsEnum 
    model.handlingDistrictId = districtId;
}
Ester Kaufman
sumber
Terima kasih Ester atas jawaban Anda. Karena saya sudah pindah dari pemrograman ke Desain UX penuh waktu saya tidak bisa memverifikasi ini lagi. @crowd, beri tahu saya jika saya menerima jawaban yang masih jalan pada tahun 2019! Cheers
Tim Schoch
2
@TimSchoch Saya dapat mengkonfirmasi ini berfungsi dengan baik setidaknya untuk enum numerik. Ini adalah solusi imho paling elegan.
Patrick P.
@ PatrickP. dapatkah Anda mengkonfirmasi bahwa solusi yang diusulkan oleh Ester juga berfungsi untuk enum string?
Tim Schoch
1
@TimSchoch Ya! Ini juga berfungsi untuk string. seperti Kamus - Anda dapat menggunakan jenis apa saja untuk tombol-tombol dalam kamus.
Ester Kaufman
9
Perhatikan bahwa ini TIDAK berfungsi untuk string enum jika enum menggunakan inisialisasi string dengan nilai yang berbeda dari nama anggota enum. Lihat jawaban @ Xiv di bawah ini: stackoverflow.com/a/47755096/4752920
kcstricks
5
export enum UserLevel {
  Staff = 0,
  Leader,
  Manager,
}

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

Hasil perbedaan dalam log:

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

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

Solusinya, kita perlu menghapus kunci sebagai angka.

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

Pemakaian

// 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
}
Nhan Cao
sumber
0

Sesuai jawaban Ryan Cavanaugh , Anda cukup melakukan hal berikut untuk memeriksa apakah suatu nilai terkandung dalam enum yang diberikan:

if ('value4' in someEnum) {
  // ...
}
A. Maitre
sumber