cf.completefrontend
Open lab My progress
THE TYPESCRIPT FIELD GUIDE

Enums

Name a fixed set of choices with a TypeScript enum, see the JavaScript it turns into, and learn when a literal union does the same job with no extra code.

By the end, you can
  • 01
    Write an enumMake numeric and string enums, predict each member's value, and read the errors TypeScript gives for a wrong value.
  • 02
    Know what it becomesRead the JavaScript tsc writes for an enum and a const enum, including the reverse mapping from numbers to names.
  • 03
    Pick enum or unionReplace an enum with a literal union or an as const object, and say when each one fits better.

Names for a fixed set of choices

An order on a shop page is pending, shipped, or delivered. Many apps store that as a number, because numbers are small and quick to compare. Here is what that looks like in plain JavaScript:

An order status stored as a numberPop out in the code editor (opens in a new tab)JavaScript
const order = { id: 7, status: 1 };

if (order.status === 1) {
  console.log("Your order is on its way");
}

Line 1 makes order 7 with a status of 1. Line 3 checks whether the status is 1, and line 4 prints Your order is on its way. It works, but what does 1 mean? You have to remember, or find a comment somewhere, that 1 means "shipped". Type a 2 by mistake and nothing tells you.

TypeScript has a feature for this, called an enum (short for "enumeration", a list of every option). An enum gives names to a fixed set of values. Each name in it is a member:

The same status as an enumPop out in the code editor (opens in a new tab)TypeScript
enum OrderStatus {  Pending,  Shipped,  Delivered,} const order = { id: 7, status: OrderStatus.Shipped }; if (order.status === OrderStatus.Shipped) {  console.log("Your order is on its way");}console.log(order.status);

Lines 1 to 5 make an enum called OrderStatus with three members: Pending, Shipped, and Delivered. You read a member like a property, with a dot: line 7 gives the order the status OrderStatus.Shipped, and line 9 compares with it. Line 10 prints Your order is on its way.

Line 12 shows what the status really is: it prints 1. You didn't write any numbers. TypeScript numbered the members for you, counting from 0, so Pending is 0, Shipped is 1, and Delivered is 2. Your code reads like words, and still stores the small number.

Three tags, Pending, Shipped, and Delivered, the names you write. Each has an arrow to a card with its value when the code runs: 0, 1, and 2.the names you writePendingShippedDeliveredthe values when it runs012
In your code you write the names, like OrderStatus.Shipped. When the code runs, each name stands for a number, counting up from 0.

An enum is also a type. status: OrderStatus means "one of the three statuses". Try it: type a value for line 7 and watch the list under the code.

Playground: type the order's status
An order statusPop out in the code editor (opens in a new tab)TypeScript
enum OrderStatus {  Pending,  Shipped,  Delivered,} const status: OrderStatus = OrderStatus.Shipped;console.log(status);
Line 7 holdsOrderStatus.Shipped
What happens
TypeScriptNo errors
When it runsprints 1
Try it yourself

OrderStatus.Shipped is a member of the enum, so it fits. Its value is the number 1, because members count up from 0.

The code is checked by the real TypeScript compiler each time you type. Only line 7 changes. Reset puts OrderStatus.Shipped back.

OrderStatus.Delivered fits and prints 2. A typo like OrderStatus.Shiped gets an error that suggests the right name. The text "Shipped" gets an error, because a name in quotes isn't the member. The surprise is 1: no error, because some member has the value 1. 7 gets an error, because no member does.

Real-life analogyThe program buttons on a washing machine

A washing machine has a few programs. Inside, its computer knows them as program 0, 1, and 2. But the buttons on the front say Cotton, Wool, and Quick, so you never have to remember which number is which. You press Wool, and the machine gets 1. There's no button for a program the machine doesn't have.

