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

I'm currently working on a small music player component, and I've run into a classic problem. I have a function that updates the UI based on the player's current state. Initially, I did what most of us do: I used a string for the state.

function updatePlayerUI(state: string) {
  if (state === "playing") {
    console.log("Show the pause button");
  } else if (state === "paused") {
    console.log("Show the play button");
  } else if (state === "stopped") {
    console.log("Show the stop button");
  }
}

updatePlayerUI("playing"); // Works great.
updatePlayerUI("paused");  // Still great.

The "Anything Goes" Problem

Here is the issue. Because I told TypeScript that state is a string, TypeScript trusts me implicitly. It thinks any sequence of characters is valid. I tried this just now, and look what happens:

updatePlayerUI("banana"); 

The code compiles. No red squiggly lines. But when I run it, the function does absolutely nothing because "banana" doesn't match any of my if statements. In a real app, this is how silent bugs creep in—you pass a typo like "palying" and spend an hour wondering why the UI isn't updating.

Tightening the Screws

I want TypeScript to scream at me the moment I type something that isn't one of my three valid states. I don't want any string; I want these specific strings. Let's try changing the type definition to use the exact values.

function updatePlayerUI(state: "playing" | "paused" | "stopped") {
  // ... logic remains the same
}

updatePlayerUI("playing"); // This is fine.
updatePlayerUI("banana");  // Error: Argument of type '"banana"' is not assignable to parameter of type '"playing" | "paused" | "stopped"'.

Now we're talking. By using the actual values—"playing", "paused", and "stopped"—instead of the general string type, I've created Literal Types. I'm telling the compiler: "The only valid values for this variable are these exact literals."

It's Not Just for Strings

I wondered if this worked for other types, so I tried it with a priority system for a notification queue. I only want priorities to be 1 (High), 2 (Medium), or 3 (Low). I don't want someone passing in 99 or -1.

function setPriority(level: 1 | 2 | 3) {
  console.log(`Priority set to ${level}`);
}

setPriority(1); // Sweet.
setPriority(5); // Error: Argument of type '5' is not assignable to parameter of type '1 | 2 | 3'.

It works exactly the same way for numbers and booleans. It basically turns a value into a type. I'll admit, writing 1 | 2 | 3 inside a function signature feels a bit clunky if I have to do it in five different places in my code.

Making it Scale

To clean this up, I'll move these literals into a type alias. This makes the code more readable and gives me a single place to add a new state (like "buffering") without hunting through every function signature in my project.

type PlayerState = "playing" | "paused" | "stopped" | "buffering";

function updatePlayerUI(state: PlayerState) {
  // Now it's clean and reusable
}

const currentState: PlayerState = "playing";

One last thing to notice: if you hover over currentState in your editor, you'll see that TypeScript knows exactly which options you have. The autocomplete becomes a superpower here because you aren't guessing what strings the API expects—the IDE just tells you.




📋 Practical Task

Building a State-Driven Notification System

You are building a notification system for a dashboard. The system should only allow three specific severity levels: "info", "warning", and "error". It should also only allow three specific delivery methods: "email", "sms", and "push".

Your Task:

  • Create a type alias called Severity that only allows the three severity literals.
  • Create a type alias called DeliveryMethod that only allows the three delivery literals.
  • Define an interface Notification that uses these two types for its properties.
  • Create a function sendNotification(note: Notification) that logs a message to the console.
  • Try to create a notification object with an invalid severity (e.g., "critical") and observe the TypeScript error.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.