357

Following code can be used to create an enum in TypeScript:

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

And the values can be accessed by:

e.hello;
e.world;

How do I create an enum with string values?

enum e {
    hello = "hello", // error: cannot convert string to e
    world = "world"  // error 
};
Alexander Abakumov
  • 13,617
  • 16
  • 88
  • 129
FacePalm
  • 10,992
  • 5
  • 48
  • 50
  • heads up [Singleton types under the form of string literal types #1003](https://github.com/Microsoft/TypeScript/issues/1003) should solve this – Andreas Frische May 05 '15 at 14:34

28 Answers28

535

TypeScript 2.4

Now has string enums so your code just works:

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

TypeScript 1.8

Since TypeScript 1.8 you can use string literal types to provide a reliable and safe experience for named string values (which is partially what enums are used for).

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

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

Legacy Support

Enums in TypeScript are number based.

You can use a class with static members though:

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

You could go plain as well:

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

Update: Based on the requirement to be able to do something like var test:E = E.hello; the following satisfies this:

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); 
wonea
  • 4,783
  • 17
  • 86
  • 139
basarat
  • 261,912
  • 58
  • 460
  • 511
  • Little improvement: `toString(): string { return this.value; }` – psulek Jul 22 '13 at 11:52
  • @psulek Actually typescript will infer that `toString` returns a string since it returns `this.value` and `value` is of type string. So you cannot do `var x:number = E.hello.toString();` and if you do `var x = E.hello.toString();` x is infered to be of type `string` as well :) – basarat Jul 22 '13 at 12:11
  • 2
    @BASarat This is true that typescript handle such case, but i mean to have always have decorated methods with return types every time we know it, even it is not necessary for ts compiler, but for us coders to know when we saw method definition what type it returns. – psulek Jul 26 '13 at 06:53
  • @basarat is there any downside to replacing the `get()` method with `return this.value`? That way it will return the string value whenever accessed and not just when converting `toString()`. – John Feb 28 '14 at 23:37
  • @basarat If you have several "enums" like that, the compiler will not be distinguishing between them because of structural typing - compiler will see `value` member on all types and treat them as comparable types. You could make `value` member private though. This way compiler will not see it and won't try to apply structural typing. – Kirill G. Jun 03 '15 at 01:36
125

In latest version (1.0RC) of TypeScript, you can use enums like this:

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]);

Update 1

To get number value of enum member from string value, you can use this:

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

Update 2

In latest TypeScript 2.4, there was introduced string enums, like this:

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

    // Aliases
    RemoveUser = DeleteUser,
}

For more info about TypeScript 2.4, read blog on MSDN.

wonea
  • 4,783
  • 17
  • 86
  • 139
