6

I often use .firstWhere((E element) -> bool) -> E in my project. When porting it to support null safety I couldn't cleanly handle a scenario when an element is not found in a List instance.

.firstWhere, .singleWhere and .lastWhere returns E, not E? so when handling a case when a List does not contain required element there's no other way to return null other than casting a whole list from eg. List<String> to List<String?> which makes testing function worried about each element being potentially null, which it can't be. Before null safety I was able to just use orElse: () => null but with null safety orElse have to return element of type E so troublesome casting is required.

Do I have to have a null substitute for each type to use in orElse or are there other methods to make list checking support missing element scenario with null?

Marcin Wróblewski
  • 811
  • 1
  • 10
  • 25

2 Answers2

25

You can just use firstWhereOrNull which should work exactly as you expect.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
5

The solution would be to create an extension on the Iterable type:

extension IterableModifier<E> on Iterable<E> {
  E? firstWhereOrNull(bool Function(E) test) =>
      cast<E?>().firstWhere((v) => v != null && test(v), orElse: () => null);
}

Then use it like this:

final myList = <String?>['A', 'B', null, 'C'];
String? result = myList.firstWhereOrNull((e) => e == 'D');
print(result); // output: null
  
result = myList.firstWhereOrNull((e) => e == 'A');
print(result); // output: "A"

Try the full example on DartPad

Guillaume Roux
  • 6,352
  • 1
  • 13
  • 38