Where State Lives

One when, three screens

Look back at WalkersScreen's body: it doesn't have an if isLoading and a separate if hasError sitting side by side β€” it has one when (val s = state) with three branches, one per UiState case. Because UiState is a sealed interface, the screen is exactly one of loading, success, or error, never some confusing mix. The compiler even checks the when is exhaustive β€” miss a case and it won't build.

Compare that to three separate flags (isLoading: Boolean, walkers: List<Walker>, errorMessage: String?), where "loading AND showing an error" becomes a state you can accidentally construct β€” and will, at the worst possible time. The sealed interface makes that whole bug category impossible to write.