psulek
  • 4,308
  • 3
  • 29
  • 37
  • 2
    Generally, this solution is prefered (as it's a real enum) however you are very constrained on what the enum name is (hence the 'string'). – JasonS Feb 04 '15 at 16:27
  • 2
    Anything new on this? Because `States[str]` doesn't work nowadays. `Type 'string' is not assignable to type 'States'` – MrCroft Sep 26 '16 at 14:53
  • 1
    @MrCroft You can use: `States[str as any]` to do in current (2.x) version of Typescript. – psulek Feb 28 '17 at 05:53
  • Bit late but better to use `States[str as keyof States]` – Dustin Gaudet Nov 10 '22 at 20:51
85

TypeScript 2.4+

You can now assign string values directly to enum members:

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

See #15486 for more information.

TypeScript 1.8+

In TypeScript 1.8+, you can create a string literal type to define the type and an object with the same name for the list of values. It mimics a string enum's expected behaviour.

Here's an example:

type MyStringEnum = "member1" | "member2";

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

Which will work like a string enum:

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

Make sure to type all the strings in the object! If you don't then in the first example above the variable would not be implicitly typed to MyStringEnum.

David Sherret
  • 101,669
  • 28
  • 188
  • 178
  • 1
    How can I define something similar in a declaration file? – Zev Spitz Jun 27 '16 at 11:59
  • @ZevSpitz you can do [this](https://github.com/Microsoft/TypeScript/issues/3192#issuecomment-228752644) – David Sherret Jun 27 '16 at 13:56
  • Worth noting, that with the current compiler, you can mistype the string values in MyStringEnum and it will not complain. I have been creating an 'Enforcer' interface to make sure my strings are always valid. For example: interface MyStringEnumEnforcer { Member1: MyStringEnum, Member2: MyStringEnum } Then const MyStringEnum:MyStringEnumEnforcer = { Member1: "member1", Member2:"member2"} This does not allow for mistyped strings, although the compiler may end up working for your original scenario eventually. There's a lot of ceremony with this approach but I like the safety. – jmorc Feb 16 '17 at 17:02
  • [link to my example above](http://www.typescriptlang.org/play/index.html#src=type%20MyStringEnum%20%3D%20%22member1%22%20%7C%20%22member2%22%3B%0D%0Ainterface%20MyStringEnumEnforcer%0D%0A%7B%20%0D%0A%09Member1%3A%20MyStringEnum%2C%0D%0A%09Member2%3A%20MyStringEnum%2C%0D%0A%09Member3%3A%20MyStringEnum%2C%0D%0A%7D%0D%0Aconst%20MyStringEnum%3AMyStringEnumEnforcer%20%3D%20%7B%0D%0A%20%20%20%20Member1%3A%20%22member1%22%2C%0D%0A%20%20%20%20Member2%3A%20%22member2%22%2C%0D%0A%20%20%20%20Member3%3A%20%22not%20allowed%22%0D%0A%7D%3B) – jmorc Feb 16 '17 at 20:38
40

In TypeScript 0.9.0.1, although it occurs a compiler error, the compiler can still compile the ts file into js file. The code works as we expected and Visual Studio 2012 can support for automatic code completion.

Update :

In syntax, TypeScript doesn't allow us to create an enum with string values, but we can hack the compiler :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']);

Playground

wonea
  • 4,783
  • 17
  • 86
  • 139
JiaChen ZENG
  • 711
  • 8
  • 16
30

TypeScript 2.1 +

Lookup types, introduced in TypeScript 2.1 allow another pattern for simulating string enums:

// 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('Bar');            // 
doIt('Baz');            //  

TypeScript 2.4 +

With version 2.4, TypeScript introduced native support for string enums, so the solution above is not needed. From the TS docs:

enum Colors {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE",
}
intagli
  • 286
  • 4
  • 5
  • 20
Michael Bromley
  • 4,792
  • 4
  • 35
  • 57
  • How would I do this if the enum key name is different than the string value (because it's very long, for example)? – CletusW Apr 14 '17 at 21:41
  • Never mind! Solved in @Łukasz-pniewski 's answer below http://stackoverflow.com/a/42820134/1431146 – CletusW Apr 14 '17 at 21:45
  • tslint will throw an error on that String-Enum example when trying to reverse-map the Enum: Element implicitly has an 'any' type because index expression is not of type 'number'. I guess the issue is that in TS string Enums can not be reverse-mapped, see the comment in the String-Enum example at https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html - This seems to be true for TS 2.4 where String-Enum was introduced but I also get the error in TS 2.6.2. Example: `Colors["RED"]` will not work. Any idea how to solve this (required for JSON conversion). – omni Dec 29 '17 at 08:57
  • I found a solution similar to your initial answer, but without the redundancy (each entry is only typed once, not three times): https://stackoverflow.com/a/68143656/2441655 – Venryx Jun 26 '21 at 15:23
19

Why not just use the native way of accessing the strings of a enum.

enum e {
  WHY,
  NOT,
  USE,
  NATIVE
}

e[e.WHY] // this returns string 'WHY'
  • 2
    This is the answer I was looking for, thanks! The other solutions are clever workarounds, but this is so simple :) – M-- Oct 21 '15 at 10:17
  • 21
    This does not answer the question. The question is not about accessing strings of an enum. `enum Why { Because = "You Can't", Always = "Do Things That Way." }` ;) – James Wilkins Mar 04 '16 at 01:59
  • There are issues when using numeric value enums, such as 0 being falsy, harder to debug etc – robmcm Apr 20 '17 at 08:15
  • @robmcm solved enum e { WHY = 1, NOT = 2, USE = 3, NATIVE = 4 } e[e.WHY] // this returns string 'WHY' – Mient-jan Stelling Mar 28 '18 at 10:14
