Dart TypeError:类型不是Null类型的子类型

时间:2020-05-26 19:21:30

标签: dart types

考虑以下代码:

void printInt(int i) => print(i);
void printString(String s) => print(s);

void printSomething(Object o) {
  final printer = {
    int: printInt,
    String: printString,
  }[o.runtimeType];
  print('Printer is $printer');
  printer(o);
}

void main() => printSomething('Hello');

它会打印正确的printString函数,然后崩溃,但出现以下异常:

TypeError: "Hello": type 'String' is not a subtype of type 'Null'

为什么会这样?

1 个答案:

答案 0 :(得分:2)

该错误来自以下事实:您的地图已被赋予类型Map<Type, void Function(Null)>,因为这是它可以基于列表内容使用的唯一类型。

问题在于Dart无法为您的地图提供其他类型,因为从类型系统的角度来看,其他任何事情都是无效的。假设类型为Map<Type, void Function(Object)>。好吧,然后我们可以从该映射中将任何对象发送到方法中。但这是不允许的,因为映射中的两个方法明确定义为接受intString而不是Object

因为我们有一个采用Map<Type, void Function(int)>的方法,所以我们可以给它指定类型String

此外,Map<Type, void Function(dynamic)>Object的问题相同,因为两种方法都明确定义为采用精确类型。

所以Dart会改用Null作为参数的类型,因为我们知道对这两种方法有效的唯一方法就是null值。

由于您然后尝试将String作为参数提供给签名为void Function(Null)的方法,因此从类型系统中会收到错误消息。

如果您想运行代码,则需要告诉类型系统充分了解您的工作。为此,对于从地图上接收的方法类型,应使用dynamic

void printInt(int i) => print(i);
void printString(String s) => print(s);

void printSomething(Object o) {
  final dynamic printer = {
    int: printInt,
    String: printString,
  }[o.runtimeType];
  print('Printer is $printer');
  printer(o);
}

void main() => printSomething('Hello');