DART / CHAPTER 10
Sealed results and exhaustive branching
AdvancedModel alternatives so every result state is handled.
By the end of this chapter
- Define a closed family of result variants
- Destructure variants in switch patterns
- Make new states visible to exhaustive checks
The idea
A sealed class restricts direct subtypes to its library and lets the compiler reason about a known family of alternatives. Represent successful and failed outcomes as separate variants rather than one class with unrelated nullable fields. Each variant can then require exactly the data that makes sense in that state, reducing impossible combinations.
A switch expression can pattern-match the variant and extract its fields. Exhaustiveness checking highlights missing cases when the sealed family changes. Avoid an unnecessary catch-all when the goal is for new variants to trigger review. Static exhaustiveness does not validate arbitrary external messages; decode and validate those at the boundary before constructing trusted result objects.
sealed class Outcome {}
class Good extends Outcome { final int value; Good(this.value); }
class Bad extends Outcome { final String reason; Bad(this.reason); }
String describe(Outcome o) => switch(o) { Good(:final value) => "value=$value", Bad(:final reason) => reason };
void main() { print(describe(Good(4))); }value=4
The Good pattern extracts its required value. The two cases cover the known Outcome variants.
Try it yourself
Model pending, success, and failure variants with an exhaustive display function.
Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.
CHECK YOUR UNDERSTANDING