In real life: The machine has a fixed set of programs
In TypeScript: An enum has a fixed set of members
In real life: The buttons say Cotton, Wool, Quick
In TypeScript: You write OrderStatus.Shipped
In real life: Inside, the machine runs program 0, 1, or 2
In TypeScript: When the code runs, Shipped is the number 1
In real life: There's no button for a program that doesn't exist
In TypeScript: A member that doesn't exist gets an error
The main idea

An enum gives names to a fixed set of values. You write OrderStatus.Shipped, and when the code runs that name stands for a number, like 1, or a string. Unlike a type alias, an enum doesn't disappear: TypeScript turns it into a JavaScript object.

Numeric and string enums

An enum whose members are numbers is a numeric enum. If you give the first member a number, the rest count up from there:

A priority that starts at 1Pop out in the code editor (opens in a new tab)TypeScript
enum Priority {  Low = 1,  Medium,  High,} let level = Priority.Medium;//  ^?console.log(level, Priority.High);

Line 2 says Low = 1. Lines 3 and 4 have no number, so Medium is 2 and High is 3. Line 7 stores the medium priority, and the query on line 8 shows let level: Priority: the variable can hold any of the three. Line 9 prints 2 3.

You saw that a numeric enum accepts the number 1. It goes further than that, and this is the weak spot of numeric enums:

Numbers going into a numeric enum (an error on purpose)Pop out in the code editor (opens in a new tab)TypeScript
enum Priority {  Low = 1,  Medium,  High,} const typed: Priority = 2;const tooBig: Priority = 7; const fromServer: number = 7;const loose: Priority = fromServer;console.log(typed, tooBig, loose);

Line 7 stores the number 2, which is Medium's value, so it's fine. Line 8 stores 7, and TypeScript marks it on purpose: Type '7' is not assignable to type 'Priority', "no member has the value 7". But line 10 makes a plain number, the way a value from a server would arrive, and line 11 stores it with no error. TypeScript checks a number you write in the code; any value whose type is just number gets in. Line 12 prints 2 7 7.

The other kind is a string enum. Each member gets a text value, written with =. There's no counting, so you write every value:

A string enum for the theme (an error on purpose)Pop out in the code editor (opens in a new tab)TypeScript
enum Theme {  Light = "light",  Dark = "dark",} function setTheme(theme: Theme) {  console.log(`Switched to ${theme}`);} setTheme(Theme.Dark);setTheme("dark");

Lines 1 to 4 make Theme, whose Light member is the text "light" and Dark member is "dark". Line 6 says setTheme takes a Theme. Line 10 passes Theme.Dark, which fits. Line 11 passes the text "dark", and TypeScript marks it on purpose: Argument of type '"dark"' is not assignable to parameter of type 'Theme'. The value is the same, but a string enum accepts only its members. Run it anyway, and both lines print Switched to dark.

String values are easier to read: a log or a saved setting says dark, not 1. The table below compares the two kinds. Read each row as a question, then the answer for each kind.

Numeric and string enums, side by side
QuestionNumeric enumString enum
How are the values set?They count up from 0, or from the first number you give.You give every member its text, like Dark = "dark".
What does a value look like when you log it?A number, like 1, which says little on its own.Its text, like dark, which you can read.
Does a plain value fit, like 1 or "dark"?A number you write fits if a member has it. Any number from a variable fits.No. Only the members fit, like Theme.Dark.
Can you look up a name from a value?Yes: OrderStatus[1] is "Shipped".No. A string enum has no reverse mapping.

What an enum compiles to

Most of TypeScript is types, and types are removed before the code runs. An enum is different: your code reads OrderStatus.Shipped while it runs, so something called OrderStatus has to exist. Here is a small enum:

An enum, and two reads from itPop out in the code editor (opens in a new tab)TypeScript
enum OrderStatus {  Pending,  Shipped,  Delivered,} console.log(OrderStatus.Shipped);console.log(OrderStatus[1]);

Line 7 reads a member by name and prints 1. Line 8 reads with a number in square brackets and prints Shipped. That second read only works because of the JavaScript the TypeScript compiler, tsc, writes for the enum:

