The result of Future.wait is an ImmutableList.

Dart SDK 2.9.3
macOS 10.15

For example, if “futures” is an empty list, then “waited” becomes an ImmutableList and an error will occur with singleWhere.
https://dartpad.dev/bec06f4ba0a586b002cc40e597f8b079

Uncaught Error: TypeError: Closure 'main_closure0': type '() => String' is not a subtype of type '(() => Null)?'
void main() async {
  final futures = <Future<String>>[];

  final waited = await Future.wait(futures);

  final actual = waited.singleWhere(
    (element) => element == 'Hello1',
    orElse: () => 'unknown',
  );

  print(actual);
}

However, if “futures” is not an empty list, there is no problem.
https://dartpad.dev/6b96d2200234c6de2f37e51fb9a4849d

void main() async {
  final futures = <Future<String>>[
    Future.delayed(
      Duration(seconds: 1),
      () => 'Hello1',
    ),
    Future.delayed(
      Duration(seconds: 2),
      () => 'Hello2',
    ),
  ];

  final waited = await Future.wait(futures);

  final actual = waited.singleWhere(
    (element) => element == 'Hello1',
    orElse: () => 'unknown',
  );

  print(actual);
}

The easiest way around this problem is to do a List<String>.from(waited), but I’ve never thought about it until I ran into this problem.
Consider changing the result of “Future.wait” to something other than “ImmutableList”.

Author: Fantashit

1 thought on “The result of Future.wait is an ImmutableList.

  1. That should probably be fixed. The optimization of returning the same const <Null>[] every time is based on the assumption that an immutable List<Null> can be a stand-in for any other list, because when you are not writing to the list, you are not using the element type contravariantly.
    That’s not true for singleWhere, so we should probably just return a new empty list, and not try to be clever.

Comments are closed.