How to get all static const fields of a Dart class without using mirrors?

Viewed 608

I know, this question is very similar to DART find all the fields in class. I wonder if there is any way to achieve this without using mirrors?

My use case is the following: I use the shared_preferences package to store many values. For the keys I have a class like this:

class Key {
  static const String FOO = 'foo';
  static const String BAR = 'bar';
  ...
}

I want to write a unit test that checks, that this class of constants does not contains any duplicates. The following would leed to bugs:

class Key {
  static const String FOO = 'foo';
  static const String BAR = 'bar';
  static const String ANOTHER = 'foo';
}

Since dart:mirrors does not work here, what is the best way to implement the test?

1 Answers

If your keys happen to follow the syntax for naming variables, you can use an enum instead of a class:

enum Key { foo, bar }

After you swap out your class for the enum, replace references to Key.FOO and Key.BAR with Key.foo.name and Key.bar.name respectively. And as a bonus, using an enum means you don't have to test for duplicate keys!


Dart 2.17 (released May 11, 2022) introduced "enhanced enums". Feel free to check out this article or the Dart language tour for an in-depth description of what you can do.

If you want to be able to use any string as a key, you can make an enhanced enum:

enum Key {
  foo('multiple words'),
  bar('punctuation!');

  final String keyname;
  const Key(this.keyname);

  @override
  String toString() => keyname;
  String call() => keyname;
}

bool noDuplicates() {
  final List<String> keys = [for (final k in Key.values) k()];
  return keys.length == keys.toSet().length;
}

toString() and call() aren't necessary, but they can be convenient for when you want to represent the key as "${Key.foo}" or Key.foo() instead of having to use Key.foo.keyname.

Related