当list literal的元素与声明的泛型类型不匹配时,不会报告类型错误.为什么?

Pat*_*lin 6 generics typechecking dart

当我遇到以下代码时,我一直在通过Shailen Tuli的Dart By示例片段集合:

List<String> fruits = [
  {'name': 'apple', 'selected': true},
  {'name': 'banana', 'selected': true},
  {'name': 'kiwi', 'selected': false}
 ];
Run Code Online (Sandbox Code Playgroud)

请注意,fruits声明为a List<String>但列表元素实际上是map.

问题:为什么没有报告类型错误?

Pat*_*lin 5

如果代码示例是使用强静态类型语言编写的,则会报告错误.但达特是:

  • 动态类型语言
  • 静态类型检查的基础" 型启发式的乐观系统 " 1.

考虑这个声明:

List<num> lst = [4, "ty-two"];
Run Code Online (Sandbox Code Playgroud)

要明白,数组文本是很重要的[4, "ty-two"],因为给出的类型的List<dynamic>,这里dynamic静态类型归结为一个表达式时,静态类型系统不知道它是什么(例如,用户没有声明静态类型)或者不想打扰进行更深入的分析以找出类型可能是什么 - 就像列表的泛型参数一样lst.

如果您声明文字列表元素的预期静态类型,静态类型系统只能指出存在类型错误,如下所示:

List<num> lst = <num>[4, "tytoo"];
List<String> fruits = <Map>[{'name': 'apple', ...}, ...];
Run Code Online (Sandbox Code Playgroud)

现在,在这两种情况下都会报告类型错误.在lst乐观系统的情况下,可以很容易地告诉我们String "ty-two"永远不会是类型num.类似的评论适用于fruits.另一方面,如果我们有

var a = "tytoo";
List<num> lst = <num>[4, a];
Run Code Online (Sandbox Code Playgroud)

声明变量与var实际上意味着(给静态类型检查器),其a是类型dynamic.因此,在分配中没有报告错误lst.

详细信息在语言规范和这两篇(IMHO)优秀文章中给出 ; 他们解释了在Dart中的输入,同时也涵盖了相对于类型系统所采用的语言设计决策背后的基本原理.

-

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