I am trying to assign a List as a value to a field in a Map.
However, if I vary the types in the Map, the methods seem to be no longer available on the List.
Example:
var list = [1,2];
var myMap = {
'list' : list,
//'commentOut' : 3,
};
print("${myMap['list'].runtimeType}");
print("${myMap['list']!.length}");
Output
JSArray<int>
2
However, if I uncomment the line 'commentOut' : ' I get the error
Error: The getter 'length' isn't defined for the class 'Object'.
Is there a way to get this to work, or am I misunderstanding something fundamental we can't do with Maps ?
CodePudding user response:
When you do:
var list = [1,2];
var myMap = {
'list' : list,
};
then the inferred type of myMap is Map<String, List<int>>.
When you instead do:
var myMap = {
'list' : list,
'commentOut' : 3,
};
your Map's values are now heterogeneous, so Dart infers the value type as the nearest common base type. In this case, the common base type of List<int> and int is Object, so myMap's inferred type is Map<String, Object>.
Consequently, static analysis tools (the Dart analyzer and the Dart compiler) know only that the static (known at compile-time) type of myMap['list'] is Object? even though the actual runtime type is List<int>. It therefore will be a compile-time error to attempt to directly access List methods on it, because calling List methods on an arbitrary Object is potentially unsafe.
You either must explicitly cast the value (myMap['list'] as List<int>) or disable static type checking by explicitly declaring myMap to be of type Map<String, dynamic>.
CodePudding user response:
3 is a value type, not an object type. So the property "length" is not defined on a value type. Even though you defined the element 'list' to get the length, it doesn't know how to handle it.
