Union Types for Flexibility in TypeScript
Learn how to use Union Types in TypeScript to allow variables to hold multiple values, enabling flexible and robust code for your task management system.

Previously in this course, we explored defining object shapes with interfaces and handling optional properties. While interfaces allow us to model complex data, sometimes a single variable needs the flexibility to represent more than one type—for instance, a task status that might be a string or a numerical code.
This lesson introduces Union Types, a powerful feature that allows a variable to hold values of several different types, and demonstrates how to safely interact with them.
Defining Union Types
A union type is formed by combining two or more other types using the pipe (|) character. Think of it as an "OR" operator for types. When you declare a variable as string | number, you are telling TypeScript that the variable is allowed to be either a string or a number, but nothing else.
This is essential for real-world scenarios where data sources might return inconsistent formats, or where a single API field serves dual purposes.
TYPESCRIPT// A variable that can be a string or a number let taskId: string | number; taskId = "task-101"; // Valid taskId = 101; // Also valid taskId = true; // Error: Type CE9178">'boolean' is not assignable to type CE9178">'string | number'
Applying Unions to Task Statuses

In our running project—the task API client—we often encounter statuses that might arrive as different types depending on the backend version. Let’s update our Task interface to reflect this flexibility.
Suppose our API currently supports both a human-readable string (e.g., "pending") and a numeric status code (e.g., 0).
TYPESCRIPTinterface Task { id: number; title: string; // The status can be a string OR a number status: string | number; } const task1: Task = { id: 1, title: "Learn TypeScript", status: "in-progress" }; const task2: Task = { id: 2, title: "Build API Client", status: 1 };
Narrowing Types Using Conditionals
The challenge with union types is that TypeScript doesn't know which type is currently stored in the variable at any given moment. If you try to call a method like .toUpperCase() on a string | number, TypeScript will throw an error because numbers don't have that method.
To solve this, we use type narrowing. We can use conditional logic to check the type before performing operations on it. This is similar to how we use control logic in JavaScript to handle different inputs.
TYPESCRIPTfunction getStatusLabel(status: string | number): string { // Narrowing: Check if the type is a string if (typeof status === "string") { return status.toUpperCase(); } else { // TypeScript knows status must be a number here return CE9178">`STATUS_CODE_${status}`; } }
By checking the type with typeof inside an if block, we "narrow" the scope of the variable. Inside the if, the compiler treats status as a string. In the else, it treats it as a number.
Hands-on Exercise
Update your current task management code to include a priority field in your Task interface.
- Define
priorityasstring | number. - Create a function
formatPrioritythat accepts this priority. - If the priority is a number, return a message like "Priority Level: X".
- If the priority is a string, return the string capitalized.
- Test your function with both a string and a number.
Common Pitfalls

- Forgetting to narrow: The most common mistake is attempting to access properties or methods specific to one member of the union without checking the type first. Always use an
iforswitchto safely access data. - Over-using
any: When faced with a complex union, it is tempting to switch toany. Avoid this! Union types allow you to maintain type safety while embracing flexibility. If your union becomes too large (e.g., 5+ types), it is usually a sign that you should refactor your data model into a more specific structure. - Assuming exclusivity: Remember that a union type includes all listed types. If you define
string | number, you must be prepared to handle both cases in your application logic.
FAQ
Q: Can I include more than two types in a union?
A: Yes! You can chain as many types as you need using the pipe operator, such as string | number | boolean | null.
Q: Does the order of types in a union matter?
A: No, string | number is identical to number | string.
Q: Are union types only for primitives? A: Not at all. You can create unions of object types, interfaces, or even specific literal values, which we will explore in upcoming lessons.
Recap

Union types are the primary tool for representing variables that can hold multiple types. By combining types with | and narrowing them using typeof checks in your conditional logic, you keep your code flexible without sacrificing the safety guarantees that make TypeScript valuable.
Up next: We will explore Literal Types, which allow us to restrict variables to very specific values, further refining our task status management.
Work with me

React & Next.js Dashboard / Admin UI Development
A clean, data-rich dashboard UI in React or Next.js — charts, tables, and real-time data that your users will actually enjoy using.

Next.js Full-Stack Web App Development
A fast, SEO-ready full-stack web app built with Next.js 16 — from idea to deployed product, by an engineer who ships to production.


