Discriminated (tagged) union — набор object types с общим литеральным полем (kind, status, type), по которому компилятор сужает весь union в switch/if. Лучший паттерн моделирования state: невозможные состояния непредставимы + exhaustiveness на compile time.
Антипаттерн — мешок optional-полей: { isLoading: boolean; data?: T; error?: Error }. Допускает nonsense — loading и error, data и error сразу — UI вынужден защищаться вечно. Discriminated union: запрос ровно один из { status: 'loading' }, { status: 'success'; data: T }, { status: 'error'; error: Error }. Нелегальные комбинации буквально не сконструировать.
Discriminant — общее literal-typed свойство. При state.status === 'success' TS сужает union к этому члену и открывает data. Одно «почти boolean» поле превращает ambiguous shape в state machine, которую компилятор проверяет.
Итог
Tagged union с литеральным discriminant делает impossible states unrepresentable и включает exhaustiveness.