首页 > 解决方案 > Dart TypeError:类型不是 Null 类型的子类型

问题描述

考虑以下代码:

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'

为什么会这样?

标签: darttypes

解决方案


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

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

我们可以给它类型Map<Type, void Function(int)>,因为我们有一个采用String.

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

所以 Dart 将改为使用Null参数的类型,因为我们唯一知道给这两种方法都有效的是null值。

并且由于您随后尝试将Stringas 参数提供给具有您的签名的方法,因此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');

推荐阅读