DEV Community

Cover image for Enums in Flutter: Usage, Patterns, and Localization
مصعب يوسف
مصعب يوسف

Posted on Originally published at Medium on

Enums in Flutter: Usage, Patterns, and Localization

Enums in Flutter: Usage, Patterns, and Localization

Enums (short for enumerations) in Flutter and Dart are a powerful feature used to define a set of named constants. They help make your code more readable, type-safe, and maintainable. By encapsulating a set of related values, Enums provide structure and allow for a clean representation of fixed concepts within your codebase.

Why Use Enums in Flutter?

Enums are ideal for modeling fixed sets of values such as user roles, app themes, form states, or navigation tabs. Instead of using strings or integers, Enums provide clarity and prevent errors like typos. Using Enums also enables IDE auto-completion and compile-time safety, which results in a better developer experience.

Benefits:

  • Type safety: Prevents assigning invalid values, reducing runtime bugs.
  • Readability: Improves code clarity by replacing magic strings and numbers with meaningful names.
  • Maintainability: Easy to update and refactor, especially when using features like enum extensions.
  • Scalability: As your app grows, enums provide a central way to manage state representations.

How to Use Enums

Basic Example:

enum RoleType {
  @JsonValue("master-admin")
  masterAdmin,
  @JsonValue("admin")
  admin,
  @JsonValue("customer")
  customer,
  @JsonValue("organizer")
  organizer,
  @JsonValue("partner")
  partner,
}

RoleTyperole = RoleType.admin;
if (role == RoleType.admin) {
  print("User is an admin");
}
Enter fullscreen mode Exit fullscreen mode

Using switch with Enums:

RoleType roleType(String roleString) {
  switch (roleString) {
    case 'masterAdmin':
      return RoleType.masterAdmin;
    case 'admin':
      return RoleType.admin;
    case 'customer':
      return RoleType.customer;
    case 'organizer':
      return RoleType.organizer;
    case 'partner':
      return RoleType.partner;
    default:
      throw ArgumentError('Invalid role string: $roleString');
  }
}
Enter fullscreen mode Exit fullscreen mode

Using a switch statement ensures all possible enum values are handled. If a new value is added to the enum and not handled in the switch, Dart will warn you, making it easier to maintain your logic.

Enum Extensions (Patterns)

Dart supports extensions, which allow adding utility methods and computed properties to enums. This makes it easier to encapsulate behavior alongside data.

extension UserRoleExtension on RoleType{
  String get label {
    switch (this) {
     case RoleType.masterAdmin:
        return " Master Administrator";
      case RoleType.admin:
        return "Administrator";
      case RoleType.customer:
        return "Customer";
      case RoleType.organizer:
        return "Organizer";
       case RoleType.partner:
        return "Partner";
    }
  }

bool get canDeleteUsers {
    return this == RoleType.admin || this == RoleType.masterAdmin;
  }
}

// Usage
final role = RoleType.admin;
print(role.label); // Output: Administrator
print(role.canDeleteUsers); // Output: true
Enter fullscreen mode Exit fullscreen mode

This pattern is useful for adding logic that belongs with the enum itself, like permissions, display labels, or conditional checks.

Pattern Matching with switch Expressions (Dart 3)

Dart 3 introduces more expressive switch expressions, which make your code more concise and functional:

String roleLabel(RoleType) => switch (RoleType) {
  RoleType.masterAdmin=> 'Admin',
  RoleType.admin=> 'Admin',
  RoleType.customer=> 'Customer',
};
Enter fullscreen mode Exit fullscreen mode

This feature reduces boilerplate and makes the intent of your code more direct. It’s also easier to chain into other expressions.

Localizing Enums in Flutter

Localization is essential when building multilingual apps, and enums often represent visible strings like status labels or UI options. To localize enums, you can pair them with extensions that utilize your app’s localization system.

Step-by-step Localization Example

  1. Define enum values:
enum OrderStatus {
  pending,
  processing,
  shipped,
  delivered,
}
Enter fullscreen mode Exit fullscreen mode
  1. Add keys to localization files (e.g. en.json, ar.json)
// en.json
"orderStatus.pending": "Pending",
"orderStatus.processing": "Processing",
"orderStatus.shipped": "Shipped",
"orderStatus.delivered": "Delivered"
Enter fullscreen mode Exit fullscreen mode
// ar.json
"orderStatus.pending": "قيد الانتظار",
"orderStatus.processing": "قيد المعالجة",
"orderStatus.shipped": "تم الشحن",
"orderStatus.delivered": "تم التوصيل"
Enter fullscreen mode Exit fullscreen mode
  1. Create an extension for localization:
import 'package:flutter_gen/gen_l10n/app_localizations.dart';


extension OrderStatusLocalization on OrderStatus {
  String localized(AppLocalizations loc) {
    switch (this) {
      case OrderStatus.pending:
        return loc.orderStatusPending;
      case OrderStatus.processing:
        return loc.orderStatusProcessing;
      case OrderStatus.shipped:
        return loc.orderStatusShipped;
      case OrderStatus.delivered:
        return loc.orderStatusDelivered;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Use in widgets:
final status = OrderStatus.shipped;
Text(status.localized(AppLocalizations.of(context)!));
Enter fullscreen mode Exit fullscreen mode

This approach keeps your localization centralized and scalable. If you add a new enum value or language, you only need to update the ARB files and the extension logic.

Extra Tips for Working with Enums

  • Use toString().split('.') only for quick debugging. Avoid it in production code.
  • Consider serializing enums using custom converters if you’re saving them to JSON.
  • Combine enums with sealed classes or union types in Dart 3 for powerful modeling.
  • You can create a generic widget that takes an enum and displays a dropdown with localized labels.

Conclusion

Enums in Flutter are a clean and robust way to model fixed sets of values. With enum extensions and Dart 3 pattern matching, you can write more expressive, maintainable, and scalable code. Enums improve both developer productivity and code clarity. When working with multiple languages, localizing enums through extensions ensures consistency and clarity across the app. Whether you are building UI elements, managing state, or supporting localization, enums are a vital tool in your Flutter toolkit.

Top comments (0)