web-dev-qa-db-fra.com

Créer une énumération avec des valeurs de chaîne

Le code suivant peut être utilisé pour créer une enum dans TypeScript:

enum e {
    hello = 1,
    world = 2
};

Et les valeurs peuvent être consultées par: 

e.hello;
e.world;

Comment créer une enum avec des valeurs de chaîne?

enum e {
    hello = "hello", // error: cannot convert string to e
    world = "world"  // error 
};
223
FacePalm

TypeScript 2.4

Maintenant, a des énumérations de chaîne pour que votre code fonctionne: 

enum E {
    hello = "hello",
    world = "world"
};

????

TypeScript 1.8

Depuis TypeScript 1.8, vous pouvez utiliser des types littéraux de chaîne pour fournir une expérience fiable et sécurisée aux valeurs de chaîne nommée (qui correspond partiellement aux énumérations utilisées). 

type Options = "hello" | "world";
var foo: Options;
foo = "hello"; // Okay 
foo = "asdf"; // Error!

Plus: https://www.typescriptlang.org/docs/handbook/advanced-types.html#string-literal-types

Support hérité

Les énumérations dans TypeScript sont basées sur des nombres. 

Vous pouvez utiliser une classe avec des membres statiques si: 

class E
{
    static hello = "hello";
    static world = "world"; 
}

Vous pouvez aussi aller en clair: 

var E = {
    hello: "hello",
    world: "world"
}

Mise à jour: Basé sur l'exigence de pouvoir faire quelque chose comme var test:E = E.hello;, ce qui suit satisfait à ceci: 

class E
{
    // boilerplate 
    constructor(public value:string){    
    }

    toString(){
        return this.value;
    }

    // values 
    static hello = new E("hello");
    static world = new E("world");
}

// Sample usage: 
var first:E = E.hello;
var second:E = E.world;
var third:E = E.hello;

console.log("First value is: "+ first);
console.log(first===third); 
347
basarat

Dans la dernière version (1.0RC) de TypeScript, vous pouvez utiliser des énumérations comme ceci:

enum States {
    New,
    Active,
    Disabled
} 

// this will show message '0' which is number representation of enum member
alert(States.Active); 

// this will show message 'Disabled' as string representation of enum member
alert(States[States.Disabled]);

Mise à jour 1

Pour obtenir la valeur numérique du membre enum à partir de la valeur de chaîne, vous pouvez utiliser ceci:

var str = "Active";
// this will show message '1'
alert(States[str]);

Mise à jour 2

Dans la dernière version de TypeScript 2.4, des énumérations de chaînes ont été introduites, comme suit:

enum ActionType {
    AddUser = "ADD_USER",
    DeleteUser = "DELETE_USER",
    RenameUser = "RENAME_USER",

    // Aliases
    RemoveUser = DeleteUser,
}

Pour plus d'informations sur TypeScript 2.4, lisez blog sur MSDN .

105
psulek

TypeScript 2.4+

Vous pouvez maintenant affecter des valeurs de chaîne directement aux membres enum:

enum Season {
    Winter = "winter",
    Spring = "spring",
    Summer = "summer",
    Fall = "fall"
}

Voir # 15486 pour plus d'informations.

TypeScript 1.8+

Dans TypeScript 1.8+, vous pouvez créer un type littéral pour définir le type et un objet du même nom pour la liste de valeurs. Il imite le comportement attendu d'un énumère de chaîne.

Voici un exemple:

type MyStringEnum = "member1" | "member2";

const MyStringEnum = {
    Member1: "member1" as MyStringEnum,
    Member2: "member2" as MyStringEnum
};

Ce qui fonctionnera comme un enum string:

// implicit typing example
let myVariable = MyStringEnum.Member1; // ok
myVariable = "member2";                // ok
myVariable = "some other value";       // error, desired

// explict typing example
let myExplicitlyTypedVariable: MyStringEnum;
myExplicitlyTypedVariable = MyStringEnum.Member1; // ok
myExplicitlyTypedVariable = "member2";            // ok
myExplicitlyTypedVariable = "some other value";   // error, desired

