"x === 'literal' is how the compiler verifies your discriminated unions are wired correctly."
Equality as a narrowing operation
Comparing a value to a literal narrows it. if (x === 'red') inside the branch makes the compiler know x is the literal type 'red'. If x was previously 'red' | 'blue' | 'green', it's now just 'red'. In the else branch, it's 'blue' | 'green'.
This is the operator that makes discriminated unions work in switch and chained if statements. if (shape.kind === 'circle') narrows the whole shape object to the circle variant.
Loose equality (==) — almost never use it
JavaScript's == performs type coercion: '1' == 1 is true. TypeScript treats == as a narrowing operator, but the narrowing follows the coercion rules — which are confusing and almost never what you want.
The rule: always use === for narrowing. Reserve == only for explicit null/undefined checks (x == null matches both null AND undefined — a deliberate idiom that's clear in context). Otherwise, strict equality.
Narrowing on === with constants from as const
Combining as const with equality narrowing is a very common pattern. const STATUSES = ['idle', 'loading', 'done'] as const gives you literal types. Then any x === STATUSES[0] correctly narrows x to 'idle'.