What tsc writes for the enumPop out in the code editor (opens in a new tab)JavaScript
var OrderStatus;
(function (OrderStatus) {
    OrderStatus[OrderStatus["Pending"] = 0] = "Pending";
    OrderStatus[OrderStatus["Shipped"] = 1] = "Shipped";
    OrderStatus[OrderStatus["Delivered"] = 2] = "Delivered";
})(OrderStatus || (OrderStatus = {}));
console.log(OrderStatus.Shipped);
console.log(OrderStatus[1]);

In plain words, line by line:

  1. Line 1 makes a variable, OrderStatus, with no value yet.
  2. Lines 2 to 6 are a function that runs as soon as it's made. Line 6 calls it, with OrderStatus || (OrderStatus = {}): if the variable is empty, it first gets a new empty object (the Logical operators lesson covers ||).
  3. Line 3 does two stores in one. The inner part, OrderStatus["Pending"] = 0, stores the number 0 under the name Pending. An assignment gives back the value it stored, 0, so the outer part becomes OrderStatus[0] = "Pending": the name stored under the number.
  4. Lines 4 and 5 do the same for Shipped (1) and Delivered (2).
  5. Lines 7 and 8 are your two reads, unchanged.

Step through it and watch the object fill up:

Step through the enum's JavaScript
Step 0 of 10Ready
Your turn: follow the blue line

This replays the JavaScript tsc writes for the enum, one assignment at a time. Watch the object fill up with six entries: three names and three numbers.

Running in
  1. script
Next: line 1
(function (OrderStatus) {    OrderStatus[OrderStatus["Pending"] = 0] = "Pending";    OrderStatus[OrderStatus["Shipped"] = 1] = "Shipped";    OrderStatus[OrderStatus["Delivered"] = 2] = "Delivered";})(OrderStatus || (OrderStatus = {}));console.log(OrderStatus.Shipped);console.log(OrderStatus[1]);
CallStoreChangeResultBlue line: runs next. Ran: already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

Each member leaves two entries: one from the name to the number, and one from the number back to the name. The second kind is called a reverse mapping. It's why OrderStatus[1] gives "Shipped", which helps when a number arrives and you want to show its name.

A window named OrderStatus, the object the JavaScript makes. Left column, names to numbers: Pending: 0, Shipped: 1, Delivered: 2. Right column, numbers to names: 0: "Pending", 1: "Shipped", 2: "Delivered".OrderStatusnames to numbersPending: 0Shipped: 1Delivered: 2numbers to names0: "Pending"1: "Shipped"2: "Delivered"
After lines 1 to 6 run, OrderStatus is an object with six entries. Each name leads to its number, and each number leads back to its name, so OrderStatus[1] is "Shipped".

The reverse mapping has a side effect. The object has six keys, not three:

Listing a numeric enum's keysPop out in the code editor (opens in a new tab)TypeScript
enum OrderStatus {  Pending,  Shipped,  Delivered,} console.log(Object.keys(OrderStatus).join(", "));console.log(Object.keys(OrderStatus).length);

Line 7 lists the object's keys with Object.keys and prints 0, 1, 2, Pending, Shipped, Delivered. Line 8 prints 6. If you build a menu from a numeric enum's keys, you'll get the numbers too. String enums don't have this problem:

A string enumPop out in the code editor (opens in a new tab)TypeScript
enum Theme {  Light = "light",  Dark = "dark",} console.log(Theme.Dark);
What tsc writes for the string enumPop out in the code editor (opens in a new tab)JavaScript
var Theme;
(function (Theme) {
    Theme["Light"] = "light";
    Theme["Dark"] = "dark";
})(Theme || (Theme = {}));
console.log(Theme.Dark);

Lines 3 and 4 store only the name to the text, like Theme["Dark"] = "dark". A string enum has no reverse mapping, so Object.keys(Theme) lists just Light and Dark. Line 6 prints dark.