17

You can use string enums in the latest TypeScript:

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

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


UPDATE - 2016

A slightly more robust way of making a set of strings that I use for React these days is like this:

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);
wonea
  • 4,783
  • 17
  • 86
  • 139
Richard
  • 14,798
  • 21
  • 70
  • 103
  • 1
    This was the most concise way that did the job for me... At least until I can figure out how to update my scaffolding to compile with TS 1.8 – ThinkBonobo Feb 17 '16 at 21:08
  • However, one issue with this is that `e.hello` triggers an error. `e.hello` is still considered as a number by the compiler. `e.hello` does work though. Is there any way around this? All I can think of is `e.hello`. – RainingChain May 31 '16 at 05:31
  • Another issue is when having enum member equals to enum value. Ex: `enum Test { a = "b", b = "c", c = "a" }` `Test.a === 'c'` – RainingChain May 31 '16 at 05:52
  • I use this method all the time. String enum's rock. It's disappointing that the compiler doesn't have first class support for string literals, but it does have 2nd class support. The compiler actually knows when you've used the hack as it will stop you from using it in a .d.ts file - that to me gives some legitimacy to the use of this "hack" since the compiler is obviously aware of it but doesn't stop it completely. – CodeAndCats Aug 22 '16 at 07:28
  • Btw, if you want to compare a string value with a string enum value, rather then casting to `` then to ``, just do: `someStringValue == someEnumValue.toString()` – CodeAndCats Aug 22 '16 at 07:29
12

UPDATE: TypeScript 3.4

You can simply use as const:

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

TypeScript 2.1

This can also be done this way. Hope it help somebody.

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
ggradnig
  • 13,119
  • 2
  • 37
  • 61
  • This is exactly what I needed! It supports having the key name be different from the string value, as you've shown with your uppercase/lowercase difference. Thanks! – CletusW Apr 14 '17 at 21:43
10

Here's a fairly clean solution that allows inheritance, using TypeScript 2.0. I didn't try this on an earlier version.

Bonus: the value can be any type!

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: // ...
}
Westy92
  • 19,087
  • 4
  • 72
  • 54
8

A hacky way to this is: -

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

How to use

Utils.getEnumString(Status, Status.COMPLETED); // = "COMPLETED"
nishantkyal
  • 814
  • 1
  • 10
  • 8
6

This works for me:

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

or

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

8)

Update: Shortly after posting this I discovered another way, but forgot to post an update (however, someone already did mentioned it above):

enum MyEnum {
    value1 = <any>"value1 ", 
    value2 = <any>"value2 ", 
    value3 = <any>"value3 " 
}
James Wilkins
  • 6,836
  • 3
  • 48
  • 73
6

There a lot of answers, but I don't see any complete solutions. The problem with the accepted answer, as well as enum { this, one }, is that it disperses the string value you happen to be using through many files. I don't really like the "update" either, it's complex and doesn't leverage types as well. I think Michael Bromley's answer is most correct, but it's interface is a bit of a hassle and could do with a type.

I am using TypeScript 2.0.+ ... Here's what I would do

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

Then use like this:

let greet: Greeting = Greeting.hello

It also has much nicer type / hover-over information when using a helpful IDE. The draw back is you have to write the strings twice, but at least it's only in two places.

KyleMit
  • 30,350
  • 66
  • 462
  • 664
