Frontend Development 8 min read

Mastering TypeScript Enums: Numeric, String, and Const Variants Explained

This article explains how TypeScript enums work, covering numeric, string, and const enums, their compilation behavior, reverse mappings, type differences, and best‑practice usage to write clearer and more maintainable code.

Code Mala Tang
Code Mala Tang
Code Mala Tang
Mastering TypeScript Enums: Numeric, String, and Const Variants Explained

In TypeScript, the enum keyword provides a way to define a set of named constants that can be used as types or values. Enums were introduced in the first version of TypeScript, offering powerful runtime features despite not being part of JavaScript.

Enums are ideal for defining a finite, stable set of constant values, helping developers write clearer and more maintainable code.

Numeric Enums

Numeric enums automatically assign numeric values starting from 0. Example:

<code>enum AlbumStatus {
  NewRelease,
  OnSale,
  StaffPick
}
</code>

In this example, AlbumStatus.NewRelease is 0, AlbumStatus.OnSale is 1, etc. They can be used by name:

<code>function logStatus(status: AlbumStatus) {
  console.log(status); // outputs 0
}
logStatus(AlbumStatus.NewRelease);
</code>

You can also assign explicit values:

<code>enum AlbumStatus {
  NewRelease = 1,
  OnSale = 2,
  StaffPick = 3
}
</code>

Now NewRelease is 1, OnSale is 2, etc.

Auto‑incremented Numeric Enums

If only some members have explicit values, TypeScript auto‑increments from the last specified value.

<code>enum AlbumStatus {
  NewRelease = 1,
  OnSale,
  StaffPick,
}
</code>

Here OnSale becomes 2 and StaffPick becomes 3.

String Enums

String enums assign string values to each member, providing more expressive semantics.

<code>enum AlbumStatus {
  NewRelease = "NEW_RELEASE",
  OnSale = "ON_SALE",
  StaffPick = "STAFF_PICK",
}
</code>

Using a string enum, the logStatus function will output the string value:

<code>function logStatus(status: AlbumStatus) {
  console.log(status); // outputs "NEW_RELEASE"
}
logStatus(AlbumStatus.NewRelease);
</code>

Quirky Behaviors of Enums

Reverse Mapping of Numeric Enums

When compiled, numeric enums generate an object that supports reverse mapping from value to name.

<code>enum AlbumStatus {
  NewRelease,
  OnSale,
  StaffPick,
}
</code>

Compiled JavaScript:

<code>var AlbumStatus;
(function (AlbumStatus) {
  AlbumStatus[AlbumStatus["NewRelease"] = 0] = "NewRelease";
  AlbumStatus[AlbumStatus["OnSale"] = 1] = "OnSale";
  AlbumStatus[AlbumStatus["StaffPick"] = 2] = "StaffPick";
})(AlbumStatus || (AlbumStatus = {}));
</code>

Object.keys(AlbumStatus) yields ["0","1","2","NewRelease","OnSale","StaffPick"].

Simplified Behavior of String Enums

String enums do not generate reverse mappings; only the enum values are kept.

<code>enum AlbumStatus {
  NewRelease = "NEW_RELEASE",
  OnSale = "ON_SALE",
  StaffPick = "STAFF_PICK",
}
</code>

Compiled JavaScript:

<code>var AlbumStatus;
(function (AlbumStatus) {
  AlbumStatus["NewRelease"] = "NEW_RELEASE";
  AlbumStatus["OnSale"] = "ON_SALE";
  AlbumStatus["StaffPick"] = "STAFF_PICK";
})(AlbumStatus || (AlbumStatus = {}));
</code>

Object.keys(AlbumStatus) returns ["NewRelease","OnSale","StaffPick"].

Type Differences

Numeric and string enums behave differently as types. With a numeric enum you can pass either an enum member or its numeric value, but passing an out‑of‑range number causes a type error.

<code>enum AlbumStatus {
  NewRelease = 0,
  OnSale = 1,
  StaffPick = 2,
}
function logStatus(status: AlbumStatus) {
  console.log(status);
}
logStatus(AlbumStatus.NewRelease);
logStatus(0);
// logStatus(3); // error
</code>

String enums only accept enum members; passing the raw string also causes a type error.

<code>enum AlbumStatus {
  NewRelease = "NEW_RELEASE",
  OnSale = "ON_SALE",
  StaffPick = "STAFF_PICK",
}
function logStatus(status: AlbumStatus) {
  console.log(status);
}
logStatus(AlbumStatus.NewRelease);
logStatus("NEW_RELEASE"); // error
</code>

String enums are nominally compared, so two enums with identical string values but different names are incompatible.

<code>enum AlbumStatus2 {
  NewRelease = "NEW_RELEASE",
  OnSale = "ON_SALE",
  StaffPick = "STAFF_PICK",
}
logStatus(AlbumStatus2.NewRelease); // error
</code>

Const Enums

Const enums are erased during compilation; their members are inlined as literal values.

<code>const enum AlbumStatus {
  NewRelease = "NEW_RELEASE",
  OnSale = "ON_SALE",
  StaffPick = "STAFF_PICK",
}
</code>

Compiled output replaces usages with the string literals directly.

<code>let albumStatuses = ["NEW_RELEASE","ON_SALE","STAFF_PICK"];
</code>

The TypeScript team advises avoiding const enums in library code because they can lead to unpredictable behavior for consumers.

Summary

Numeric enums have reverse mapping and allow using raw numbers.

String enums lack reverse mapping and enforce strict nominal typing.

Const enums are inlined at compile time and generate no runtime code.

Using enums appropriately can make code cleaner, clearer, and more maintainable.

TypeScriptenumconst enumnumeric enumstring enum
Code Mala Tang
Written by

Code Mala Tang

Read source code together, write articles together, and enjoy spicy hot pot together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.