A response type with four optional properties permits sixteen shapes, of which three are valid.
// before
interface Result {
status: string
data?: Order
error?: string
retryAfter?: number
}
// after
type Result =
| { status: 'ok'; data: Order }
| { status: 'error'; error: string }
| { status: 'retry'; retryAfter: number }
The compiler now narrows on status, so the branch that reads data is the branch where it exists — no non-null assertions and no defensive checks. The discriminant has to be a literal type on every member, and a member without one silently disables the narrowing, which produces errors that read as if the union itself is wrong.