Nathan Cooper
  • 6,262
  • 4
  • 36
  • 75
  • I think I've found a solution with the same advantages, but with less redundancy (ie. each entry being typed only once instead of four times): https://stackoverflow.com/a/68143656/2441655 – Venryx Jun 26 '21 at 15:45
  • Ah, well the difference is actually four times vs *two* times, because your solution also sets each entry to have type `Greeting` explicitly (ie. by name), rather than just "matching by having the same set of literal values". Not a big deal imo, but worth mentioning. (eg. some people might want to use the same "cast to named type" approach with that answer) – Venryx Jun 26 '21 at 15:54
4

I just declare an interface and use a variable of that type access the enum. Keeping the interface and enum in sync is actually easy, since TypeScript complains if something changes in the enum, like so.

error TS2345: Argument of type 'typeof EAbFlagEnum' is not assignable to parameter of type 'IAbFlagEnum'. Property 'Move' is missing in type 'typeof EAbFlagEnum'.

The advantage of this method is no type casting is required in order to use the enum (interface) in various situations, and more types of situations are thus supported, such as the switch/case.

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

Using the variable, rather than the enum, produces the desired results.

var strVal: string = AbFlagEnum.Edit;

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

Flags were another necessity for me, so I created an NPM module that adds to this example, and includes tests.

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

wonea
  • 4,783
  • 17
  • 86
  • 139
djabraham
  • 766
  • 11
  • 20
  • This is the only answer I found which allows to mix definitions with imports. Nice! You can use `export default EAbFlagEnum as IAbFlagEnum;` instead of redeclaring a variable. I also removed the `` cast in the enum, it works fine. – Guillaume F. Jan 21 '20 at 14:50
4

String enums in Typescript:

String enums are a similar concept, but have some subtle runtime differences as documented below. In a string enum, each member has to be constant-initialized with a string literal, or with another string enum member.

enum Direction {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT",
}

While string enums don’t have auto-incrementing behavior, string enums have the benefit that they “serialize” well. In other words, if you were debugging and had to read the runtime value of a numeric enum, the value is often opaque - it doesn’t convey any useful meaning on its own (though reverse mapping can often help), string enums allow you to give a meaningful and readable value when your code runs, independent of the name of the enum member itself. Reference link is below.

enter link description here

Muhammad Awais
  • 4,238
  • 1
  • 42
  • 37
3

With custom transformers (https://github.com/Microsoft/TypeScript/pull/13940) which is available in typescript@next, you can create enum like object with string values from string literal types.

Please look into my npm package, ts-transformer-enumerate.

Example usage:

// 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'
kimamula
  • 11,427
  • 8
  • 35
  • 29
2

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

To the source link you can find more and easier ways to accomplish string literal type

wonea
  • 4,783
  • 17
  • 86
  • 139
Panagiotis Koursaris
  • 3,794
  • 4
  • 23
  • 46
1

@basarat's answer was great. Here is simplified but a little bit extended example you can use:

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...
}
Manuel Fodor
  • 464
  • 4
  • 6
1

I had the same question, and came up with a function that works well:

  • Each entry's key and value are strings, and identical.
  • Each entry's value is derived from the key. (ie. "don't repeat yourself", unlike for the regular enums with string values)
  • The TypeScript types are full-fledged and correct. (preventing typos)
  • There remains an easy way to have TS auto-complete your options. (eg. typing MyEnum., and immediately seeing the options available)
  • And a couple other advantages. (see bottom of answer)

The utility function:

export function createStringEnum<T extends {[key: string]: 1}>(keysObj: T) {
    const optionsObj = {} as {
        [K in keyof T]: keyof T
        // alternative; gives narrower type for MyEnum.XXX
        //[K in keyof T]: K
    };
    const keys = Object.keys(keysObj) as Array<keyof T>;
    const values = keys; // could also check for string value-overrides on keysObj
    for (const key of keys) {
        optionsObj[key] = key;
    }
    return [optionsObj, values] as const;
}

Usage:

