206

Before enums were available in Dart I wrote some cumbersome and hard to maintain code to simulate enums and now want to simplify it. I need to get the name of the enum as a string such as can be done with Java but cannot.

For instance little test code snippet returns 'day.MONDAY' in each case when what I want is 'MONDAY"

enum day {MONDAY, TUESDAY}
print( 'Today is $day.MONDAY');
print( 'Today is $day.MONDAY.toString()');

Am I correct that to get just 'MONDAY' I will need to parse the string?

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
Nate Lockwood
  • 3,325
  • 6
  • 28
  • 34

32 Answers32

233

Dart 2.15

enum Day { monday, tuesday }

main() {
  Day monday = Day.monday;
  print(monday.name); //prints 'monday'
}

Dart 2.7 - 2.14

With new feature called Extension methods you can write your own methods for Enum as simple as that!

enum Day { monday, tuesday }

extension ParseToString on Day {
  String toShortString() {
    return this.toString().split('.').last;
  }
}

main() {
  Day monday = Day.monday;
  print(monday.toShortString()); //prints 'monday'
}
mbartn
  • 3,018
  • 4
  • 12
  • 16
  • As described here, I couldn't use the extension from a different file although the enum was correctly imported. It worked when I followed doc example and added a name to the extension: "extension Formatting on Day". Maybe have an edit if it's not just me. Also response should be updated with a mix of Jannie and mbartn responses. – ko0stik Apr 01 '20 at 08:27
  • 1
    I reverted last edit changes because it doesn't work without name of extension –  Apr 21 '20 at 18:44
  • this is not the best solution. Kalpesh Dabhi providade a better one here: https://stackoverflow.com/a/60615370/9695154 – Gustavo Rodrigues Jun 16 '20 at 22:38
  • `describeEnum` is a Flutter only method, the question is hot to get the value of an enum in Dart – mbartn Jun 17 '20 at 20:00
  • 1
    @mbartn Flutter's implementation shown at https://api.flutter.dev/flutter/foundation/describeEnum.html – Ian May 01 '21 at 09:40
  • To prevent attacks / collisions via 3rd party libs, the extension works only in the local file. To use it in other files you will have to import the extension name itself, in this case: `ParseToString`. Keep in mind that if you need i18n then using enums as string might not be the best approach. Some "intermediary" code will still be needed. – Adrian Moisa May 13 '21 at 12:14
145

Update Dart 2.15:

enum Day {
  monday,
  tuesday,
}

You can use name property on the enum.

String monday = Day.monday.name; // 'monday'

Old solution:

1. Direct way:

var dayInString = describeEnum(Day.monday);
print(dayInString); // prints 'monday'

2. Using Extension:

extension DayEx on Day {
  String get name => describeEnum(this);
}

You can use it like:

void main() {
  Day monday = Day.monday;
  print(monday.name); // 'monday'
}
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
  • 4
    Taking advantage of `describeEnum` is the way to go. Using an extension is a neat bonus – pierrea Sep 23 '20 at 20:49
  • 1
    Worth noting that `describeEnum` is a method only available through the Flutter framework. So not ideal for those who want to do the same in vanilla dart. – shennan Apr 22 '21 at 20:46
  • 2
    This should be the first answer (current first answer is obsolete). – yoni keren Aug 11 '22 at 16:29
140

Bit shorter:

String day = theDay.toString().split('.').last;
Jannie Theunissen
  • 28,256
  • 21
  • 100
  • 127
101

It used to be correct that the only way to get the source name of the enum value was through the toString method which returns "day.MONDAY", and not the more useful "MONDAY".

Since Dart 2.15, enums have exposed a extension getter which returns just the source name, so day.MONDAY.name == "MONDAY".

Since Dart 2.17, you can also add your own members to enum declarations, and choose to provide another name for a value than justits source name, e.g., with a more appropriate capitalization:

enum Day {
  monday("Monday"),
  tuesday("Tuesday"),
  // ...
  saturday("Saturday");
  sunday("Sunday");
 
  final String name;
  Day(this.name);
 
  // And other members too.
  bool get isWorkday => index < saturday.index;
}

Then you get Day.sunday.name == "Sunday" (hiding the extension name getter which would return "sunday").

Before these features, you could only get the name from the toString string, extracting the rest of the string as:

