A Map with the compile-time check that every enum
constant has an entry in it.
Overview
For an enum
like this
enum Fruit { apple, orange, banana }
... you can generate the following class:
class FruitMap<V> extends EnumMap<Fruit, V> { // implements Map<Fruit, V>
FruitMap({
required this.apple,
required this.orange,
required this.banana,
});
// ...
}
Which means that the app will only build if you set all the values in the constructor. And then you can treat this object like an ordinary map.
Usage
Add these packages to your pubspec.yaml:
dependencies:
enum_map: ^0.1.0
dev_dependencies:
build_runner:
enum_map_gen: ^0.1.0
Run dart pub get
Given that your enum is in fruit.dart
, add:
part 'fruit.g.dart;
directive.@enumMap
or@unmodifiableEnumMap
annotation, or both.
import 'package:enum_map/enum_map.dat';
part 'fruit.g.dart'; // Add '.g' to the current file name before '.dart' extension.
@enumMap
@unmodifiableEnumMap
enum Fruit { apple, orange, banana }
Then run this in your project root:
$ dart run build_runner build
This creates a file next to your enum file. If it was lib/fruit.dart
, then the generated
file is lib/fruit.g.dart
.
This is how you use it:
import 'fruit.dart';
void main() {
final modifiableMap = FruitMap<String>(apple: 'a', orange: 'o', banana: 'b');
print(modifiableMap); // prints: {Fruit.apple: a, Fruit.orange: o, Fruit.banana: b}
print(modifiableMap[Fruit.apple]); // prints: a
print(modifiableMap.get(Fruit.apple)); // prints: a
const unmodifiableMap = UnmodifiableFruitMap<String>(apple: 'a', orange: 'o', banana: 'b');
print(unmodifiableMap); // prints: {Fruit.apple: a, Fruit.orange: o, Fruit.banana: b}
print(unmodifiableMap[Fruit.apple]); // prints: a
print(unmodifiableMap.get(Fruit.apple)); // prints: a
}
The generated classes contain:
- All 21 of the public members of the
Map
interface. V get(Fruit key)
-- the non-nullable getter that guarantees the result of typeV
.toString()
that works like with the default maps.
Do Not Put Generated Files Under Version Control
You should never put generated files under version control.
Instead you should generate them after each checkout.
To do this, add the above command to your build pipeline before dart compile
or flutter build
.
If you store generated files under version control, there is a risk that these files get outdated.
Then your program will only work until the next re-generation, and then fixing it will be hard.
To ensure you do not store generated files under version control, add the following line to
your .gitignore
file:
*.g.dart
There is however a safety in get()
method. It uses switch (key)
to return the result.
If you add a value to your enum, the generated file will break the build because there will be
an uncovered case that does not return a result.
This will remind you to rebuild your generated files.
Support Chat
Do you have any questions? Feel free to ask in the Telegram Support Chat.
Or even just join to say 'Hi!'. I like to hear from the users.