Comment comparer les énumérations Dans TypeScript

Dans TypeScript, je veux comparer deux variables contenant des valeurs enum. Voici mon exemple de code minimal:

enum E {
  A,
  B
}

let e1: E = E.A
let e2: E = E.B

if (e1 === e2) {
  console.log("equal")
}

Lors de la compilation avec tsc (v 2.0.3) j'obtiens l'erreur suivante:

TS2365: L'opérateur '= = = 'ne peut pas être appliqué aux types 'E. A' et 'E. B'.

Même avec ==, !== et !=. J'ai essayé d'ajouter le mot-clé const mais cela semble n'avoir aucun effet. La spécification TypeScript indique ce qui suit:

4.19.3 le, =, ==, != , = = = et !== les opérateurs

Ces opérateurs exigent que l'un ou les deux types d'opérandes soient assignables à l'autre. Le résultat est toujours du type booléen primitif.

Ce qui (je pense) explique l'erreur. Mais comment puis-je obtenir autour d'elle?

Note de Côté
J'utilise L'éditeur Atom avec atom-typescript , et je ne reçois aucune erreur / avertissement dans mon éditeur. Mais quand je cours tsc dans le même répertoire, j'obtiens l'erreur ci-dessus. Je pensais qu'ils étaient censés utiliser le même tsconfig.json fichier, mais apparemment ce n'est pas le cas.

29
demandé sur John J. Camilleri 2016-09-30 09:47:36

6 réponses

Il y a une autre façon: si vous ne voulez pas que le code javascript généré soit affecté de quelque manière que ce soit, vous pouvez utiliser type cast:

let e1: E = E.A
let e2: E = E.B


if (e1 as E === e2 as E) {
  console.log("equal")
}

En général, ceci est causé par l'inférence de type basée sur le flux de contrôle. Avec l'implémentation typescript actuelle, il est désactivé chaque fois que l'appel de fonction est impliqué, donc vous pouvez également faire ceci:

let id = a => a

let e1: E = id(E.A)
let e2: E = id(E.B)

if (e1 === e2) {
  console.log('equal');
}

La chose étrange est qu'il n'y a toujours pas d'erreur si la fonction id est déclarée pour renvoyer précisément le même type que son agument:

function id<T>(t: T): T { return t; }
10
répondu artem 2016-09-30 17:36:31

Eh bien, je pense que j'ai trouvé quelque chose qui fonctionne:

if (e1.valueOf() === e2.valueOf()) {
  console.log("equal")
}

Mais je suis un peu surpris que cela ne soit mentionné nulle part dans la documentation.

9
répondu John J. Camilleri 2016-09-30 06:56:20

Si était capable de comparer deux énumérations avec ceci

 if (product.ProductType && 
       (product.ProductType.toString() == ProductTypes[ProductTypes.Merchandises])) {
      // yes this item is of merchandises
  } 

Avec ProductTypes étant ceci export enum ProductTypes{Merchandises,Goods,...}

3
répondu Bellash 2018-01-18 13:44:12

La seule chose qui a fonctionné pour moi (dans typescript 2.2.1) était la suivante:

if (E[e1] === E[e2]) {
  console.log("equal")
}

Cela compare les chaînes représentant les noms (par exemple. "A" et "B").

2
répondu Russ 2017-03-26 04:24:50

Dans mon cas, aucune des solutions ci-dessus n'a fonctionné, la raison en était que je convertissais la valeur enum à l'objet enum.

Après cela, j'essayais de savoir si l'enum était équivalent à un autre objet enum... j'ai donc créé les fonctionsgénériques suivantes:

  public static enumEquals<T>(e: any, e1: T, e2: T): boolean {
    const v1 = this.enumValue(e, e1);
    return v1 === this.enumValue(e, e2, typeof v1);
  }

  private static enumValue<T>(enumType: any, value: T, validType?: string) {
    let v = enumType[value];
    if (!validType) {
      return v;
    }
    while (typeof v !== validType) {
      v = enumType[v];
    }
    return v;
  }

Ceci est un exemple de mon cas de test:

enum SomeEnum {
  VALUE1, VALUE2, VALUE3, VALUE_DEF
}

const enumRefKey = localStorage.getItem('someKey');
const parsedEnum = SomeEnum[enumRefKey] || SomeEnum.VALUE_DEF;
console.log(parsedEnum);
if (parsedEnum === SomeEnum.VALUE_DEF) {
  // do stuff
}

Évidemment, ce code n'a pas fonctionné, après avoir essayé les solutions données ici à cette question, j'ai trouvé que lorsque enumRefKey est valide console.log(parsedenum) imprimait des nombres et le texte value_def quand n'est pas. Le même résultat s'est produit en utilisant toutes les autres solutions:

  • parsedEnum comme SomeEnum
  • parsedEnum.valueOf ()
  • SomeEnum[parsedEnum]

La solution en utilisant les méthodes génériques ressemble à ceci:

enum SomeEnum {
  VALUE1, VALUE2, VALUE3, VALUE_DEF
}

const enumRefKey = localStorage.getItem('someKey');
const parsedEnum = SomeEnum[enumRefKey] || SomeEnum.VALUE_DEF;
console.log(parsedEnum);
if (this.enumEquals(SomeEnum, parsedEnum, SomeEnum.VALUE_DEF) {
  // do stuff
}

J'espère que cela aide quelqu'un.

0
répondu Lu15 2018-08-24 22:38:43

L'erreur est levée car le compilateur se rend compte que l'instruction est toujours fausse et donc redondante. Vous déclarez deux variables qui ne sont clairement pas égales, puis essayez de voir si elles sont égales.

Si vous le changez par exemple:

enum E {
  A,
  B
}

foo() {
  let e1: E = E.A
  let e2: E
  e2 = foo();

  if (e1 === e2) {
    console.log("equal")
  }
}

bar(): E {
  return E.B
}

, Il devrait compiler sans erreur.

Sur une note, les géohelminthiases. comme

let e1 = E.A;
if (e1 && e1 === E.B) {
  ...
}

Ne compilerait pas non plus, comme e1 dans ce cas est 0 (comme A est la première enum 'option') et donc {[4] } ce qui signifie que le un deuxième État ne serait jamais atteint (sans tenir compte du fait que la deuxième déclaration serait même valide dans ce cas)

0
répondu seBaka28 2018-09-28 10:12:45