Collect Related Strings in a String Enum in TypeScript

Marius Schulz
InstructorMarius Schulz
Share this video with your friends

Social Share Links

Send Tweet
Published 7 years ago
Updated 5 years ago

As of TypeScript 2.4, it is now possible to define string enums, or more precisely, enums with string members. Just like any other numeric enum, string enums can be made constant using the const modifier so that they disappear entirely from the generated JavaScript; in this case, all enum values will be inlined into the output.

Let's say we want to use fetch to load some data from a remote JSON API. The first thing we want to do is specify an HTTP accept header of application JSON, the JSON media type. In this setup, I have the TypeScript compiler running in the background. If I save the file on the left, we can immediately see the output on the right.

Right now, I'm specifying this media type inline, but I'd rather collect all media types in a central location. As of TypeScript 2.4, we can create string enums or technically enums with string members.

I'll go ahead and create an enum media types. Within it, I'm going to define a member called JSON that maps to the application JSON media type. Down in our header subject, I can now reference the enum and replace the inline value. Let's now save this file and take a look at the compiled output.

The compiler has generated a mapping object called media types. Below that declaration, it has inserted a function in which it assigns all the values to the keys. For example, here we have the key JSON, and we sign the value application JSON to it. We get a mapping from key to value.

Notice that we're lacking a reverse mapping here. We're not mapping from application JSON to the key JSON. With other enum types in TypeScript that would be the case. If we had a numeric enum, for example, something like ports where we map the SSL port to 443, we can see that we get a generated output with two mappings. We're mapping from SSL to 443, and from 443, we map to SSL.

Note that the usage looks exactly like it does in TypeScript. We simply reference the media types object and then its JSON property. Just like with any other enum in TypeScript, we can make our string enum a const enum by adding the const modifier.

If we now compile the fie again with a const modifier in place, the generated output looks pretty different. First of all, you'll notice that it's smaller than before. This is especially important on the Web where we want to minimize the time spent transferring and parsing our JavaScript files. Second, we no longer have a runtime manifestation of the media types enum. Our application JSON string has been inlined into the output.

The compiler also leaves a little comment there and tells us which enum case we used. This is not a problem for file size because if you use the minifier later, this comment will disappear.

Note that because of the const modifier, we don't have a runtime manifestation of the media types enum right now. In JavaScript land, nobody can say media types dot and then use our enum. If you want your compiled code to contain the media types enum, you can either remove the const keyword or you can leave the const keyword in and change your TypeScript compiler configuration.

Head over to your TS config JSON file, and set the preserve const enums option to true. With this configuration in place, the compiler will still do the inlining, but it will also emit the enums into the generated JavaScript code.

Stephen
Stephen
~ 6 years ago

Its seems that 'fetch' under ts 2.5.3 has no correct typings, so there are several warnings with headers etc. Great lessons here, but can no longer code along.

Marius Schulz
Marius Schulzinstructor
~ 6 years ago

@Stephen: Yeah, this is currently a known regression, but the fix has been merged already, so it should be part of the next TypeScript release.

Brendan Whiting
Brendan Whiting
~ 6 years ago

What’s the advantage of string enum over a union type of string literals?

enum ReservationType {
  PICKUP = ‘PICKUP,
  DROPOFF = 'DROPOFF'
}

type ReservationType = "PICKUP" | "DROPOFF";
Marius Schulz
Marius Schulzinstructor
~ 6 years ago

@Brendan: String enums and string literal types compile to different JavaScript code. String enums typically emit a mapping object (unless you use a const enum without --preserveConstEnums), whereas string literal types have no runtime manifestation at all.

If you're typing an existing JavaScript API, you'd probably use string literal types to describe the set of allowed values. In your own applications, you can use either string enums and string literal types, whichever one you prefer.

Brendan Whiting
Brendan Whiting
~ 6 years ago

Cool, thanks

Markdown supported.
Become a member to join the discussionEnroll Today