Mr Josselin A - TypeScript









Enums

Références

L'actualité

Librairie

L'information

Introduction

Les énumérations nous permettent de définir un ensemble de constantes nommées. L'utilisation de enums peut faciliter la documentation de l'intention ou la création d'un ensemble de cas distincts. TypeScript fournit à la fois des énumérations numériques et des énumérations basées sur des chaînes.

Enums numériques

Nous commencerons par les énumérations numériques, qui sont probablement plus familières si vous venez d'autres langagues. Une énumération peut être définie à l'aide du mot clé enum.

Ci-dessus, nous avons un enum numérique où Up est initialisé avec 1. Tous les membres suivants sont auto-incrémentés à partir de ce moment. En d'autres termes, Direction.Up a la valeur 1, Down a 2, Left a 3 et Right a 4.

Si nous le voulions, nous pourrions laisser complètement les initialiseurs :

Ici, Up aurait la valeur 0, Down aurait 1, etc... Ce comportement d'auto-incrémentation est utile dans les cas où nous ne nous soucions peut-être pas des valeurs de membre elles-mêmes, mais que chaque valeur soit distincte des autres valeurs du même enum.

Utiliser une énumération est simple: il suffit d'accéder à un membre en tant que propriété de l'énumération elle-même et de déclarer les types à l'aide du nom de l'énumération :

Les énumérations numériques peuvent être mélangées dans des membres calculés et constants (voir ci-dessous). En résumé, les énumérations sans initialiseurs doivent être les premières ou celles qui suivent les énumérations numériques initialisées avec des constantes numériques ou d'autres membres d'énumérations constantes. En d'autres termes, les opérations suivantes ne sont pas autorisées :


Enums de chaîne

Les énumérations de chaînes correspondent à un concept similaire, mais présentent quelques différences d'exécution subtiles, décrites ci-dessous. Dans une énumération de chaîne, chaque membre doit être initialisé de manière constante avec un littéral de chaîne ou avec un autre membre d'énumération de chaîne.

Bien que les énumérations de chaîne n'aient pas de comportement d'incrémentation automatique, elles ont l'avantage de bien "sérialiser". En d'autres termes, si vous étiez en train de déboguer et que vous deviez lire la valeur d'exécution d'une énumération numérique, cette valeur est souvent opaque - elle ne transmet aucune signification utile en soi (bien que le mappage inverse puisse souvent aider), les énumérations de chaîne vous permettent pour donner une valeur explicite et lisible lorsque votre code est exécuté, indépendamment du nom du membre enum lui-même.

Enums hétérogènes

Techniquement, les énumérations peuvent être mélangées avec des membres de chaîne et des membres numériques, mais il n'est pas clair pourquoi vous voudriez le faire :

Sauf si vous essayez vraiment de tirer parti du comportement d'exécution de JavaScript de manière intelligente, il est conseillé de ne pas le faire.

Membres calculés et constants

Chaque membre enum est associé à une valeur qui peut être constante ou calculée. Un membre enum est considéré comme constant si :

C'est le premier membre de l'énumération et il ne possède pas d'initialiseur, auquel cas la valeur lui est attribuée 0 :

Il n'a pas d'initialiseur et le membre enum précédent était une constante numérique. Dans ce cas, la valeur du membre enum actuel sera la valeur du membre enum précédent plus un.