const enums leave no object

Write const before enum and you get a const enum. It works the same in your code, but tsc doesn't write an object for it. Instead it copies each member's value to every place that uses it:

A const enum for sizesPop out in the code editor (opens in a new tab)TypeScript
const enum Size {  Small = "S",  Large = "L",} const pick = Size.Large;console.log(pick);
What tsc writes for the const enumPop out in the code editor (opens in a new tab)JavaScript
const pick = "L" /* Size.Large */;
console.log(pick);

In the TypeScript, lines 1 to 4 make Size, and line 6 reads Size.Large. In the JavaScript, there's no Size at all. Line 1 holds the value "L" itself, with a comment saying which member it came from. This is called inlining. Line 2 prints L.

A file sizes.ts holds const enum Size and const pick = Size.Large. An arrow labelled value copied in leads to sizes.js, which holds only const pick = "L".sizes.tsconst enum Size {…}const pick = Size.Large;you write thisvaluecopied insizes.jsconst pick = "L";the browser runs this
tsc copies the value "L" to the place that used Size.Large, and writes nothing for the enum itself. No Size object exists when the code runs.

Because there's no object, you can only read members of a const enum, never use the enum itself as a value:

Listing a const enum's values (an error on purpose)TypeScript
const enum Size {  Small = "S",  Large = "L",} console.log(Object.values(Size).join(", "));

Line 6 passes Size to Object.values, and TypeScript marks it on purpose: 'const' enums can only be used in property or index access expressions …. In plain words: you may write Size.Large or Size["Large"], and nothing else, because there will be no Size to pass.

One more thing to know. Inlining needs the type checker, because tsc must know each member's value. Many build tools turn TypeScript into JavaScript one file at a time, without checking types, and so does this page's editor. They keep a const enum as an ordinary object instead. Your code works the same either way, but don't count on the object being gone.

Literal unions instead

Many teams don't use enums at all. A union of exact texts does most of the same job, with no JavaScript left over. Each option is a literal type: a type that allows one exact value. Here is a search page's sort menu:

Sort options as a literal union (an error on purpose)Pop out in the code editor (opens in a new tab)TypeScript
type SortOrder = "relevance" | "price-low" | "price-high"; function sortLabel(order: SortOrder) {  return `Sorted by ${order}`;} console.log(sortLabel("price-low"));console.log(sortLabel("cheapest"));

Line 1 says a SortOrder is one of three exact texts. Line 3 says sortLabel takes one. Line 7 passes "price-low", which fits, and prints Sorted by price-low. Line 8 passes "cheapest", which isn't an option, and TypeScript marks it on purpose: Argument of type '"cheapest"' is not assignable to parameter of type 'SortOrder'. So you get the same safety as an enum: only the listed options fit, and the editor suggests them when you type a quote.

What you don't get is names like SortOrder.PriceLow. If you want them, write a plain object with as const, which keeps every value exact and read-only:

Sort options as an as const objectPop out in the code editor (opens in a new tab)TypeScript
const SortOrder = {  Relevance: "relevance",  PriceLow: "price-low",  PriceHigh: "price-high",} as const; type SortOrder = (typeof SortOrder)[keyof typeof SortOrder];//   ^? function sortLabel(order: SortOrder) {  return `Sorted by ${order}`;} console.log(sortLabel(SortOrder.PriceLow));console.log(sortLabel("price-high"));

Lines 1 to 5 are an ordinary JavaScript object with three names and three texts. Line 7 makes the type, and reads from the inside out:

  • typeof SortOrder is the type of the object on line 1.
  • keyof typeof SortOrder is its names: "Relevance" | "PriceLow" | "PriceHigh".
  • The square brackets look up the values at those names, which gives the union of the three texts.