Assurez-vous de taper toutes les chaînes de l'objet! Sinon, dans le premier exemple ci-dessus, la variable ne serait pas implicitement typée à MyStringEnum.

77
David Sherret

Dans TypeScript 0.9.0.1, bien qu'il se produise une erreur du compilateur, le compilateur peut toujours compiler le fichier ts en fichier js. Le code fonctionne comme prévu et Visual Studio 2012 peut prendre en charge la complétion automatique du code.

Mettre à jour : 

En syntaxe, TypeScript ne nous permet pas de créer une énumération avec des valeurs de chaîne, mais nous pouvons pirater le compilateur: p

enum Link
{
    LEARN   =   <any>'/Tutorial',
    PLAY    =   <any>'/Playground',
    GET_IT  =   <any>'/#Download',
    RUN_IT  =   <any>'/Samples',
    JOIN_IN =   <any>'/#Community'
}

alert('Link.LEARN:    '                     + Link.LEARN);
alert('Link.PLAY:    '                      + Link.PLAY);
alert('Link.GET_IT:    '                    + Link.GET_IT);
alert('Link[\'/Samples\']:    Link.'        + Link['/Samples']);
alert('Link[\'/#Community\']    Link.'      + Link['/#Community']);

Cour de récréation

40
Shinoka

TypeScript 2.1 +

Les types de recherche , introduits dans TypeScript 2.1 autorisent un autre motif pour la simulation d'énums de chaînes:

// String enums in TypeScript 2.1
const EntityType = {
    Foo: 'Foo' as 'Foo',
    Bar: 'Bar' as 'Bar'
};

function doIt(entity: keyof typeof EntityType) {
    // ...
}

EntityType.Foo          // 'Foo'
doIt(EntityType.Foo);   // ????
doIt(EntityType.Bar);   // ????
doIt('Foo');            // ????
doIt('Bad');            // ???? 

TypeScript 2.4 +

Avec la version 2.4, TypeScript a introduit la prise en charge native des énumérations de chaîne, de sorte que la solution ci-dessus n'est pas nécessaire. De la documentation TS:

enum Colors {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE",
}
22
Michael Bromley

Pourquoi ne pas utiliser simplement la manière native d’accéder aux chaînes d’un enum.

enum e {
  WHY,
  NOT,
  USE,
  NATIVE
}

e[e.WHY] // this returns string 'WHY'
19
Mient-jan Stelling

Vous pouvez utiliser des énumérations de chaîne dans le dernier TypeScript:

enum e
{
    hello = <any>"hello",
    world = <any>"world"
};

Source: https://blog.rsuter.com/how-to-implement-an-enen-with-string-values-in-TypeScript/


MISE À JOUR - 2016

Voici un moyen plus robuste de créer un jeu de chaînes que j'utilise pour React:

export class Messages
{
    static CouldNotValidateRequest: string = 'There was an error validating the request';
    static PasswordMustNotBeBlank: string = 'Password must not be blank';   
}

import {Messages as msg} from '../core/messages';
console.log(msg.PasswordMustNotBeBlank);
16
Richard

Voici une solution relativement propre qui permet l’héritage, en utilisant TypeScript 2.0. Je n'ai pas essayé cela sur une version antérieure.

Bonus: la valeur peut être de type any!

export class Enum<T> {
  public constructor(public readonly value: T) {}
  public toString() {
    return this.value.toString();
  }
}

export class PrimaryColor extends Enum<string> {
  public static readonly Red = new Enum('#FF0000');
  public static readonly Green = new Enum('#00FF00');
  public static readonly Blue = new Enum('#0000FF');
}

export class Color extends PrimaryColor {
  public static readonly White = new Enum('#FFFFFF');
  public static readonly Black = new Enum('#000000');
}

// Usage:

console.log(PrimaryColor.Red);
// Output: Enum { value: '#FF0000' }
console.log(Color.Red); // inherited!
// Output: Enum { value: '#FF0000' }
console.log(Color.Red.value); // we have to call .value to get the value.
// Output: #FF0000
console.log(Color.Red.toString()); // toString() works too.
// Output: #FF0000

