Typescript: Enums
Jatin Sharma

Jatin Sharma @j471n

About: Turning Web Dreams into Reality, Just Like Tony Stark's Vision

Location:
🇮🇳 India
Joined:
Oct 20, 2020

Typescript: Enums

Publish Date: Mar 12 '23
190 18

In this article, you'll learn about what enums are and how you can use them in your projects. Enums, short for Enumerated Types.

This is going to be a full series of typescript where you will learn from basic topics like string, boolean to more complex like Type Aliases, enums, Interface, generics, and etc.

Table of Contents

Enums

Enums are one of the few features TypeScript has which is not a type-level extension of JavaScript.

Enums allow a developer to define a set of named constants. Using enums can make it easier to document intent, or create a set of distinct cases. TypeScript provides both numeric and string-based enums.

Numeric enums

We will first take a look at Numeric enums and how we can create them. An enum can be defined using the enum keyword.

enum Direction  {
    Up, 
    Down, 
    Left, 
    Right,
}
Enter fullscreen mode Exit fullscreen mode

Above, we have a numeric enum where Up is initialized with 0. All of the following members are auto-incremented from that point on. In other words, Direction.Up has the value 0, Down has 1, Left has 2, and Right has 3.

In the Numeric enums, the values are in the incremented order as explained above. You can manipulate these values as you want. Let’s take a few examples of that:

// Up = 1, Down = 2, Left = 3, Right = 4
enum Direction  {
    Up = 1, 
    Down, 
    Left, 
    Right,
}

// Up = 1, Down = 5, Left = 6, Right = 7
enum Direction  {
    Up, 
    Down = 5, 
    Left, 
    Right,
}

// Up = 10, Down = 11, Left = 14, Right = 15
enum Direction  {
    Up = 10, 
    Down, 
    Left = 14, 
    Right,
}
Enter fullscreen mode Exit fullscreen mode

In the above code example, I have updated the values and shown you what will be the value of the others members.

String enums

String enums are a similar concept. In a string enum, each member has to be constant-initialized with a string literal, or with another string enum member.

enum Direction {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT",
}
Enter fullscreen mode Exit fullscreen mode

To access any members you can do the following:

console.log(Direction.Up) // output: UP
Enter fullscreen mode Exit fullscreen mode

Heterogeneous enums

enums can be mixed with string and numeric members, but it’s not clear why you would ever want to do so. it’s advised that you don’t do this.

enum ExtraFries {
  No = 0,
  Yes = "YES",
}
Enter fullscreen mode Exit fullscreen mode

If you want to learn more about Enums, consider reading the documentation.

Wrapping up

In this article, I have explained what enums are and how you can use them in your projects. Enums, short for Enumerated Types.

This is a series of Typescript that will help you to learn Typescript from the scratch. If you enjoyed this article, then don't forget to give ❤️ and Bookmark 🏷️for later use and if you have any questions or feedback then don't hesitate to drop them in the comments below. I'll see in the next one.

Connect with me

