1

I would like to have a set of string enums in typescript so I can do things like having the user select from a set of predefined options.

I found a good solution in this answer: How to convert string to enum in TypeScript?

However, that only works for single words... (basically, the above allows you to get the enum name value -- and that can't have a space in it).

So, further looking, I found this person with a workaround: Workaround for string based enums in typescript

That will allow something like this to work:

export enum EventType {
    Photoshoot = <any>"Photoshoot",
    BookingMeeting = <any>"Booking Meeting",
    PostShootMeeting = <any>"Post Shoot Meeting",
    Purchase = <any>"Purchase",
    Print = <any>"Print"
}

The only response basically says doing so is unsafe. (but I should say, it DOES work -- I can type EventType.dot ... and Atom editor gives me the 5 camel-case options to select from (keeping things consistent in the code) I can then use that to have the string value spit out to give my users a good space-filled experience, in the future I can change the enum and for different languages/option wording without messing with the 'code' at all, etc...

Is there a better way to do this? I'd rather not do it 'unsafely' -- but I don't know of any other way.

Community
  • 1
  • 1
lowcrawler
  • 6,777
  • 9
  • 37
  • 79
  • You could define class with static read-only strings instead of enum – Aleksey L. Jan 24 '17 at 05:54
  • 1
    based on this open issue https://github.com/Microsoft/TypeScript/issues/1206, I think your work around is the best approach at the moment. In fact the work around is listed in one of the comments. – shusson Jan 24 '17 at 06:22
  • **See Also**: [Create an enum with string values](https://stackoverflow.com/q/15490560/1366033) – KyleMit Jan 02 '22 at 01:35

3 Answers3

5

TypeScript enums are number based. You can use string literals with union types to mock a string based enum as in the CardinalDirection example below.

type CardinalDirection =
    "North"
    | "East"
    | "South"
    | "West";

function move(distance: number, direction: CardinalDirection) {
    // ...
}

move(1,"North"); // Okay
move(1,"Nurth"); // Error!

here's more: https://basarat.gitbooks.io/typescript/content/docs/types/literal-types.html

the string enums are in the offing https://github.com/Microsoft/TypeScript/issues/3192

Chandan Rai
  • 9,879
  • 2
  • 20
  • 28
  • 2
    How does this get me the "give my developers specific options that doesn't result in hard-coding strings into the business logic code" ? In the OP solution, one could change the string "Photoshoot" to "Photo shoot" without any other coding changes (because all the business logic code refers to `EventType.Photoshoot`. It seems that in this solution, you'd need to find every use of "North" in the business code if you ever wanted to change it to "nerf". Perhaps I'm missing something, however... ? (glad string enums are being discussed for future typescript) – lowcrawler Jan 24 '17 at 05:29
  • @lowcrawler If you want to change "North" to "nerf", just go to where `type CardinalDirection` is defined in the code and change "North" to "nerf". Now the compiler will give an error on every use of "North" where a CardinalDirection is expected, so you can easily find them all. – thedayturns Jan 24 '17 at 06:13
  • @thdayturns my mistake, as you point out you will get a compiler error. – shusson Jan 24 '17 at 06:34
1

Update for TS 2.4 - 2017+

String Enums are available starting in TypeScript 2.4 using the following syntax:

enum Color {
    Red = "red",
    Green = "green",
    Blue = "blue"
}

Demo in TS Playground

Further Reading

KyleMit
  • 30,350
  • 66
  • 462
  • 664
0

You have other options, as described in Reverse-Mapping for String Enums.

Here is an example:

type EventType = "Photoshoot" | "Booking Meeting" | "Post Shoot Meeting" | "Purchase" | "Print";
const EventType {
    get Photoshoot(): EventType { return "Photoshoot"; },
    get BookingMeeting(): EventType { return "Booking Meeting"; },
    get PostShootMeeting(): EventType { return "Post Shoot Meeting"; },
    get Purchase(): EventType { return "Purchase"; },
    get Print(): EventType { return "Print"; }
}
Rodris
  • 2,603
  • 1
  • 17
  • 25