Le membre enum est initialisé avec une expression enum constante. Une expression constante enum est un sous-ensemble d'expressions TypeScript qui peuvent être entièrement évaluées lors de la compilation. Une expression est une expression constante enum si elle est :

  • une expression d'énumération littérale (fondamentalement une chaîne de caractères ou une valeur numérique)
  • une référence à un membre énuméré constant défini précédemment (qui peut provenir d'une énumération différente).
  • une expression constante énumérée entre parenthèses
  • l'un des opérateur unaire +, -, ~ appliqué à l' expression de la constante enum
  • +, -, *, /, %, <<, >>, >>>, &, |, ^ Opérateurs binaires avec des expressions enum constantes comme opérandes. Il est une erreur de compilation pour les expressions ENUM constantes à évaluer à NaNou Infinity.

Dans tous les autres cas, le membre enum est considéré comme calculé.


Enums Union et types de membres enum

Il existe un sous-ensemble spécial de membres enum constant qui ne sont pas calculés : les membres enum littéraux. Un membre enum littéral est un membre enum constant sans valeur initialisée ou avec des valeurs initialisées à

  • toute chaîne de caractères (par exemple "foo", "bar", "baz")
  • tout littéral numérique (par exemple 1, 100)
  • un moins (-) unaire appliqué à n'importe quel littéral numérique (par exemple -1, -100)
Lorsque tous les membres d'une énumération ont des valeurs d'énumération littérales, une sémantique spéciale s'impose.

La première est que les membres de enum deviennent aussi des types ! Par exemple, nous pouvons dire que certains membres ne peuvent avoir la valeur d'un membre enum :

L'autre changement est que les types enum eux-mêmes deviennent effectivement une union de chaque membre enum. Bien que nous n'ayons pas encore discuté des types d'union , tout ce que vous devez savoir, c'est qu'avec les énumérations d'unions, le système de types est capable de tirer parti du fait qu'il connaît le jeu exact de valeurs qui existent dans le enum. à cause de cela, TypeScript peut attraper des bugs stupides où nous pourrions être en train de comparer des valeurs de manière incorrecte.

Par exemple :

Dans cet exemple, nous avons d'abord vérifié si ce x n'était pas le cas E.Foo. Si cette vérification réussit, nous allons court-circuiter || et le corps du "si" sera exécuté. Cependant, si la vérification échoue, x ne peut en être E.Foo ainsi, il n'a donc aucun sens de savoir si elle est égale à E.Bar.

Enums à l'exécution

Les énumérations sont des objets réels qui existent au moment de l'exécution.
Par exemple, l'énumération suivante

Peut effectivement être passé aux fonctions


Mappages inverses

En plus de créer un objet avec des noms de propriété pour les membres, les membres numériques obtiennent également un mappage inverse des valeurs enum en noms de enum.

Par exemple, dans cet exemple :

TypeScript pourrait compiler ceci en quelque chose comme le JavaScript suivant :

Dans ce code généré, une énumération est compilée dans un objet qui stocke les mappages avant (name-> value) et inverses (value-> name). Les références à d'autres membres de l'énumération sont toujours émises en tant qu'accès à la propriété et ne sont jamais alignées.

Gardez à l'esprit que les membres de String enum ne reçoivent pas du tout de mappage inverse.


const enum

Dans la plupart des cas, les enum sont une solution parfaitement valable. Cependant, les exigences sont parfois plus strictes. Pour éviter de payer le coût supplémentaire de code généré et d'indirection supplémentaire lors de l'accès à des valeurs enum, il est possible d'utiliser des énumérations const. Les énumérations constantes sont définies à l'aide du modificateur const de nos énumérations :

Les énumérations constantes ne peuvent utiliser que des expressions constantes et, contrairement aux énumérations classiques, elles sont complètement supprimées lors de la compilation. Les membres de const enum sont en ligne sur les sites d'utilisation. Cela est possible car les énumérations constantes ne peuvent pas avoir de membres calculés.

Le code généré deviendra


Enums ambiants

Les énumérations ambiantes sont utilisées pour décrire la forme des types d'énumération déjà existants.
Une différence importante entre les énumérations ambiantes et non ambiantes réside dans le fait que, dans les énumérations régulières, les membres qui ne possèdent pas d'initialiseur seront considérés comme constants si le membre de enum précédent est considéré comme constant. En revanche, un membre enum ambiant (et non-const) qui ne possède pas d'initialiseur est toujours considéré comme étant calculé.