Comments 18 total

  • Aziz Kaukawala
    Aziz KaukawalaMar 13, 2023

    Helping a lot! 🫀
    Please keep continuing the series mate!

    Thank you! 🔥🔥

  • Jake Lundberg
    Jake LundbergMar 13, 2023

    Great breakdown :) and thank you for sharing that the Heterogeneous enums are a bad idea! Keep up the good work!

  • Pedro Furlaneto
    Pedro FurlanetoMar 14, 2023

    Nice article bro 🔥🔥

    Could you give me an example of when I could use an enum instead of an object, please?

    Keep going on the series dude!

    • Jatin Sharma
      Jatin Sharma Mar 15, 2023

      Objects are re-assignable but you can't assign values to enums types.

      enum ExtraFries {
        No = "No",
        Yes = "YES",
      }
      
      let v1 = ExtraFries.No;
      let v2 = ExtraFries.Yes;
      
      // ❌ Type '"Yes"' is not assignable to type 'ExtraFries
      v1 = "Yes";
      
      // ❌ Cannot assign to 'No' because it is a read-only property.
      ExtraFries.No = "Nooooo"
      
      // ✅ This will work
      v1 = ExtraFries.Yes
      
      Enter fullscreen mode Exit fullscreen mode

      But if we use object that it will allows us:

      const obj = {
          no: "NO",
          yes:"YES"
      }
      
      let v3 = obj.no
      v3 = "YES";
      
      obj.no = "Nooooooooooooooo"
      // It will allow everything
      
      Enter fullscreen mode Exit fullscreen mode

      You can check the playground:
      typescriptlang.org/play?#code/PTAE...

      • Pedro Furlaneto
        Pedro FurlanetoMar 15, 2023

        Thanks bro! 🤝

      • Christian Bewernitz
        Christian BewernitzMar 15, 2023

        by appending as const to the value of obj you even get a read-only version of it, which can not be modified at runtime, and where obj.no and obj.yes have a narrowed type of the string literal value!

        To even get a type for all the possible values, you can use the following snippet:

        type EnumFromDict<T extends ReadonlyRecord<string, string>> = T[keyof T];
        
        Enter fullscreen mode Exit fullscreen mode

        of course it might help to have the same casing for both keys and values to simplify your searches.
        Putting it all together:

        export const YesNo = {
          Yes: 'Yes',
          No: 'No',
        } as const;
        export type YesNo = EnumFromDict<typeof YesNo>;
        
        Enter fullscreen mode Exit fullscreen mode

        (yes, you can export a type and a value with the same name from a module!)

        This still allows you to use literal values everywhere and from what I know if as close as you can get to an enum.
        If you need to reference the type of one of the keys from the const, you need to use typeof YesNo.Yes. (There are other options but they are longer.)

        Hope it helps

        • Pedro Furlaneto
          Pedro FurlanetoMar 15, 2023

          Thanks mate! It will helps for sure, I was searching for that way of typing

          🤝🤝

  • Heather Parker
    Heather Parker Mar 14, 2023

    I loved this post series; it's incredible!

  • Brian Bates
    Brian BatesMar 15, 2023

    Really cool and helpful! Thanks!

  • Dmitry A. Efimenko
    Dmitry A. EfimenkoMar 15, 2023

    I wish this article didn't get this much positive feedback - or any at all for that matter.
    I see comments like "Really cool and helpful! Thanks!". No, it's the opposite of helpful. It's spreading an anti-pattern. Nothing wrong with talking about what Enums are. But if you do that, you should also talk whether Enums should ever be used in TS. And the answer is - in most cases they should not.

    TypeScript Enums are an awkward attempt to make Enums from C# or Java work in JS. They have weird edge-cases and should almost never be used. String literals will achieve the result with better ergonomics in most situations. This is the most important thing anybody need to know about JS Enums.

    Don't believe me? Just do a quick google search and see smarter people talk about it.

    • Sebastian Krah
      Sebastian KrahMar 15, 2023

      I can just agree. Enums in TypeScript should be avoided. See also @karfau answer for a better approach.

  • Yoïchi Trigalot
    Yoïchi TrigalotMar 16, 2023

    Such a great series of articles. Although I used type script in some of my projects, it helps me simplify, popularize, and understand better some subtleties.
    Great job man! Appreciate 🔥

  • Code of Relevancy
    Code of RelevancyMar 18, 2023

    Great article..

  • eerk
    eerkMar 18, 2023

    Since I discovered you can use strings as types I just use the following:

    type Direction = "UP" | "LEFT" | "DOWN" | "RIGHT"
    let direction : Direction = "boink"  // error :boink is not assignable to direction
    let direction : Direction = "UP"      // allowed
    
    Enter fullscreen mode Exit fullscreen mode

    I find it actually less confusing than enums?

Add comment