How to implement an enum with string values in TypeScript

I currently work an a single-page application (SPA), where we use TypeScript to access web services. In some places, the sent and received data structures use enums to describe the range of allowed values. I tried to use the enums from TypeScript to access the web services in a strongly typed way:

export interface PersonDto {
    language: Language; 
}

export enum Language {
    English, 
    German, 
    French, 
    Itialian    
}

When serializing a PersonDto instance to JSON, the language field is converted to a number and not a string as required by the web service API:

var person = <PersonDto> { language: Language.German }
var json = JSON.stringify(person);

The json variable now contains:

"{ language: 1 }"

The solution to this problem is to assign the expected string value to each enum member. However, TypeScript only allows numbers as enum member values. But there is a simple solution: Just cast the string literal to any before assigning:

export enum Language {
    English = <any>"English",
    German = <any>"German",
    French = <any>"French",
    Italian = <any>"Italian"
}

The shown TypeScript code is transpiled into the following JavaScript code:

(function (Language) {
    Language[Language["English"] = "English"] = "English";
    Language[Language["German"] = "German"] = "German";
    Language[Language["French"] = "French"] = "French";
    Language[Language["Italian"] = "Italian"] = "Italian";
})(exports.Language || (exports.Language = {}));
var Language = exports.Language;

With the shown changes to the enum, the output of the previous serialization code works as expected:

"{ language: "German" }"

Read more about this problem on this GitHub Issue page.


Tags:

7 responses to “How to implement an enum with string values in TypeScript”

  1. Why use enums when there are string literal types, especially if there is not a hugh chance that the strings will change?

    export type Language = "English" | "German" | "French" | "Italian";

    • Rico Suter says:

      Yes, string literal types are also an option for modeling enums… But there are also some downsides to them, for example the caller still uses string literals which are harder to refactor, etc.

      • Per Persson says:

        You are right.

        Why do you have <any> in front of the strings? They seem to just create unnecessary bloat in the compiled code. Where they needed two years ago?

        • Rico Suter says:

          Yes, this was needed in an old TypeScript version – this is why this blog post even exists.
          Nowadays it just works as expected…

  2. […] How to implement an enum with string values in TypeScript […]

  3. Yogesh A says:

    Hello,

    Actually i am trying to bind the enum to Dropdown list but unfortunately i could not bind.
    so can you please tell me how to do this.

    Thanks & Regards,
    Yogesh Amritkar.

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

This site uses Akismet to reduce spam. Learn how your comment data is processed.