Home > Software engineering >  List loses methods when assigning as Map value
List loses methods when assigning as Map value

Time:12-31

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.

  •  Tags:  
  • dart
  • Related