day theDay = day.MONDAY;      
print(theDay.toString().substring(theDay.toString().indexOf('.') + 1));

which was admittedly hardly convenient.

Another way to get the enum name as a string, one which is shorter, but also less efficient because it creates an unnecessary string for first part of the string too, was:

theDay.toString().split('.').last

If performance doesn't matter, that's probably what I'd write, just for brevity.

If you want to iterate all the values, you can do it using day.values:

for (day theDay in day.values) {
  print(theDay);
}
lrn
  • 64,680
  • 7
  • 105
  • 121
  • 1
    The old way enums http://stackoverflow.com/questions/15854549 offer more flexibility but can't be used as constants. Creating a library and importing it with a prefix allows to work around this (see this answer in the lined question above http://stackoverflow.com/a/15855913/217408). – Günter Zöchbauer Apr 10 '15 at 17:49
  • What is the problem with using "enum-class" instances as constants? – lrn Apr 10 '15 at 17:53
  • There shouldn't be any problem creating const instances of a class and having them available as static const members - that's what the language enum implementation does anyway: `class MyEnum { static const MyEnum someItem = const MyEnum(0); static const MyEnum someOtherItem = const MyEnum(1); final int id; const MyEnum(this.id); }` – lrn Apr 10 '15 at 19:04
  • @Irm I was able to to rewrite and test a couple of methods I need. Perhaps enum will be extended some day to provide the name as a string. – Nate Lockwood Apr 10 '15 at 20:06
  • @lrn I tried it and it worked. Thanks for pointing that out. The last time I tried I got an error at `doSomething1([Status status = Status.off]) {` [DartPad](https://dartpad.dartlang.org/59f4ff738632009278d4) – Günter Zöchbauer Apr 11 '15 at 09:21
  • @Irn To me this code to parse the string returned by toString() is more readable: unumName(var target) => (target.toString()).split('.')[1]; Is it equivalent or a bad practice? I'm still pretty much a novice with Dart. – Nate Lockwood Apr 11 '15 at 21:46
  • Using `split` is slightly more wasteful because it creates two substrings and only uses one of them. If it's not used heavily, it's probably just the same. – lrn Apr 12 '15 at 13:58
  • Had the same problem in one of my projects and existing solutions were not very clean, I published my code `Vnum` in pub package. Hope it helps someone. https://github.com/AmirKamali/Flutter_Vnum – Amir.n3t Apr 10 '19 at 14:07
  • This answer is outdated, as many have stated, .name (e.g. day.monday.name) is the way to go since Dart 2.15. – Benjamin Ting Feb 10 '23 at 04:37
  • Thanks for reminding, will update answer. – lrn Feb 10 '23 at 09:59
82

Simplest way to get the name of an enum is a standard method from the flutter/foundation.dart

describeEnum(enumObject)

enum Day {
  monday, tuesday, wednesday, thursday, friday, saturday, sunday
}

void validateDescribeEnum() {
  assert(Day.monday.toString() == 'Day.monday');
  assert(describeEnum(Day.monday) == 'monday');
}
gbixahue
  • 1,383
  • 10
  • 9
  • 12
    This can only be used in Flutter. For dart only code (run with dart instead of flutter), it will cause an error. – Roun Sep 30 '19 at 17:32
  • 1
    The full implementation is given at https://api.flutter.dev/flutter/foundation/describeEnum.html – Ian May 01 '21 at 09:39
  • check this post, it will solve all the problems https://arkapp.medium.com/supercharge-enum-with-extensions-in-flutter-abf8fdf706fe – abdul rehman Jun 28 '22 at 12:49
24
enum day {MONDAY, TUESDAY}
print( 'Today is ${describeEnum(day.MONDAY)}' );

console output: Today is MONDAY

Tim
  • 413
  • 3
  • 8
23

There is a more elegant solution:

enum SomeStatus {
  element1,
  element2,
  element3,
  element4,
}

const Map<SomeStatus, String> SomeStatusName = {
  SomeStatus.element1: "Element 1",
  SomeStatus.element2: "Element 2",
  SomeStatus.element3: "Element 3",
  SomeStatus.element4: "Element 4",
};

print(SomeStatusName[SomeStatus.element2]) // prints: "Element 2"
ItsMeMihir
  • 294
  • 1
  • 5
  • 18
Daniel Vladco
  • 311
  • 3
  • 4
  • 31
    Are you calling it elegant? How? By adding extra space into memory and 20 new lines? – GensaGames Nov 29 '19 at 17:04
  • 5
    this is actually an anti-pattern. when you need to add more values to your enum, you need to modify the code at two places because you should modify the map as well. imagine if you have hundreds of enums in a big app and hundreds of maps for them at different parts of the app. quite hard to maintain. – Daniel Leiszen Jul 09 '20 at 12:36
  • 5
    I actually really like this. The other solutions seem hacky. – Tony Aug 04 '20 at 04:26
  • 1
    If you are using JsonSerializable this Map can be generated automatically by it. And since most real world projects need to use some kind of JSON parser I see this as the best solution. Others rely on implementation detail of enum.toString() having a dot in it. – Dread Boy Mar 02 '21 at 08:47
  • Now dart has `enum.name` there is no reason to use this pattern. – rjh Mar 10 '22 at 10:28
13

Sometimes I need to separate ui-value and real-value, so I defined keys and values using Map. This way, we have more flexiblity. And by using extension (since Dart 2.7), I made a method to read its key and value.

enum Status {
  progess,
  done,
}

extension StatusExt on Status {
  static const Map<Status, String> keys = {
    Status.progess: 'progess',
    Status.done: 'done',
  };

  static const Map<Status, String> values = {
    Status.progess: 'In Progress',
    Status.done: 'Well done',
  };

  String get key => keys[this];
  String get value => values[this];

  // NEW
  static Status fromRaw(String raw) => keys.entries
      .firstWhere((e) => e.value == raw, orElse: () => null)
      ?.key;
}

// usage 1
Status status = Status.done;
String statusKey = status.key; // done
String statusValue = status.value; // Well done

// usage 2 (easy to make key and value list)
List<Status> statuses = Status.values;
List<String> statusKeys = statuses.map((e) => e.key).toList();
List<String> statusValues = statuses.map((e) => e.value).toList();

// usage 3. create Status enum from string.
Status done1 = StatusExt.fromRaw('done') // Status.done
Status done2 = StatusExt.fromRaw('dude') // null
axunic
  • 2,256
  • 18
  • 18
11

As noted in https://medium.com/dartlang/dart-2-17-b216bfc80c5d:

With Dart 2.17 we now have general support for members on enums. That means we can add fields holding state, constructors that set that state, methods with functionality, and even override existing members.

Example:

enum Day {
   MONDAY("Monday"),
   TUESDAY("Tuesday");

  const Day(this.text);
  final String text;
}

Output:

void main() {
  const day = Day.MONDAY;
  print(day.text); /// Monday
}

For above functionality override dart version like below which target 2.17 and greater

environment:
  sdk: ">=2.17.0 <3.0.0"
sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Jitesh Mohite
  • 31,138
  • 12
  • 157
  • 147
  • Its working, but there is a mistake need be corrected enum Day { MONDAY("Monday"), TUESDAY("Tuesday"); const Day(this.text); final String text; } – Rick Robin Jun 19 '22 at 14:52
9

I use structure like below:

abstract class Strings {
  static const angry = "Dammit!";
  static const happy = "Yay!";
  static const sad = "QQ";
}
Nae
  • 14,209
  • 7
  • 52
  • 79
8

I use the functions below to get the name of the enum value and, vise versa, the enum value by the name:

String enumValueToString(Object o) => o.toString().split('.').last;

T enumValueFromString<T>(String key, Iterable<T> values) => values.firstWhere(
      (v) => v != null && key == enumValueToString(v),
      orElse: () => null,
    );

When using Dart 2.7 and newer, extension methods would work here (as well as for any other Objects):

extension EnumX on Object {
  String asString() => toString().split('.').last;
}

The implementation above is not dependant on the specific enums.

Usage examples:

enum Fruits {avocado, banana, orange}
...
final banana = enumValueFromString('banana', Fruits.values);
print(enumValueToString(banana)); // prints: "banana"
print(banana.asString()); // prints: "banana"

Edit from 2020-04-05: Added nullability checks. values parameter could be Iterable, not necessarily List. Added extensions method implementation. Removed <Fruits> annotation from the example to show that the class name duplication is not required.

Alexandr Priezzhev
  • 1,383
  • 13
  • 18
8

I got so over this I made a package:

https://pub.dev/packages/enum_to_string

Also has a handy function that takes enum.ValueOne and parses it to "Value one"

Its a simple little library but its unit tested and I welcome any additions for edge cases.

Ryan Knell
  • 6,204
  • 2
  • 40
  • 32
7

Dart 2.15 includes an extension to make this easy:

enum day {MONDAY, TUESDAY}
print( 'Today is ${day.MONDAY.name}');

Until the changes in https://github.com/dart-lang/sdk/commit/18f37dd8f3db6486f785b2c42a48dfa82de0948b are rolled out to a stable version of Dart, the other clever but more complex answers here are very useful.

Luckyrat
  • 1,455
  • 14
  • 16
6

since dart 2.15 just use ".name"

enum day {monday, tuesday}
print( 'Today is ${day.monday.name}');
钟智强
  • 459
  • 6
  • 17
JC Wu
  • 61
  • 1
  • 2
4

One more way:

enum Length {
  TEN,
  TWENTY,
  THIRTY,
  NONE,
}

extension LengthValue on Length {
  static const _values = [10, 20, 30, 0];

  int get value => _values[this.index];
}
Ketan Choyal
  • 93
  • 2
  • 7
3

My approach is not fundamentally different, but might be slightly more convenient in some cases:

enum Day {
  monday,
  tuesday,
}

String dayToString(Day d) {
  return '$d'.split('.').last;
}

In Dart, you cannot customize an enum's toString method, so I think this helper function workaround is necessary and it's one of the best approaches. If you wanted to be more correct in this case, you could make the first letter of the returned string uppercase.

You could also add a dayFromString function

Day dayFromString(String s) {
  return Day.values.firstWhere((v) => dayToString(v) == s);
}

Example usage:

void main() {
  Day today = Day.monday;
  print('Today is: ${dayToString(today)}');
  Day tomorrow = dayFromString("tuesday");
  print(tomorrow is Day);
}
Vince Varga
  • 6,101
  • 6
  • 43
  • 60
3
enum day {MONDAY, TUESDAY}
print(day.toString().split('.')[1]);
OR
print(day.toString().split('.').last);
Haroon khan
  • 1,018
  • 2
  • 15
  • 27
3

Create a class to help:

class Enum {
    Enum._();

    static String name(value) {
        return value.toString().split('.').last;
    }
}

and call:

Enum.name(myEnumValue);
Tiago
  • 691
  • 7
  • 12
3

One of the good ways I found in the answer is

String day = theDay.toString().split('.').last;

But I would not suggest doing this as dart provide us a better way.

Define an extension for the enum, may be in the same file as:

enum Day {
  monday, tuesday, wednesday, thursday, friday, saturday, sunday
}

extension DayExtension on Day {
  String get value => describeEnum(this);
}

You need to do import 'package:flutter/foundation.dart'; for this.

Ahmad Khan
  • 757
  • 9
  • 22
3

As from Dart 2.15, you can get enum value from

print(MyEnum.one.name);
// and for getting enum from value you use
print(MyEnum.values.byName('two');
Edie Kamau
  • 230
  • 1
  • 5
2

I had the same problem in one of my projects and existing solutions were not very clean and it didn't support advanced features like json serialization/deserialization.

Flutter natively doesn't currently support enum with values, however, I managed to develop a helper package Vnum using class and reflectors implementation to overcome this issue.

Address to the repository:

https://github.com/AmirKamali/Flutter_Vnum

To answer your problem using Vnum, you could implement your code as below:

@VnumDefinition
class Visibility extends Vnum<String> {
  static const VISIBLE = const Visibility.define("VISIBLE");
  static const COLLAPSED = const Visibility.define("COLLAPSED");
  static const HIDDEN = const Visibility.define("HIDDEN");

  const Visibility.define(String fromValue) : super.define(fromValue);
  factory Visibility(String value) => Vnum.fromValue(value,Visibility);
}

You can use it like :

var visibility = Visibility('COLLAPSED');
print(visibility.value);

There's more documentation in the github repo, hope it helps you out.

Amir.n3t
  • 2,859
  • 3
  • 21
  • 28
2

Instead of defining extension for every enum, we can define extension on object and get access to .enumValue from any enum.

void main() {

  // ❌ Without Extension ❌

  print(Countries.Cote_d_Ivoire.toString().split('.').last.replaceAll("_", " ")); // Cote d Ivoire
  print(Movies.Romance.toString().split('.').last.replaceAll("_", " ")); //Romance


  // ✅ With Extension ✅

  print(Countries.Cote_d_Ivoire.enumValue); // Cote d Ivoire
  print(Movies.Romance.enumValue); //Romance
}

enum Countries { United_States, United_Kingdom, Germany, Japan, Cote_d_Ivoire }
enum Movies { Romance, Science_Fiction, Romantic_Comedy, Martial_arts }

extension PrettyEnum on Object {
  String get enumValue => this.toString().split('.').last.replaceAll("_", " ");
}

With this, you can even define multi-word enum where words are separated by _(underscore) in its name.

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
erluxman
  • 18,155
  • 20
  • 92
  • 126
1

try this solution:

extension EnumValueToString on Enum {
  String valueAsString() {
    return describeEnum(this);
  }
}

how to used it:

enum.valueAsString()
Mahmoud Salah Eldin
  • 1,739
  • 16
  • 21
1

dart 2.15 is now supporting this you can just type

print(day.MONDAY.name); //gives you: MONDAY
Amr Ahmed
  • 203
  • 3
  • 12
1

Since Dart 2.15, we can just do Day.monday.name, where

enum Day { monday, tuesday }
kamalbanga
  • 1,881
  • 5
  • 27
  • 46
1

As from Dart version 2.15, you can access the String value of an enum constant using .name:

enum day {MONDAY, TUESDAY}

void main() {
  print('Today is ${day.MONDAY.name}');
  // Outputs: Today is MONDAY
}

You can read in detail about all the enum improvements in the official Dart 2.15 release blog post.

Péter Gyarmati
  • 1,151
  • 1
  • 5
  • 4
1

as of dart 2.15 you can use .name to get the name of enum elements.

enum day {MONDAY, TUESDAY}
print(day.MONDAY.name); // prints MONDAY
SinaMN75
  • 6,742
  • 5
  • 28
  • 56
1

Dart version 2.15 has introduced name property on enums.

Example

void main() {
  MyEnum.values.forEach((e) => print(e.name));
}

enum MyEnum { value1, Value2, VALUE2 }

Output:

value1
Value2
VALUE2
Abdullah Alsigar
  • 1,236
  • 1
  • 12
  • 16
1

For those who require enum with values use this approach as Dart doesn't support this:

class MyEnumClass {
  static String get KEY_1 => 'value 1';
  static String get KEY_2 => 'value 2';
  static String get KEY_3 => 'value 3';
  ...
}

// Usage:
print(MyEnumClass.KEY_1); // value 1
print(MyEnumClass.KEY_2); // value 2
print(MyEnumClass.KEY_3); // value 3
...

And sure you may put whatever types you need.

Osama Remlawi
  • 2,356
  • 20
  • 21
0

now with null safety it looks like this

String enumToString(Object? o) => o != null ? o.toString().split('.').last : '';


T? enumFromString<T>(String key, List<T> values) {
  try {
    return values.firstWhere((v) => key == enumToString(v));
  } catch(e) {
    return null;
  }
}
martinseal1987
  • 1,862
  • 8
  • 44
  • 77
0

You can check out this package enum_object

// convert enum value to string
print(TestEnum.test.enumValue);

// convert String to enum value
var enumObject = EnumObject<TestEnum>(TestEnum.values);
print(enumObject.enumFromString('test2'));```
Edie Kamau
  • 230
  • 1
  • 5
  • As from Dart 2.15, you can get enum value from; `print(MyEnum.one.name);` and for getting enum from value you use; `print(MyEnum.values.byName('two')` – Edie Kamau Jan 12 '22 at 23:44
0
void main() {
 print( 'Today is ${day.MONDAY.name}');
   }
enum day {MONDAY, TUESDAY}
  • We can use the name function to view only the value of enum as string – Kazi Shakib Mar 05 '23 at 19:34
  • Remember that Stack Overflow isn't just intended to solve the immediate problem, but also to help future readers find solutions to similar problems, which requires understanding the underlying code. This is especially important for members of our community who are beginners, and not familiar with the syntax. Given that, **can you [edit] your answer to include an explanation of what you're doing** and why you believe it is the best approach? – Jeremy Caney Mar 08 '23 at 00:09