TypeScript

Unions in TypeScript – Complete Guide with Examples

✅ — unions are one of the most powerful and expressive features of TypeScript. They let you describe data that can take on multiple possible forms, making your code safer and clearer.

Here’s a comprehensive, unique explanation with practical examples across different domains.


In JavaScript, a variable can hold any type at runtime. TypeScript makes this safer by introducing union types, which let you explicitly say:

👉 “This value can be either A or B or C.”


1. What is a Union Type?

A union type combines multiple possible types using the | (pipe) operator.

let value: string | number;

value = "Hello"; // ✅
value = 42;      // ✅
value = true;    // ❌ Error: not string or number

Here, value can be string OR number — but nothing else.


2. Unions with Primitive Types

You can restrict variables to specific primitives.

type Status = "loading" | "success" | "error";

let s: Status;

s = "loading"; // ✅
s = "done";    // ❌ Error

👉 This pattern is called a string literal union and is often used instead of enums.


3. Unions with Objects

Union types are not limited to primitives.
You can describe alternative object shapes:

type Dog = { kind: "dog"; bark: () => void };
type Cat = { kind: "cat"; meow: () => void };

type Pet = Dog | Cat;

function interact(pet: Pet) {
  if (pet.kind === "dog") {
    pet.bark(); // ✅ Safe
  } else {
    pet.meow(); // ✅ Safe
  }
}

👉 This is called a discriminated union — each object has a distinguishing field (kind).


4. Functions with Union Parameters

Union types are very useful for function arguments:

function format(input: string | number): string {
  return typeof input === "number" ? input.toFixed(2) : input.toUpperCase();
}

console.log(format(42));     // "42.00"
console.log(format("hello")); // "HELLO"

5. Union with Arrays

Unions apply to arrays too:

let arr: (string | number)[] = ["a", 1, "b", 2];

arr.push("c"); // ✅
arr.push(true); // ❌

6. Narrowing Union Types

Since unions can be broad, TypeScript requires type narrowing before using specific methods.

Ways to narrow:

  1. typeof check function print(x: string | number) { if (typeof x === "string") { console.log(x.toUpperCase()); } else { console.log(x.toFixed(2)); } }
  2. in operator type Car = { drive: () => void }; type Boat = { sail: () => void }; type Vehicle = Car | Boat; function move(v: Vehicle) { if ("drive" in v) v.drive(); else v.sail(); }
  3. Discriminated property type Success = { status: "success"; data: string }; type Error = { status: "error"; message: string }; type Result = Success | Error; function handle(res: Result) { if (res.status === "success") { console.log("Data:", res.data); } else { console.error("Error:", res.message); } }

7. Real-World Examples

(a) API Response Handling

type ApiResponse<T> =
  | { status: "ok"; data: T }
  | { status: "error"; error: string };

async function fetchUser(): Promise<ApiResponse<{ id: number; name: string }>> {
  return { status: "ok", data: { id: 1, name: "Alice" } };
}

(b) React Component Props with Unions

type ButtonProps =
  | { variant: "text"; label: string }
  | { variant: "icon"; icon: string };

const Button = (props: ButtonProps) => {
  if (props.variant === "text") {
    return <button>{props.label}</button>;
  }
  return <button><i className={props.icon}></i></button>;
};

👉 This ensures only valid props combinations are allowed.


(c) Angular Input Model

type InputType = "text" | "email" | "password";

@Component({...})
export class InputComponent {
  @Input() type: InputType = "text";
}

(d) Vue Component with Props

type Size = "small" | "medium" | "large";

export default defineComponent({
  props: {
    size: { type: String as PropType<Size>, required: true }
  }
});

8. Union vs Intersection

  • Union (|) → value can be either A or B.
  • Intersection (&) → value must be A AND B at the same time.
type A = { a: number };
type B = { b: number };

type U = A | B; // either {a} or {b}
type I = A & B; // must have both {a, b}

9. Best Practices for Unions

  • ✅ Use string literal unions instead of enums for lightweight status codes.
  • ✅ Use discriminated unions for safe object modeling.
  • ✅ Always narrow types before accessing union-specific fields.
  • ❌ Don’t create unions that are too large (hard to narrow).
  • ❌ Don’t use any when a union type can give better safety.

10. Conclusion

Unions in TypeScript:

  • Allow variables to hold multiple possible types.
  • Work with primitives, objects, arrays, and functions.
  • Require type narrowing for safe access.
  • Are crucial in API response handling, UI props, and real-world domain modeling.

👉 Mastering unions helps you write expressive, type-safe, and bug-resistant TypeScript code.


Related posts
TypeScript

Literals in TypeScript: String, Number, Boolean, Template, and Compound Literals

Literals are one of the fundamental building blocks of TypeScript programming. They represent fixed…
Read more
TypeScript

Utility Types in TypeScript: Pick, Omit, Partial, Required, Readonly, Record...

✅ — Utility Types are one of the most powerful features of TypeScript, but also one of the most…
Read more
TypeScript

Complete TypeScript Tutorial Online: Master TypeScript in 2025

TypeScript has revolutionized modern web development by bringing static typing to JavaScript, making…
Read more