Dart Sealed Class vs State Pattern: Which to Pick
Choosing between sealed classes and state objects for UI logic? This head-to-head compares the classic State pattern against Dart 3's sealed classes for replacing enum switches in Flutter.
Here's the short answer to dart sealed class vs state pattern : if your states are mostly *data* that the UI renders differently, sealed classes win — the compiler checks your switch for you. If your states carry *behavior* — different validation rules, different allowed transitions, different side effects — state objects win. Both beat a sprawling enum switch. The rest of this article is the full comparison, with working code for each side and a verdict you can apply today. The Choice, Stated Plainly Every Flutter developer eventually writes this: enum WizardStep { personal, address, review } String stepTitle(WizardStep step) { switch (step) { case WizardStep.personal: return 'Personal details'; case WizardStep.address: return 'Address'; case WizardStep.review: return 'Review'; } } bool canProceed(WizardStep step, Map<String, String> answers) { switch (step) { case WizardStep.personal: return answers['name']?.isNotEmpty == true; case WizardStep.address: return answers['city']?.isNotEmpty == true; case WizardStep.review: return true; } } One enum, N switches scattered across the codebase. Add a fourth step and you must find every switch by hand — miss one and the compiler says nothing, because a non-exhaustive switch on an enum without a default is only a warning away from a runtime surprise. You have two idiomatic escapes in modern Dart: Option A — the classic State pattern: turn each step into a class that owns its title, its validation, and its transition to the next step. Option B — sealed classes: keep the switch, but switch over a closed hierarchy so the compiler *forces* every case to be handled. Both kill the enum. They differ in where the logic lives. Option A — State Classes: the Classic State Pattern In…