Search code examples
genericsdarttypechecking

No type errors reported when list literal has elements not matching declared generic type. Why?


I have been making my way through Shailen Tuli's collection of of snippets in Dart By Example, when I came across the following code:

List<String> fruits = [
  {'name': 'apple', 'selected': true},
  {'name': 'banana', 'selected': true},
  {'name': 'kiwi', 'selected': false}
 ];

Notice that fruits is declared to be a List<String> but that the list elements are actually maps.

Question: Why is there no type error being reported?


Solution

  • If the code example had been written in a strongly statically typed language then an error would be reported. But Dart is a:

    • Dynamically typed language with
    • Static type checking based an "optimistic system of type heuristics" 1.

    Consider this declaration:

    List<num> lst = [4, "ty-two"];
    

    It is important to understand that the array literal [4, "ty-two"], as given, is of type List<dynamic>, where dynamic is the static type attributed to an expression when the static type system does not know what it is (e.g., the user did not declare a static type), or doesn't want to bother doing a deeper analysis to figure out what the type might be -- as is the case for the generic parameter to the list lst.

    The static type system can only help point out that there is a type error if you declare the expected static type of the literal list's elements like this:

    List<num> lst = <num>[4, "tytoo"];
    List<String> fruits = <Map>[{'name': 'apple', ...}, ...];
    

    Now, in both cases a type error is reported. In the case of lst the optimistic system can easily tell that the String "ty-two" can never be of type num. Similar remarks apply for fruits. On the other hand if we had

    var a = "tytoo";
    List<num> lst = <num>[4, a];
    

    To declare a variable with a var effectively means (to the static type checker) that a is of type dynamic. Hence, no error is reported in the assignment to lst.

    Details are given in the Language Specification and these two (IMHO) excellent articles; they explain typing in Dart while also covering the rationale behind the language design decisions that were taken relative to the type system.

    --

    1 https://www.dartlang.org/articles/why-dart-types/
    2 https://www.dartlang.org/articles/optional-types/