Skip to Content
Course content

9: Enums and Const Enums

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Imagine you're running a busy coffee shop. You could tell your baristas, "When a customer orders a '1', make a Latte; a '2' is a Cappuccino, and a '3' is a Flat White." Technically, that works. But it's a nightmare. One morning, a new hire forgets if '2' was a Cappuccino or a Mocha, or someone accidentally types '4' into the system, and suddenly you're serving something that doesn't exist. To fix this, you create a menu. The menu gives a human-readable name (the "Label") to a specific item (the "Value").

That is exactly what an Enum does in TypeScript. It lets you define a set of named constants so you aren't passing "magic numbers" or random strings around your codebase and hoping you didn't make a typo.

Giving Names to Magic Numbers

Let's say we're building an e-commerce order tracker. Without enums, you might use numbers to represent the status of an order. But if (order.status === 2) tells you absolutely nothing about what's actually happening. Here is how I'd handle that using a numeric enum:

enum OrderStatus {
  Pending,   // 0
  Processing, // 1
  Shipped,    // 2
  Delivered,  // 3
}

function updateShipping(status: OrderStatus) {
  if (status === OrderStatus.Shipped) {
    console.log("Notify the customer their package is on the way!");
  }
}

updateShipping(OrderStatus.Shipped);

By default, TypeScript assigns numbers starting at 0. The beauty here is that OrderStatus.Shipped is much easier to read than the number 2. Also, if you ever need to change the underlying value, you change it in one place, not in fifty different if statements across your app.

When Strings Make More Sense

Numeric enums are great, but they have a downside: when you log them to the console or send them to an API, you just see 0, 1, 2. If you're debugging a production log at 2 AM, you don't want to be cross-referencing a documentation file to remember what "Status 2" means. That's where string enums come in.

enum OrderStatus {
  Pending = "PENDING",
  Processing = "PROCESSING",
  Shipped = "SHIPPED",
  Delivered = "DELIVERED",
}

const currentStatus = OrderStatus.Shipped;
console.log(currentStatus); // Output: "SHIPPED"

I almost always prefer string enums for things that get saved to a database or sent over a network. It makes the data self-documenting. You don't need a secret decoder ring to understand the state of your application.

Stripping the Runtime Overhead

Now, here is a bit of a "pro" detail. Standard enums are one of the few features in TypeScript that aren't just type-level sugar—they actually generate a real JavaScript object when the code is compiled. For most projects, this doesn't matter. But if you're writing a library or working in a high-performance environment, you might not want that extra object hanging around in your final bundle.

That's why we have const enum. When you add the const keyword, TypeScript doesn't create an object at runtime. Instead, it simply replaces every mention of the enum member with the actual value during compilation.

const enum UserRole {
  Admin = 1,
  Editor = 2,
  Viewer = 3,
}

const myRole = UserRole.Admin;
// In the compiled JavaScript, this literally becomes:
// const myRole = 1;

You lose the ability to iterate over the enum keys at runtime, but you gain a tiny bit of performance and a smaller file size. Use them when you know you only need the names for type-checking and don't need to treat the enum as an object in your JS code.




📋 Practical Task

Building a User Access Level Controller

You are building a permission system for a corporate dashboard. You need to ensure that users are assigned a specific access level and that the system handles these levels safely.

Your Task:

  • Create a string enum called AccessLevel with the following members: Guest, Employee, Manager, and Admin.
  • Write a function called canAccessAdminPanel that takes an AccessLevel as an argument.
  • The function should return true only if the user is an Admin or a Manager; otherwise, return false.
  • Test your function by calling it with both AccessLevel.Guest and AccessLevel.Admin and logging the results to the console.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.