class Thing {
  color: Color;
}

let thing: Thing = {
  color: Color.Red,
};

switch (thing.color) {
  case Color.Red: // ...
  case Color.White: // ...
}
10
Westy92

Un moyen hacky pour cela est: -

CallStatus.ts

enum Status
{
    PENDING_SCHEDULING,
    SCHEDULED,
    CANCELLED,
    COMPLETED,
    IN_PROGRESS,
    FAILED,
    POSTPONED
}

export = Status

Utils.ts

static getEnumString(enum:any, key:any):string
{
    return enum[enum[key]];
}

Comment utiliser

Utils.getEnumString(Status, Status.COMPLETED); // = "COMPLETED"
8
nishantkyal

Cela fonctionne pour moi:

class MyClass {
    static MyEnum: { Value1; Value2; Value3; }
    = {
        Value1: "Value1",
        Value2: "Value2",
        Value3: "Value3"
    };
}

ou 

module MyModule {
    export var MyEnum: { Value1; Value2; Value3; }
    = {
        Value1: "Value1",
        Value2: "Value2",
        Value3: "Value3"
    };
}

8)

Mise à jour: Peu de temps après avoir posté ceci, j'ai découvert un autre moyen, mais j'ai oublié de poster une mise à jour (cependant, quelqu'un l'a déjà mentionné ci-dessus): 

enum MyEnum {
    value1 = <any>"value1 ", 
    value2 = <any>"value2 ", 
    value3 = <any>"value3 " 
}
7
James Wilkins

TypeScript 2.1

Cela peut aussi être fait de cette façon. J'espère que ça aidera quelqu'un.

const AwesomeType = {
    Foo: "foo" as "foo",
    Bar: "bar" as "bar"
};

type AwesomeType = (typeof AwesomeType)[keyof typeof AwesomeType];

console.log(AwesomeType.Bar); // returns bar
console.log(AwesomeType.Foo); // returns foo

function doSth(awesometype: AwesomeType) {
    console.log(awesometype);
}

doSth("foo") // return foo
doSth("bar") // returns bar
doSth(AwesomeType.Bar) // returns bar
doSth(AwesomeType.Foo) // returns foo
doSth('error') // does not compile
4
Łukasz Pniewski

Je viens de déclarer une interface et utiliser une variable de ce type pour accéder à l'énumération. Maintenir l'interface et l'énum synchronisées est en fait facile, puisque TypeScript se plaint si quelque chose change dans l'énum, ​​comme ça.

erreur TS2345: l'argument de type 'typeof EAbFlagEnum' n'est pas assignable au paramètre de type 'IAbFlagEnum'. La propriété 'Move' est manquante dans le type 'typeof EAbFlagEnum'.

L'avantage de cette méthode est qu'aucune transtypage n'est nécessaire pour utiliser l'énum (interface) dans diverses situations, et plusieurs types de situations sont donc pris en charge, tels que le commutateur/le boîtier.

// Declare a TypeScript enum using unique string 
//  (per hack mentioned by zjc0816)

enum EAbFlagEnum {
  None      = <any> "none",
  Select    = <any> "sel",
  Move      = <any> "mov",
  Edit      = <any> "edit",
  Sort      = <any> "sort",
  Clone     = <any> "clone"
}

// Create an interface that shadows the enum
//   and asserts that members are a type of any

interface IAbFlagEnum {
    None:   any;
    Select: any;
    Move:   any;
    Edit:   any;
    Sort:   any;
    Clone:  any;
}

// Export a variable of type interface that points to the enum

export var AbFlagEnum: IAbFlagEnum = EAbFlagEnum;

L'utilisation de la variable plutôt que de l'énumération produit les résultats souhaités.

var strVal: string = AbFlagEnum.Edit;

switch (strVal) {
  case AbFlagEnum.Edit:
    break;
  case AbFlagEnum.Move:
    break;
  case AbFlagEnum.Clone
}