The query on line 8 shows the result: type SortOrder = "relevance" | "price-low" | "price-high". The object and the type can share the name SortOrder, because one is a value and the other is a type. Line 14 uses a name, line 15 uses plain text, and both fit. They print Sorted by price-low and Sorted by price-high. (The keyof & typeof lesson explains line 7 in full.)

Compare the three ways side by side. Each button shows the same sort menu:

Playground: three ways to write the sort options
A sort menu's optionsPop out in the code editor (opens in a new tab)TypeScript
enum SortOrder {  Relevance = "relevance",  PriceLow = "price-low",  PriceHigh = "price-high",} function sortLabel(order: SortOrder) {  return `Sorted by ${order}`;} console.log(sortLabel(SortOrder.PriceLow));console.log(sortLabel("price-high"));
Console outputSorted by price-low, Sorted by price-high
What happens
TypeScript1 error: line 12
Plain text fitsNo
Left in the JavaScripta SortOrder object
Try it yourself

Line 11 passes the member SortOrder.PriceLow, which fits. Line 12 passes the text "price-high", and a string enum doesn't accept it: Argument of type '"price-high"' is not assignable to parameter of type 'SortOrder'. tsc also writes a SortOrder object into the JavaScript.

TypeScript checks the code for real each time you press a button, and the output is what the code prints. Reset goes back to A string enum.

All three print the same thing. They differ in two places: whether plain text like "price-high" fits, and what tsc leaves in the JavaScript.

Three windows, each showing the JavaScript tsc writes for the sort options. A string enum leaves a SortOrder object. A literal union leaves nothing. An as const object leaves the object you wrote.string enumsort.jsvar SortOrder;(function …)an object tsc makesliteral unionsort.jsnothingthe type is removedas const objectsort.jsconst SortOrder= { … };the object you wrote
After tsc removes the types, a string enum still leaves an object it made, a literal union leaves nothing, and an as const object stays because it's ordinary JavaScript you wrote.

That last difference matters more than it used to. Node.js can now run a .ts file by only removing its types, and some build tools work the same way. An enum can't run there, because it's code that has to be written, not a type that can be removed. TypeScript 5.8 added a setting, erasableSyntaxOnly, that reports anything like this:

An enum with erasableSyntaxOnly on (an error on purpose)Pop out in the code editor (opens in a new tab)TypeScript
enum Theme {  Light = "light",  Dark = "dark",} type ThemeName = "light" | "dark";const saved: ThemeName = "dark";console.log(Theme.Dark, saved);

The list under the code shows the setting this example turns on. Line 1 gets This syntax is not allowed when 'erasableSyntaxOnly' is enabled, on purpose. Line 6, a literal union, is only a type, so it's fine. Line 8 prints dark dark.

The table below sums up the choice. Read each row as a question, then the answer for each way.

An enum or a literal union
QuestionEnumLiteral union
Is anything left in the JavaScript?Yes, an object, unless it's a const enum.No. The type is removed.
Does plain text like "price-high" fit?Not for a string enum. You write SortOrder.PriceHigh.Yes, if it's one of the options.
Does the editor suggest the options?Yes, after you type SortOrder..Yes, when you type a quote.
Can the code list every option while it runs?Yes, with Object.values, but a numeric enum lists its numbers too.Not from the type alone. Keep the options in an as const object if you need the list.
Does it run where types are only removed, like Node.js running a .ts file?No. An enum is code that tsc has to write.Yes. It's only a type.

A simple rule: reach for a literal union first, and an as const object when you also want names or a list of the options. Use an enum when your project already does, or when you want a numeric code with readable names, and know that it becomes an object.

A status badge from a server reply

An order page gets the order's status from a server, as text, and shows a badge for it. A string enum fits well here: its values match the server's text, and the code reads OrderStatus.Shipped. The careful part is turning the server's text into an OrderStatus:

