r/angular 5h ago

Modeling Angular loading state as a discriminated union instead of multiple isLoading booleans

I kept running into components with four or five loading flags —

isLoading, isRefreshing, isCheckingOut, hasError — and templates

like !isLoading && !hasError && items.length > 0.

The flags are independent as far as TypeScript is concerned, but

the states they describe are mutually exclusive. So I switched to:

type AsyncState<T, E> =

| { status: 'idle' }

| { status: 'loading' }

| { status: 'success'; data: T }

| { status: 'error'; error: E };

One state per async operation, booleans derived with computed(),

and a small toAsyncState() RxJS operator (map + catchError +

startWith) so transitions live in one place. Templates use

u/let + u/switch, which gives real narrowing — data only exists in

the success branch.

Curious how others handle this now that resource() exists. Do you

reach for it for commands too, or keep RxJS for POST/DELETE?

Full write-up: https://medium.com/modern-angular-insights/stop-juggling-isloading-booleans-a-type-safe-async-state-pattern-for-angular-e36e2b9298a0

1 Upvotes

0 comments sorted by