Learn TypeScript - Union, Intersection, and Literal Types
Episode 4 of 23

Learn TypeScript - Union, Intersection, and Literal Types

This episode unlocks TypeScript's expressive power: union types with the | operator for values that can take several shapes, literal types to lock in specific values, and intersection types with the & operator to combine object types.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

The primitive types from episode 3 are the raw materials. Episode 4 teaches you how to combine them to reflect real data — because real-world data rarely has a single type. An ID can be a number or a string, an order status can be one of five possibilities, and an object can be a combination of several shapes.

Three concepts you'll master: union types for values that can take several forms, literal types to lock in specific values, and intersection types to combine object shapes. Together they're the foundation for building accurate domain models.

Union Type

Values with Several Possible Shapes

A union type is written with the pipe operator |:

Union type
type Id = string | number;
 
let userId: Id = 123;
userId = "a1b2c3"; // valid, masih bertipe Id
 
function formatId(id: Id): string {
    return String(id);
}

The declaration type Id = string | number; means an Id value can hold a string or a number. This union is often used for IDs coming from different sources, for example from a database or from URL parameters.

Using Union Values Safely

A problem arises when the union value is used: TypeScript doesn't allow operations that only apply to one of its members. For example, toUpperCase can't be called directly on string | number — the compiler doesn't know which shape you're holding.

Narrow first before using
function sambut(id: Id): string {
    if (typeof id === "string") {
        return id.toUpperCase();
    }
    return `Nomor: ${id}`;
}

The typeof id === "string" check above narrows the type inside the if block. This is called type narrowing, and we'll cover it thoroughly in episode 11.

Literal Types

Locking Specific Values

Besides restricting the kind of a value, TypeScript can restrict specific values:

Literal types
type Metode = "GET" | "POST" | "PUT" | "DELETE";
type Tahap = "idle" | "loading" | "sukses" | "gagal";
 
let tahap: Tahap = "loading";
tahap = "sukses"; // valid
tahap = "batal";  // error: "batal" tidak ada di union

The Tahap type above only allows four specific strings. The payoff is huge: misspelling a status becomes an immediate error, not a hard-to-track runtime bug.

Literal Unions as Lightweight Enums

Combining literals with unions is the most recommended alternative to enum (details in episode 6):

Literal union for status
type StatusOrder = "baru" | "diproses" | "dikirim" | "selesai" | "dibatalkan";
 
function cekStatus(status: StatusOrder): string {
    return `Order sedang dalam tahap: ${status}`;
}
 
console.log(cekStatus("dikirim"));

Intersection Type

Combining Object Shapes

An intersection type is written with the & operator and requires the value to satisfy all shapes at once:

Intersection type
type Identitas = {
    nama: string;
};
 
type Karyawan = Identitas & {
    jabatan: string;
    gaji: number;
};
 
const budi: Karyawan = {
    nama: "Budi",
    jabatan: "Engineer",
    gaji: 15_000_000,
};

The variable budi: Karyawan must have all the fields from Identitas plus the extra fields from the inline declaration. Intersections are most useful for combining types from several sources, such as user data from two different APIs.

Union vs Intersection: When to Use Which

The easiest distinction to remember:

  • Union means "one of": a value of type A | B is shaped like A or B.
  • Intersection means "all at once": a value of type A & B is shaped like A and B simultaneously.

Warning

Don't confuse this with the meaning of "intersection" in set theory. On objects, A & B merges properties — the value must satisfy both. For value sets like literals, the meaning is indeed an intersection. Focus on the object case, which is what you'll use most often.

In practice, unions are used far more often than intersections. Literal unions for status, unions for nullable values, and discriminated unions in episode 11 will become your main tools. Intersections are rarer, but irreplaceable when combining object types from different sources.

Closing

Episode 4 gave you the two most important operators for designing types: | for choices and & for combining, plus literal types for locking in values. You can now model IDs, statuses, and composite objects accurately.

Key takeaways:

  • A union string | number means the value can be either shape.
  • Literal types lock in specific values, for example "GET" | "POST".
  • Literal unions are a lightweight, recommended alternative to enums.
  • An intersection A & B merges the properties of both types.
  • Narrowing with typeof is required before using a union value.
  • Unions for choices; intersections for merging objects.

In the next episode 5 we'll discuss interface, type alias, and type declarations — the main way to name and define recurring object shapes, plus when to choose interface and when to choose type.

Learn TypeScript - Union, Intersection, and Literal Types | Learn TypeScript