A badge for an order's statusPop out in the code editor (opens in a new tab)TypeScript
enum OrderStatus {  Pending = "pending",  Shipped = "shipped",  Delivered = "delivered",} function badge(status: OrderStatus) {  switch (status) {    case OrderStatus.Pending:      return "Waiting to ship";    case OrderStatus.Shipped:      return "On its way";    case OrderStatus.Delivered:      return "Delivered";  }} function toStatus(text: string) {  return Object.values(OrderStatus).find((status) => status === text);} const reply = JSON.parse('{ "id": 7, "status": "shipped" }');const status = toStatus(reply.status);//    ^?console.log(status ? badge(status) : "Unknown status");console.log(toStatus("lost") ?? "Unknown status");

Lines 1 to 5 make the enum, with the same texts the server sends. Lines 7 to 16 choose the badge text with a switch, one case per member. Lines 18 to 20 turn text into a status: Object.values(OrderStatus) lists the three texts, and find gives back the one that matches, or undefined if none does.

Line 22 reads the server's reply with JSON.parse. Line 23 turns its status into an OrderStatus, and the query on line 24 shows const status: OrderStatus | undefined: TypeScript knows the text might not match. Line 25 checks before it calls badge, and prints On its way. Line 26 tries the text "lost" and prints Unknown status.

Why not pass reply.status straight to badge? JSON.parse gives back any, the type TypeScript doesn't check (see any, unknown & never), so it would let anything through, even "lost". Checking the text against the enum's values first means badge only ever gets a real status.

Error or fine?
  • enum Size { Small, Large } const s: Size = Size.Large;
  • enum Size { Small, Large } const s: Size = 5;
  • enum Theme { Dark = "dark" } const t: Theme = "dark";
  • enum Theme { Dark = "dark" } const t: Theme = Theme.Dark;
  • type Theme = "light" | "dark"; const t: Theme = "dark";
  • const enum Size { Small, Large } console.log(Object.keys(Size));
  • enum Size { Small, Large } console.log(Size[0]);
  • enum Theme { Dark = "dark" } console.log(Theme.Drak);
Try it yourself
0 of 8 correct

Sort each line by what TypeScript says about it. Each line is checked on its own.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Common mix-ups

  • "An enum is only a type, like a type alias." No. tsc writes an object for it, and your code reads that object while it runs. Only a const enum is removed, and only when tsc compiles it.
  • "A numeric enum only accepts its members." No. A number you write is checked, but any value of type number gets in, so Priority can end up holding 7.
  • "A string enum accepts its text." No. "dark" doesn't fit a Theme, even though Theme.Dark is "dark". A literal union accepts it.
  • "Object.keys gives an enum's names." Only for a string enum. A numeric enum also lists its numbers, because of the reverse mapping.
  • "Members are numbered from 1." No. They start at 0, unless you give the first one a number.
  • "An enum checks the server's text for me." No. Like every type, it can't see data that arrives while the page runs. Compare the text with Object.values, as the badge code does.

Practice exercises

Each exercise is TypeScript. Press Edit & run on the starter code to try your answer: the errors update as you type, and the console shows what it prints. Try a guess first, then use the hints.

Exercise 1 · Warm-upCount the members

A checkout has four steps. What does line 8 print?

