Interface & Union Types

Interface & Union Types: A union type is like a restaurant menu line reading 'choose a dessert: baklava OR rice pudding' — only one of those two ever arrives, a third option (say

A union type is like a restaurant menu line reading 'choose a dessert: baklava OR rice pudding' — only one of those two ever arrives, a third option (say, soup) never shows up at the table. So why not just write `any` and say 'the ID can be anything'? Because any removes the waiter's boundary entirely, leaving what comes out of the kitchen completely unpredictable; a union keeps the boundary by saying 'only these two' — Java has no direct equivalent, the closest is faking the same result with generics or method overloads and noticeably more code. The concrete QA payoff: when an API's `id` field sometimes arrives as a number and sometimes as a string, a function typed as `id: number | string` forces you to handle both cases at compile time; a function that assumes a single type silently misbehaves at runtime the moment it meets the other format.

Union type and discriminated union pattern

type Status = "PASS" | "FAIL" | "SKIP" — value can only be one of these three

status: "success" | "error" — this discriminant field tells TypeScript which type it is

if (res.status === 'success') — TypeScript then guarantees res.data exists

Order the steps to handle an API response with discriminated union:

Define union type with 'success' | 'error' discriminant

Branch with if (res.status === "success")

In success branch, safely access res.data

In error branch, display res.message

type ApiResponse = { status: 'success'; data: unknown } | { status: 'error'; message: string } — accessing res.message in the if (res.status === 'success') branch?

Compile error — TypeScript knows message doesn't exist in success branch

Returns undefined — field is absent so undefined

Works — TypeScript makes message optional