dartforeachdart-null-safetydart-analyzer

linter rule and null safety


I recently replaced deprecated pedantic package with flutter_linter and now I have hundreds warnings like this:

Avoid using `forEach` with a function literal.

it's related to avoid_function_literals_in_foreach_calls

it sounds good if you have non-nullable list, but what if code looks like this:

GetIt<SomeService>().someBehaviorSubject.value?.data?.list?.forEach((f) {
  //
});

How to change it? So it shouldn't be ugly after refactoring.


Solution

  • Interesting question. I don't really have a great answer, but this is the best I can come up with, for now.

    First solution is this which might not be the most efficient way to do it since we are properly creating a new list object:

    void main() {
      final Map<String, Iterable<int>> map = {};
    
      for (final value in [...?map['test']]) {
        // Do something with value
      }
    }
    

    More efficient but also longer would be:

    void main() {
      final Map<String, Iterable<int>> map = {};
    
      for (final value in map['test'] ?? const <int>[]) {
        // Do something with value
      }
    }
    

    The best solution might be adding an extension method on Iterable<T>? like this:

    void main() {
      final Map<String, Iterable<int>> map = {};
    
      for (final value in map['test'].emptyIfNull) {
        // Do something with value
      }
    }
    
    extension EmptyIfNullIterableExtension<T> on Iterable<T>? {
      Iterable<T> get emptyIfNull => this ?? Iterable<T>.empty();
    }
    

    This is allowed since extension methods is resolved statically and by adding a method on a nullable type, we can actually make the call even on null.

    But this does also means this solution does not work if the end result is dynamic since we cannot use extension methods on objects typed as dynamic. The reason is that extension methods are really not part of the class we extends, but instead static methods which the compiler automatically inserts calls to. The fix here is to add a typecast.