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.