Les indicateurs étant une autre nécessité pour moi, j'ai donc créé un module NPM qui complète cet exemple et inclut des tests.

https://github.com/djabraham/ts-enum-tools

3
djabraham

TypeScript <2.4

/** Utility function to create a K:V from a list of strings */
function strEnum<T extends string>(o: Array<T>): {[K in T]: K} {
  return o.reduce((res, key) => {
    res[key] = key;
    return res;
  }, Object.create(null));
}

/**
  * Sample create a string enum
  */

/** Create a K:V */
const Direction = strEnum([
  'North',
  'South',
  'East',
  'West'
])
/** Create a Type */
type Direction = keyof typeof Direction;

/** 
  * Sample using a string enum
  */
let sample: Direction;

sample = Direction.North; // Okay
sample = 'North'; // Okay
sample = 'AnythingElse'; // ERROR!

from https://basarat.gitbooks.io/TypeScript/docs/types/literal-types.html

Pour le lien source, vous pouvez trouver des moyens plus nombreux et plus simples d’accomplir le type littéral de chaîne.

2

Avec les transformateurs personnalisés ( https://github.com/Microsoft/TypeScript/pull/13940 ) disponibles dans TypeScript @ next, vous pouvez créer un enum comme objet avec des valeurs de chaîne provenant de types littéraux de chaîne.

Veuillez regarder dans mon paquet npm, ts-transformer-enumerate .

Exemple d'utilisation:

// The signature of `enumerate` here is `function enumerate<T extends string>(): { [K in T]: K };`
import { enumerate } from 'ts-transformer-enumerate';

type Colors = 'green' | 'yellow' | 'red';
const Colors = enumerate<Colors>();

console.log(Colors.green); // 'green'
console.log(Colors.yellow); // 'yellow'
console.log(Colors.red); // 'red'
2
kimamula

Il y a beaucoup de réponses, mais je ne vois pas de solutions complètes. Le problème avec la réponse acceptée, ainsi que enum { this, one }, est qu’il disperse la valeur de chaîne que vous utilisez par le biais de nombreux fichiers. Je n'aime pas trop la "mise à jour", elle est complexe et n'utilise pas non plus les types. Je pense que la réponse de Michael Bromley est tout à fait correcte, mais son interface est un peu compliquée et pourrait être utile avec un type.

J'utilise TypeScript 2.0. * Voici ce que je ferais

export type Greeting = "hello" | "world";
export const Greeting : { hello: Greeting , world: Greeting } = {
    hello: "hello",
    world: "world"
};

let greet: Greeting = Greeting.hello

Il contient également des informations beaucoup plus intéressantes sur le type/survol lors de l'utilisation d'un IDE utile. L'inconvénient est que vous devez écrire les chaînes deux fois, mais au moins c'est à deux endroits seulement.

2
Nathan Cooper

Face à ce problème récemment avec TypeScript 1.0.1, et résolu de cette façon:

enum IEvents {
        /** A click on a product or product link for one or more products. */
        CLICK,
        /** A view of product details. */
        DETAIL,
        /** Adding one or more products to a shopping cart. */
        ADD,
        /** Remove one or more products from a shopping cart. */
        REMOVE,
        /** Initiating the checkout process for one or more products. */
        CHECKOUT,
        /** Sending the option value for a given checkout step. */
        CHECKOUT_OPTION,
        /** The sale of one or more products. */
        PURCHASE,
        /** The refund of one or more products. */
        REFUND,
        /** A click on an internal promotion. */
        PROMO_CLICK
}

var Events = [
        'click',
        'detail',
        'add',
        'remove',
        'checkout',
        'checkout_option',
        'purchase',
        'refund',
        'promo_click'
];

function stuff(event: IEvents):boolean {
        // event can now be only IEvents constants
        Events[event]; // event is actually a number that matches the index of the array
}
// stuff('click') won't work, it needs to be called using stuff(IEvents.CLICK)
1
pocesar

La réponse de @ basarat était excellente. Voici un exemple simplifié mais un peu plus long que vous pouvez utiliser:

export type TMyEnumType = 'value1'|'value2';

export class MyEnumType {
    static VALUE1: TMyEnumType = 'value1';
    static VALUE2: TMyEnumType = 'value2';
}

console.log(MyEnumType.VALUE1); // 'value1'

const variable = MyEnumType.VALUE2; // it has the string value 'value2'

switch (variable) {
    case MyEnumType.VALUE1:
        // code...

    case MyEnumType.VALUE2:
        // code...
}
1
Manuel Fodor
//to access the enum with its string value you can convert it to object 
//then you can convert enum to object with proberty 
//for Example :

enum days { "one" =3, "tow", "Three" }

let _days: any = days;

if (_days.one == days.one)
{ 
    alert(_days.one + ' | ' + _days[4]);
}
0

Petit js-hacky mais fonctionne: e[String(e.hello)]

0
Majid Mallis

J'ai essayé dans TypeScript 1.5 comme ci-dessous et cela a fonctionné pour moi

module App.Constants {
   export enum e{
        Hello= ("Hello") as any,
World= ("World") as any
    }
}
0
Code-EZ

Je pense que vous devriez essayer avec ceci, dans ce cas, la valeur de la variable ne changera pas et cela fonctionne assez comme enums, en utilisant comme une classe, le seul inconvénient est que par erreur vous pouvez changer la valeur de variable statique nous ne voulons pas enums.

namespace portal {

export namespace storageNames {

    export const appRegistration = 'appRegistration';
    export const accessToken = 'access_token';

  }
}
0
Pranay Dutta

Très, très, très simple Enum avec chaîne (TypeScript 2.4)

import * from '../mylib'

export enum MESSAGES {
    ERROR_CHART_UNKNOWN,
    ERROR_2
}

export class Messages {
    public static get(id : MESSAGES){
        let message = ""
        switch (id) {
            case MESSAGES.ERROR_CHART_UNKNOWN :
                message = "The chart does not exist."
                break;
            case MESSAGES.ERROR_2 :
                message = "example."
                break;
        }
        return message
    }
}

function log(messageName:MESSAGES){
    console.log(Messages.get(messageName))
}
0
Karima Rafes

Si ce que vous voulez est principalement un débogage facile (avec assez de vérification de type) et qu'il n'est pas nécessaire de spécifier des valeurs spéciales pour l'énum, ​​voici ce que je fais:

export type Enum = { [index: number]: string } & { [key: string]: number } | Object;

/**
 * inplace update
 * */
export function enum_only_string<E extends Enum>(e: E) {
  Object.keys(e)
    .filter(i => Number.isFinite(+i))
    .forEach(i => {
      const s = e[i];
      e[s] = s;
      delete e[i];
    });
}

enum AuthType {
  phone, email, sms, password
}
enum_only_string(AuthType);

Si vous souhaitez prendre en charge le stockage de code/données hérité, vous pouvez conserver les clés numériques.

De cette façon, vous pouvez éviter de saisir deux fois les valeurs.

0
Beeno Tung
export enum PaymentType {
                Cash = 1,
                Credit = 2
            }
var paymentType = PaymentType[PaymentType.Cash];
0
Evon Dos

je cherchais un moyen d'implémenter les descriptions dans les énumérations TypeScript (v2.5) et ce modèle fonctionnait pour moi: 

export enum PriceTypes {
    Undefined = 0,
    UndefinedDescription = 'Undefined' as any,
    UserEntered = 1,
    UserEnteredDescription = 'User Entered' as any,
    GeneratedFromTrade = 2,
    GeneratedFromTradeDescription = 'Generated From Trade' as any,
    GeneratedFromFreeze = 3,
    GeneratedFromFreezeDescription = 'Generated Rom Freeze' as any
}

...

    GetDescription(e: any, id: number): string {
        return e[e[id].toString() + "Description"];
    }
    getPriceTypeDescription(price: IPricePoint): string {
        return this.GetDescription(PriceTypes, price.priceType);
    }
0
Sonic Soul