I have defined the following enum in TypeScript?

enum Color{
    Red, Green
}

Now in my function I receive color as a string. I have tried the following code:

var green= "Green";
var color : Color = <Color>green; // Error: can't convert string to enum

How can I convert that value to an enum?

9 Answers

264
basarat On Best Solutions

Enums in TypeScript 0.9 are string+number based. You should not need type assertion for simple conversions:

enum Color{
    Red, Green
}

// To String
 var green: string = Color[Color.Green];

// To Enum / number
var color : Color = Color[green];

Try it online

I have documention about this and other Enum patterns in my OSS book : https://basarat.gitbooks.io/typescript/content/docs/enums.html

16
Amitabh On

Got it working using following code.

var green= "Green";
var color : Color= <Color>Color[green];
24
Sly_cardinal On

This note relates to basarat's answer, not the original question.

I had an odd issue in my own project where the compiler was giving an error roughly equivalent to "cannot convert string to Color" using the equivalent of this code:

var colorId = myOtherObject.colorId; // value "Green";
var color: Color = <Color>Color[colorId]; // TSC error here: Cannot convert string to Color.

I found that the compiler type inferencing was getting confused and it thought that colorId was an enum value and not an ID. To fix the problem I had to cast the ID as a string:

var colorId = <string>myOtherObject.colorId; // Force string value here
var color: Color = Color[colorId]; // Fixes lookup here.

I'm not sure what caused the issue but I'll leave this note here in case anyone runs into the same problem I did.

10
Chris On

I also ran into the same compiler error. Just a slight shorter variation of Sly_cardinal's approach.

var color: Color = Color[<string>colorId];
7
Luka On

If typescript compiler knows that the type of variable is string than this works

let colorName : string = "Green";
let color : Color = Color[colorName];

otherwise you should explicitly convert it to string (to avoid compiler warning)

let colorName : any = "Green";
let color : Color = Color["" + colorName];

At runtime both solutions will work.

17
Artru On

If you are sure that an input string has exact match with Color enum then use:

const color: Color = (<any>Color)["Red"];

In the case where an input string may not match Enum use:

const mayBeColor: Color | undefined = (<any>Color)["WrongInput"];
if(mayBeColor !== undefined){
     //TSC will understand that mayBeColor of type Color here
}

Playground


If we do not cast enum to <any> type then tsc will show the error

Element implicitly has 'any' type because index expression is not of type 'number'.

It means that by default TS Enum type works with number indexes, i.e. let c = Color[0], but not with string indexes like let c = Color["string"]. This is a known restriction by Microsoft team for more general issue Object string indexes.

67
Victor On

As of Typescript 2.1 string keys in enums are strongly typed. keyof typeof is used to get info about available string keys (1):

enum Color{
    Red, Green
}

let typedColor: Color = Color.Green;
let typedColorString: keyof typeof Color = "Green";

// Error "Black is not assignable ..." (indexing using Color["Black"] will return undefined runtime)
typedColorString = "Black";

// Error "Type 'string' is not assignable ..." (indexing works runtime)
let letColorString = "Red";
typedColorString = letColorString;

// Works fine
typedColorString = "Red";

// Works fine
const constColorString = "Red";
typedColorString = constColorString

// Works fine (thanks @SergeyT)
let letColorString = "Red";
typedColorString = letColorString as keyof typeof Color;

typedColor = Color[typedColorString];

https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types

2
Nick On

There's a lot of mixed info in this question, so let's cover the whole implementation for Typescript 2.x+ in Nick's Guide to Using Enums in Models with Typescript.

This guide is for: people who are creating client-side code that's ingesting a set of known strings from the server that would be conveniently modeled as an Enum on the client side.

Define the enum

Let's start with the enum, it should look something like this:

export enum IssueType {
  REPS = 'REPS',
  FETCH = 'FETCH',
  ACTION = 'ACTION',
  UNKNOWN = 'UNKNOWN',
}

Two thing of note here:

  1. We're explicitly declaring these as string-backed enum cases which allows us to instantiate them with strings, not some other unrelated numbers.

  2. We've added an option that may or may not exist on our server model: UNKNOWN. This can be handled as undefined if you prefer, but I like to avoid | undefined on types whenever possible to simplify handling.

The great thing about having an UNKNOWN case is that you can be really obvious about it in code and make styles for unknown enum cases bright red and blinky so you know you're not handling something correctly.

Parse the enum

You might be using this enum embedded in another model, or all alone, but you're going to have to parse the string-y typed enum from JSON or XML (ha) into your strongly typed counterpart. When embedded in another model, this parser lives in the class constructor.

parseIssueType(typeString: string): IssueType {
  const type = IssueType[typeString];
  if (type === undefined) {
    return IssueType.UNKNOWN;
  }

  return type;
}

If the enum is properly parsed, it'll end up as the proper type. Otherwise, it'll be undefined and you can intercept it and return your UNKNOWN case. If you prefer using undefined as your unknown case, you can just return any result from the attempted enum parsing.

From there, it's only a matter of using the parse function and using your newly strong typed variable.

const strongIssueType: IssueType = parseIssueType('ACTION');
// IssueType.ACTION
const wrongIssueType: IssueType = parseIssueType('UNEXPECTED');
// IssueType.UNKNOWN
0
Jonas On
enum Color{
    Red, Green
}

// To String
 var green: string = Color[Color.Green];

// To Enum / number
var color : Color = Color[green as keyof typeof Color]; //Works with --noImplicitAny

This example works with --noImplicitAny in TypeScript

Sources:
https://github.com/Microsoft/TypeScript/issues/13775#issuecomment-276381229 https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types