In Dart, what’s the difference between List.from and .of, and between Map.from and .of?

The important difference between the from and of methods are that the latter have type annotations and the former do not. Since Dart generics are reified and Dart 2 is strongly typed, this is key to both ensuring the List/Map is correctly constructed:

List<String> foo = new List.from(<int>[1, 2, 3]); // okay until runtime.
List<String> bar = new List.of(<int>[1, 2, 3]); // analysis error

And ensuring that the types are inferred correctly:

var foo = new List.from(<int>[1, 2, 3]); // List<dynamic>
var bar = new List.of(<int>[1, 2, 3]); // List<int>

In Dart 1 types were completely optional, so many APIs were untyped or partially typed. List.from and Map.from are good examples, since the Iterable/Map passed into them doesn’t have a type parameter. Sometimes Dart can figure out what the type of this object should be, but sometimes it just ended up as List<dynamic> or Map<dynamic, dynamic>.

In Dart 2 the type dynamic was changed from being both a top (Object) and bottom (null) type to only being a top type. Thus if you created a List<dynamic> accidentally in Dart 1 you could still pass it to a method which required a List<String>. But in Dart 2 List<dynamic> is almost the same as List<Object>, so this would fail.

If you are using Dart 2, you should always use the typed version of these APIs. Why do the old ones still exist, and what are the plans there? I don’t really know. I would guess they would be phased out over time, along with the rest of the Dart 1.

Leave a Comment