What are union types?
1. What a union type is
Union is a type that describes a value that can be one of several possible types.
Syntax:
type MyType = TypeA | TypeB | TypeC;Here the vertical bar | means "or".
A simple example
type ID = string | number;
let userId: ID;
userId = 42; // number
userId = "abc123"; // string
userId = true; // ErrorThe
userIdvalue can be a string or a number, but nothing else.
2. Why union types are needed
Union types are especially useful when:
- a value may come in different formats (for example, an ID from a database or an API);
- a function may accept different argument types;
- an API response may be successful or an error.
Example: different argument types
function formatId(id: string | number) {
return `ID: ${id}`;
}
console.log(formatId(42)); //
console.log(formatId("abc123")) //The
formatIdfunction works with both strings and numbers.
3. Union types and objects
You can combine entire structures, not just primitives:
type User = { role: "user"; name: string };
type Admin = { role: "admin"; permissions: string[] };
type Person = User | Admin;Now the Person variable can be:
const a: Person = { role: "admin", permissions: ["delete"] };
const u: Person = { role: "user", name: "Tim" };TypeScript checks that the object matches at least one shape.
4. Type Narrowing
When a value can be one of several types,
TypeScript can figure out which type is currently in use
if you check it using conditions like typeof, in, instanceof, and so on.
Example with typeof
function logId(id: string | number) {
if (typeof id === "string") {
console.log(id.toUpperCase()); // TS now knows id is a string
} else {
console.log(id.toFixed(2)); // TS now knows id is a number
}
}Example with in
function printUser(person: User | Admin) {
if ("permissions" in person) {
console.log("Admin:", person.permissions);
} else {
console.log("User:", person.name);
}
}TypeScript "narrows" the type itself after checking the property.
5. Union types with literals (literal unions)
A very powerful feature: you can combine specific values, not just types.
type Status = "loading" | "success" | "error";
let currentStatus: Status;
currentStatus = "loading"; //
currentStatus = "done"; // ErrorThis is often used for statuses, roles, and UI or API states.
6. Union types + functions
function printValue(value: string | number | boolean) {
console.log(`Value: ${value}`);
}You can pass a string, a number, or a boolean, and TypeScript will handle it all correctly.
7. Union types vs Intersection types
| Type | Description | Example |
|---|---|---|
A | B | "A or B" (one of the options) | string | number |
A & B | "A and B" (both at once) | {name: string} & {age: number} |
8. Example from a real project
An API response can be one of two types:
type SuccessResponse = {
status: "success";
data: { id: number; name: string };
};
type ErrorResponse = {
status: "error";
message: string;
};
type ApiResponse = SuccessResponse | ErrorResponse;
function handleResponse(res: ApiResponse) {
if (res.status === "success") {
console.log(res.data.name); // TS knows this is a SuccessResponse
} else {
console.error(res.message); // TS knows this is an ErrorResponse
}
}TypeScript figures out on its own which type it is dealing with - this is called a discriminated union.
Summary
Union types (
|) in TypeScript let you describe values that can belong to one of several types.They are used when:
- data can arrive in different formats;
- a function accepts several argument variants;
- API responses have different shapes;
- fields can be restricted to specific literals (
"success" | "error").This makes the code:
- safer (TS checks every branch),
- more flexible (one function can handle different types),
- and clearer for the IDE and autocomplete.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.