Enhanced enums

Dart · Practical · 8 min

Enums model fixed sets like states and themes, and exhaustive switches catch missed cases at compile time.

A simple enum lists values: enum Status { idle, loading, done }. Every enum has values (all values in order), each value has index and name, and Status.values.byName('done') looks one up by name.

Enhanced enums (Dart 2.17+) can carry data and behavior like a class:

enum Planet {
  mercury(3.3e23, 2.44e6),
  earth(5.97e24, 6.37e6);

  const Planet(this.mass, this.radius);
  final double mass, radius;
  double get gravity => 6.67e-11 * mass / (radius * radius);
}

Rules: values come first, followed by a semicolon; the constructor must be const; fields must be final. Enums can implement interfaces, use mixins and have static members and getters. They can't be extended or instantiated outside their declaration.

switch over an enum is exhaustive: if you handle every value, no default is needed, and adding a value later makes the compiler flag each switch that misses it. Avoid a catch-all _ when you want this safety.

Enums are compared by identity, are const, and work well as Map keys. For JSON, store value.name and read back with values.byName (or a custom lookup with a fallback for unknown strings from a server).

Example

enum Plan implements Comparable<Plan> {
  free(0, maxProjects: 1),
  pro(9, maxProjects: 20),
  team(29, maxProjects: 100);
  const Plan(this.monthlyUsd, {required this.maxProjects});
  final int monthlyUsd;
  final int maxProjects;

  bool get isPaid => monthlyUsd > 0;
  @override
  int compareTo(Plan other) => monthlyUsd - other.monthlyUsd;
}

String badge(Plan p) => switch (p) {   // exhaustive, no default needed
      Plan.free => 'Free',
      Plan.pro => 'Pro ★',
      Plan.team => 'Team',
    };

void main() {
  print(Plan.values.where((p) => p.isPaid).map((p) => p.name).toList()); // [pro, team]
  print(badge(Plan.values.byName('pro')));   // Pro ★
  print(Plan.team.index);                    // 2
  print(Plan.free.compareTo(Plan.team) < 0); // true
}

Remember

  • Enums can have final fields, a const constructor, methods and interfaces
  • Switches over enums are exhaustive without default
  • Use name and values.byName for serialization

Watch out for

  • Adding _ => to every enum switch, which hides newly added values.

Check yourself

  1. What must an enhanced enum's constructor be?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: dart.dev/language/enums

Builds on

Unlocks

Nothing builds on this yet.