Starter codePop out in the code editor (opens in a new tab)TypeScript
enum Step {  Cart,  Address,  Payment,  Done,} console.log(Step.Payment);

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · Warm-upFind the line TypeScript marks

    Two saved themes, one with a mistake. Which line will TypeScript mark?

    Starter codePop out in the code editor (opens in a new tab)TypeScript
    enum Theme {
      Light = "light",
      Dark = "dark",
    }
    
    const saved: Theme = Theme.Light;
    const chosen: Theme = "dark";

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeStart counting at 1

      The priorities should be numbered 1, 2, 3, to match the server. Change one line so they are. What does the code print now?

      Starter codePop out in the code editor (opens in a new tab)TypeScript
      enum Priority {  Low,  Medium,  High,} console.log(Priority.High);

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeLook up a name from a number

        A server sends the status as the number 2. What does line 8 print?

        Starter codePop out in the code editor (opens in a new tab)TypeScript
        enum OrderStatus {  Pending,  Shipped,  Delivered,} const fromServer = 2;console.log(OrderStatus[fromServer]);

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeReplace an enum with a union

          Rewrite Theme as a literal union and fix the call. How many lines of JavaScript does your Theme leave behind?

          Starter codePop out in the code editor (opens in a new tab)TypeScript
          enum Theme {  Light = "light",  Dark = "dark",} function setTheme(theme: Theme) {  console.log(`Switched to ${theme}`);} setTheme(Theme.Dark);

          Answer, then press Check. Spacing and letter case don’t matter.

            Exercise 6 · ChallengeCheck a server's text first

            TypeScript marks line 12: a plain string isn't an OrderStatus. Turn the text into a status before you call badge. What does your fixed code print?

            Starter codePop out in the code editor (opens in a new tab)TypeScript
            enum OrderStatus {  Pending = "pending",  Shipped = "shipped",} function badge(status: OrderStatus) {  return status === OrderStatus.Shipped ? "On its way" : "Waiting";} const reply = JSON.parse('{ "status": "shipped" }');const text: string = reply.status;console.log(badge(text));

            Answer, then press Check. Spacing and letter case don’t matter.

              Check your understanding

              For each question, ask two things: what values the enum has, and what tsc writes for it. The quiz shows its code without the checker, so the error list doesn't give the answers away.

              The enums quiz · 7 questionsScore: first tries count
              1. Question 1 of 7What does Color.Blue print?

                Read the code, then predictPop out in the code editor (opens in a new tab)TypeScript
                enum Color { Red, Green, Blue }
                console.log(Color.Blue);

                Choose an answer to see the explanation.

              2. Question 2 of 7Which of these is still there when the code runs?

                Choose an answer to see the explanation.

              3. Question 3 of 7What does TypeScript say about line 2 of this theme code?

                Read the code, then predictPop out in the code editor (opens in a new tab)TypeScript
                enum Theme { Light = "light", Dark = "dark" }
                const theme: Theme = "dark";

                Choose an answer to see the explanation.

              4. Question 4 of 7What does this enum, which starts at 5, print?

                Read the code, then predictPop out in the code editor (opens in a new tab)TypeScript
                enum Level { Low = 5, High }
                console.log(Level.High, Level[6]);

                Choose an answer to see the explanation.

              5. Question 5 of 7Does TypeScript accept a number from a variable here, and what prints?

                Read the code, then predictPop out in the code editor (opens in a new tab)TypeScript
                enum Level { Low, High }
                const fromServer: number = 9;
                const level: Level = fromServer;
                console.log(level);

                Choose an answer to see the explanation.

              6. Question 6 of 7What does tsc write for line 6 of this const enum?

                Read the code, then predictPop out in the code editor (opens in a new tab)TypeScript
                const enum Size {
                  Small = "S",
                  Large = "L",
                }
                
                const pick = Size.Large;

                Choose an answer to see the explanation.

              7. Question 7 of 7Why might a team write a literal union instead of an enum?

                Choose an answer to see the explanation.

              Key takeaways

              • An enum gives names to a fixed set of values: OrderStatus.Shipped instead of a bare 1.
              • Numeric enums count up from 0, or from the first number you give. String enums give every member its text.
              • A numeric enum accepts any number from a variable; a string enum accepts only its members, not their text.
              • tsc turns an enum into an object. A numeric enum also maps numbers back to names, so Object.keys lists both.
              • A const enum is inlined by tsc and leaves no object, so you can only read its members.
              • A literal union, or an as const object, does the same job with no extra code and runs where types are only removed.

              Remember the one-liner.
              An enum is a named set of values that becomes a real object; a literal union names the same choices and disappears.

              Coming next: Typing functions. It shows how to type a function's parameters and the value it gives back, like the badge function on this page.

              CompleteFrontend Clear concepts. Working examples.