Überprüfen Sie, ob in TypeScript ein Wert in enum vorhanden ist

162

Ich erhalte eine Nummer type = 3und muss überprüfen, ob sie in dieser Aufzählung vorhanden ist:

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

Der beste Weg, den ich gefunden habe, besteht darin, alle Enum-Werte als Array abzurufen und indexOf darauf zu verwenden. Der resultierende Code ist jedoch nicht gut lesbar:

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

Gibt es einen einfacheren Weg, dies zu tun?

Tim Schoch
quelle
if(Object.values(MESSAGE_TYPE).includes(+type)? Sie können nicht viel tun.
Andrew Li
1
Dies funktioniert in ES6, aber leider nicht in ES5
Tim Schoch
@ TimSchoch Sie können nur !!MESSAGE_TYPE[type]überprüfen, ob ein Wert vorhanden ist. MESSAGE_TYPE[type]wird undefiniert zurückgeben, wenn der Wert von typenicht existiert amMESSAGE_TYPE
Kevin Babcock
1
@ Kevin Babcock Das wird allerdings bei einer der Aufzählungswerte fehlschlagen 0.
Ingo Bürk
@Ingo Bürk Toller Punkt! Ich denke, eine explizite Überprüfung könnte gemacht werdenMESSAGE_TYPE[type] !== undefined
Kevin Babcock

Antworten:

211

Wenn Sie möchten, dass dies mit Zeichenfolgenaufzählungen funktioniert, müssen Sie diese verwenden, Object.values(ENUM).includes(ENUM.value)da Zeichenfolgenaufzählungen laut https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html nicht umgekehrt zugeordnet sind :

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

wird:

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

Sie müssen also nur Folgendes tun:

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

Wenn Sie eine Fehlermeldung für: erhalten Property 'values' does not exist on type 'ObjectConstructor', zielen Sie nicht auf ES2017. Sie können entweder diese tsconfig.json-Konfiguration verwenden:

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

Oder du kannst einfach eine beliebige Besetzung machen:

if ((<any>Object).values(Vehicle).includes('car')) {
    // Do stuff here
}
Xiv
quelle
7
JSONLint wird angezeigt Property 'values' does not exist on type 'ObjectConstructor'.
BBaysinger
5
@BBaysinger in Typoskript versuchen Sie stattdessen:(<any>Object).values(Vehicle).includes(Vehicle.car)
Salem Ouerdani
1
Ausgezeichnet. Dies sollte die akzeptierte Antwort sein. Akzeptierte Antwort funktioniert nicht, wenn meine Enum-Schlüssel und Werte unterschiedlich sind
Pratap AK
2
Dies funktioniert nicht in Typoskript. Auch die Arbeit rund um Pausen in IE
Jerin Joseph
3
Ich glaube, dass dies keine Antwort auf diese Frage ist. Ihre Lösung (Object.values(Vehicle).includes(Vehicle.car))wird immer wahr sein, aber die Frage ist, wie überprüft werden soll, ob ein bestimmter Wert in enum enthalten ist, z. B. (Object.values(Vehicle).includes('car'))sollte return, trueaber (Object.values(Vehicle).includes('plane'))false zurückgeben.
Tommybernaciak
140

Wenn Sie TypeScript verwenden, können Sie eine tatsächliche Aufzählung verwenden . Dann können Sie es mit überprüfen in.

Dies funktioniert nur, wenn Ihre Aufzählung nummeriert und nicht markiert ist const:

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

var type = 3;

if (type in MESSAGE_TYPE) {

}

Dies funktioniert, weil beim Kompilieren der obigen Aufzählung das folgende Objekt generiert wird:

{
    '1': 'INFO',
    '2': 'SUCCESS',
    '3': 'WARNING',
    '4': 'ERROR',
    INFO: 1,
    SUCCESS: 2,
    WARNING: 3,
    ERROR: 4
}
Saravana
quelle
Das funktioniert nur mit richtigen Aufzählungen, oder? Derzeit ist es als solches definiert:export const MESSAGE_TYPE = { ... }
Tim Schoch
Ja. Nur mit richtigen Aufzählungen.
Saravana
ok, danke für die erklärung. Ich werde prüfen, warum wir keine richtige Aufzählung verwenden und ob wir sie ändern können.
Tim Schoch
Wir haben MESSAGE_TYPEzu einer tatsächlichen Aufzählung gewechselt , wie Sie vorgeschlagen haben, und jetzt funktioniert Ihre Lösung wie ein Zauber. Danke @Saravana
Tim Schoch
71
Das funktioniert nicht mit String Aufzählungen , weil sie nicht umgekehrt abgebildet werden: 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
quelle
3
Ich mag das am meisten
Ashley Coolman
3
In diesem Beispiel wird also nur key == value verwendet, und das ist der Grund, warum es funktioniert, oder? Wenn key! = Value, wird nach Schlüssel geprüft.
Konstantin Pelepelin
13
Eigentlich funktioniert dieser Fall nur aufgrund eines Zufalls. 'enum1' wird nur gefunden, weil es der gleiche Wert wie der Schlüssel ist. Wenn sich die Schlüssel jedoch von den Werten unterscheiden, funktioniert dies nicht.
lukas_o
3
@lukas_o hat damit recht. Diese Lösung sieht auf den ersten Blick klar aus, ist aber definitiv fehleranfällig.
Piotros
14

Es gibt eine sehr einfache und einfache Lösung für Ihre Frage:

var districtId = 210;

if (DistrictsEnum[districtId] != null) {

// Returns 'undefined' if the districtId not exists in the DistrictsEnum 
    model.handlingDistrictId = districtId;
}
Ester Kaufman
quelle
Danke Ester für deine Antwort. Seit ich von der Programmierung zum Vollzeit-UX-Design gewechselt bin, kann ich dies nicht mehr überprüfen. @crowd, lass es mich wissen, wenn ich die akzeptierte Antwort für 2019 noch habe! Prost
Tim Schoch
2
@ TimSchoch Ich kann bestätigen, dass dies zumindest für numerische Aufzählungen sehr gut funktioniert. Dies ist imho die eleganteste Lösung.
Patrick P.
@PatrickP. Können Sie bestätigen, dass die von Ester vorgeschlagene Lösung auch für String-Enums funktioniert?
Tim Schoch
1
@ TimSchoch Ja! Es funktioniert auch für Strings. wie ein Wörterbuch - Sie können einen beliebigen Typ für die Schlüssel im Wörterbuch verwenden.
Ester Kaufman
9
Beachten Sie, dass dies NICHT für Zeichenfolgenaufzählungen funktioniert, wenn die Aufzählung Zeichenfolgeninitialisierer mit anderen Werten als den Namen der Aufzählungsmitglieder verwendet. Siehe @ Xivs Antwort unten: stackoverflow.com/a/47755096/4752920
kcstricks
5
export enum UserLevel {
  Staff = 0,
  Leader,
  Manager,
}

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

Differenz Ergebnis im Protokoll:

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

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

Als Lösung müssen wir den Schlüssel als Zahl entfernen.

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

Verwendung

// 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
quelle