web-dev-qa-db-fra.com

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), l'erreur suivante apparaît:

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

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

4.19.3 Les opérateurs <,>, <=,> =, ==,! =, === et! ==

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 primitif booléen.

Ce qui (je pense) explique l'erreur. Mais comment puis-je le contourner?

Note latérale
J'utilise l'éditeur Atom avec atom-TypeScript , et je ne reçois aucune erreur ni aucun avertissement dans mon éditeur. Mais lorsque je lance tsc dans le même répertoire, l'erreur ci-dessus apparaît. Je pensais qu'ils étaient supposés utiliser le même fichier tsconfig.json, mais apparemment, ce n'est pas le cas.

32
John J. Camilleri

Il existe un autre moyen: si vous ne souhaitez pas que le code javascript généré soit affecté, vous pouvez utiliser le transtypage:

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


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

En général, cela est causé par l'inférence de type basée sur le flux de contrôle. Avec l'implémentation actuelle de TypeScript, il est désactivé chaque fois qu'un appel de fonction est impliqué. Vous pouvez donc également effectuer les opérations suivantes:

let id = a => a

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

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

Ce qui est étrange, c'est qu'il n'y a toujours pas d'erreur si la fonction id est déclarée pour renvoyer exactement le même type que son agument:

function id<T>(t: T): T { return t; }
11
artem

Eh bien, je pense avoir 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
John J. Camilleri

Si était capable de comparer deux enums avec cette

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

avec ProductTypes étant ce export enum ProductTypes{Merchandises,Goods,...}

3
Bellash

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

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

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

2
Russ

Je définirais des valeurs pour Enum comme ceci et les comparerais avec ===

const enum AnimalInfo {
Tiger = "Tiger",
Lion = "Lion"
}

let tigerStr = "Tiger";

if (tigerStr === AnimalInfo.Tiger) {
  console.log('true');
} else {
  console.log('false');
}
1
sendon1982

Dans mon cas, aucune des solutions ci-dessus ne fonctionnait, la raison en était que je transmettais la valeur enum à l'objet enum.

Après cela, j’essayais de savoir si l’énumération était équivalente à un autre objet enum ... alors j’ai créé les fonctions generic 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;
  }

Voici 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, j'ai constaté que lorsque enumRefKey est valide console.log (parsedEnum) imprimait des nombres et le texte VALUE_DEF alors que non. Le même résultat est obtenu en utilisant toutes les autres solutions: 

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

La solution 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
Luis Limas

Dans TypeScript un exemple enum:

enum Example {
   type1,
   type2
};

est transformé en javascript dans cet objet:

Example {
    '0': 'type1', 'type1': 0,
    '1': 'type2', 'type2': 1
}

J'ai eu beaucoup de problèmes avec les énumérations de comparaison dans TypeScript. Ce script simple résout le problème:

enum Example {
    type1 = 'type1',
    type2 = 'type2'
};

puis en javascript, l'objet est transformé en:

Example {
    'type1': 'type1',
    'type2': 'type2'
}

Si vous n'avez pas besoin d'utiliser d'énums, mieux vaut ne pas utiliser. TypeScript a des types plus avancés, plus ici: https://www.typescriptlang.org/docs/handbook/advanced-types.html Vous pouvez utiliser à la place:

type Example = 'type1' | 'type2';
0
W92

L'erreur est renvoyée car le compilateur réalise que la déclaration est toujours fausse et donc redondante. Vous déclarez deux variables qui ne sont clairement pas égales, puis vous 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 un sidenote, qc comme 

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

ne compilerait pas non plus, car e1 est dans ce cas 0 (car A est le premier enum 'option') et donc false, ce qui signifie que le deuxième état ne sera jamais atteint (indépendamment de la validité de la deuxième instruction 

0
seBaka28