TypeScript: remove impossible states
A small pattern worth keeping around: discriminated unions make a React or Astro component much more robust.
Posted on · by Naomi
When an interface can be in several states, the classic trap is to split the logic across independent booleans such as loading, error, and success. That usually creates ambiguous combinations and makes testing harder than it should be.
A discriminated union removes that ambiguity by making each state explicit.
1. Define the model
export type LoadState<T> = | { status: 'idle' } | { status: 'loading' } | { status: 'success'; data: T } | { status: 'error'; message: string };The compiler becomes an ally: if I introduce a new state, every switch that depends on it has to be updated. No forgotten branches.
2. Consume the state unambiguously
switch (state.status) { case 'loading': return <span>Loading…</span>; case 'error': return <span role="alert">{state.message}</span>; case 'success': return <span>{state.data.title}</span>; default: return null;}This pattern fits Astro React islands beautifully: a tiny interactive component, but with strict business logic that stays easy to audit.
3. Let compilation catch regressions
npm run lintThe real benefit is that the editor and the CI pipeline see the same truth. If an enum-like state is missing or a branch is not covered, the issue surfaces before deploy time.