Flutter中Dart的诡异行为:List类型转换报错原因咨询
编写了以下Dart代码,其中entityTypeListFromObject的版本1运行时抛出错误:_TypeError (type 'List<dynamic>' is not a subtype of type 'List<EntityTypeModel>?'),已知输入的object始终是非空List,以下是完整代码及错误原因解析:
实体类定义
Pack类
class Pack { Pack({ required this.responseCode, required this.object, }); int responseCode; dynamic object; factory Pack.fromJson(Map<String, dynamic> jsonString) => Pack( responseCode: jsonString['ResponseCode'], object: jsonString['Object'], ); }
EntityTypeModel类
class EntityTypeModel { EntityTypeModel({ required this.entityTypeCode, required this.entityTypeName, }); int entityTypeCode; String entityTypeName; factory EntityTypeModel.fromJson(Map<String, dynamic> jsonString) => EntityTypeModel( entityTypeCode: jsonString['EntityTypeCode'], entityTypeName: jsonString['EntityTypeName'], ); Map<String, dynamic> toJson() => { "EntityTypeCode": entityTypeCode, "EntityTypeName": entityTypeName, }; }
测试函数
Future<dynamic> Test(String bodyString) async { Map<String, dynamic> bodyJson = json.decode(bodyString); final pack = Pack.fromJson(bodyJson); dynamic object= entityTypeListFromObject(pack.object); //... }
两个版本的转换函数
版本1(报错版本)
List<EntityTypeModel>? entityTypeListFromObject(dynamic object) { return object.map((element) => EntityTypeModel.fromJson(element)).toList(); }
版本2(正常运行版本)
List<EntityTypeModel>? entityTypeListFromObject(dynamic object) { if (object is List) { return object .map((element) => EntityTypeModel.fromJson(element)) .toList(); } else { throw Exception('Invalid response format'); } }
输入数据
{"ResponseCode":1,"Object":[{"EntityTypeCode":10,"EntityTypeName":""},{"EntityTypeCode":11,"EntityTypeName":""},{"EntityTypeCode":12,"EntityTypeName":""},{"EntityTypeCode":13,"EntityTypeName":""},{"EntityTypeCode":14,"EntityTypeName":""},{"EntityTypeCode":15,"EntityTypeName":""}]}
错误原因解析
这个错误的核心是Dart的类型推断规则与动态类型处理逻辑导致的:
版本1中,参数
object的类型是dynamic,调用object.map()时,Dart没有足够的类型上下文来确定object的具体List类型,因此map方法返回的是Iterable<dynamic>,后续toList()生成的是List<dynamic>。而函数声明的返回类型是List<EntityTypeModel>?,Dart不允许List<dynamic>直接隐式转换为List<EntityTypeModel>,从而触发类型不匹配错误。版本2中加入了
object is List的类型检查,当条件成立时,Dart会自动对object进行类型提升——将其从dynamic类型提升为List<dynamic>。此时调用map方法,Dart会根据回调函数的返回值(EntityTypeModel)推断出Iterable<EntityTypeModel>,最终toList()生成的是List<EntityTypeModel>,完全符合函数的返回类型要求,因此不会报错。
简单来说,版本1因缺少明确的类型约束,无法让Dart正确推断出转换后的列表泛型类型;版本2通过类型检查触发类型提升,解决了类型推断的上下文缺失问题。
内容的提问来源于stack exchange,提问作者Mario Paracchino