// if the "Fruit_values" var isn't useful to you, just omit it
export const [Fruit, Fruit_values] = createStringEnum({
    apple: 1,
    pear: 1,
});
export type Fruit = keyof typeof Fruit; // "apple" | "pear"
//export type Fruit = typeof Fruit_values[number]; // alternative

// correct usage (with correct types)
let fruit1 = Fruit.apple; // fruit1 == "apple"
fruit1 = Fruit.pear; // assigning a new fruit also works
let fruit2 = Fruit_values[0]; // fruit2 == "apple"

// incorrect usage (should error)
let fruit3 = Fruit.tire; // errors
let fruit4: Fruit = "mirror"; // errors

Now someone might ask, what is the advantage of this "string-based enum" over just using:

type Fruit = "apple" | "pear";

There are a few advantages:

  1. Auto-complete is a bit nicer (imo). For example, if you type let fruit = Fruit., Typescript will immediately list the exact set of options available. With string literals, you need to define your type explicitly, eg. let fruit: Fruit = , and then press ctrl+space afterward. (and even that results in unrelated autocomplete options being shown below the valid ones)
  2. The TSDoc metadata/description for an option is carried over to the MyEnum.XXX fields! This is useful for providing additional information about the different options. For example:
  3. You can access the list of options at runtime (eg. Fruit_values, or manually with Object.values(Fruit)). With the type Fruit = ... approach, there is no built-in way to do this, which cuts off a number of use-cases. (for example, I use the runtime values for constructing json-schemas)
Venryx
  • 15,624
  • 10
  • 70
  • 96
0

TypeScript 0.9.0.1

enum e{
    hello = 1,
    somestr = 'world'
};

alert(e[1] + ' ' + e.somestr);

TypeScript Playground

wonea
  • 4,783
  • 17
  • 86
  • 139
  • The resulting JavaScript works, but this does produce a compiler error: `Cannot convert 'string' to 'e'.`. – Sam Dec 23 '13 at 03:43
0

Faced this issue recently with TypeScript 1.0.1, and solved this way:

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)
wonea
  • 4,783
  • 17
  • 86
  • 139
pocesar
  • 6,860
  • 6
  • 56
  • 88
0

I think you should try with this, in this case the value of the variable won't change and it works quite like enums,using like a class also works the only disadvantage is by mistake you can change the value of static variable and that's what we don't want in enums.

namespace portal {

export namespace storageNames {

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

  }
}
Pranay Dutta
  • 2,483
  • 2
  • 30
  • 42
0

I have tried in TypeScript 1.5 like below and it's worked for me

module App.Constants {
   export enum e{
        Hello= ("Hello") as any,
World= ("World") as any
    }
}
wonea
  • 4,783
  • 17
  • 86
  • 139
Jameel Moideen
  • 7,542
  • 12
  • 51
  • 79
0
export enum PaymentType {
                Cash = 1,
                Credit = 2
            }
var paymentType = PaymentType[PaymentType.Cash];
Slava Vedenin
  • 58,326
  • 13
  • 40
  • 59
Evon Dos
  • 155
  • 1
  • 3
0
//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

Little js-hacky but works: e[String(e.hello)]

Majid Mallis
  • 114
  • 4
0

If what you want is mainly easy debug (with fairly type check) and don't need to specify special values for the enum, this is what I'm doing:

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

If you want to support legacy code/data storage, you might keep the numeric keys.

This way, you can avoid typing the values twice.

Beeno Tung
  • 1,058
  • 10
  • 17
0

Very, very, very simple Enum with string (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))
}
wonea
  • 4,783
  • 17
  • 86
  • 139
Karima Rafes
  • 1,016
  • 10
  • 19
0

i was looking for a way to implement descriptions in typescript enums (v2.5) and this pattern worked for me:

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);
    }
Sonic Soul
  • 23,855
  • 37
  • 130
  • 196
  • just out of curiosity (all these many years later), can you think of any potential pitfalls of using TS "string enums" for descriptions..? only thing I can think of, is that all these strings can't be "minified" in any way at build time... but anything other than the build output size cost? – Andre Greeff Nov 03 '22 at 07:32