Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cast <dynamic> to List<String>?

Tags:

flutter

dart

I have a record class to parse objects coming from Firestore. A stripped down version of my class looks like:

class BusinessRecord {
  BusinessRecord.fromMap(Map<String, dynamic> map, {this.reference})
      : assert(map['name'] != null),
        name = map['name'] as String,
        categories = map['categories'] as List<String>;

  BusinessRecord.fromSnapshot(DocumentSnapshot snapshot)
      : this.fromMap(snapshot.data, reference: snapshot.reference);

  final String name;
  final DocumentReference reference;
  final List<String> categories;
}

This compiles fine, but when it runs I get a runtime error:

type List<dynamic> is not a subtype of type 'List<String>' in type cast

If I just use categories = map['categories']; I get a compile error: The initializer type 'dynamic' can't be assigned to the field type 'List<String>'.

categories on my Firestore object is a List of strings. How do I properly cast this?

Edit: Following is what the exception looks like when I use the code that actually compiles:

VSCode Exception

like image 436
ggutenberg Avatar asked Feb 07 '20 01:02

ggutenberg


3 Answers

Easier answer and as far as I am aware also the suggested way.

List<String> categoriesList = List<String>.from(map['categories'] as List);

Note the "as List" is probably not even needed.

like image 156
Terblanche Daniel Avatar answered Nov 11 '22 07:11

Terblanche Daniel


Imho, you shouldn't cast the list, instead cast its children one by one, for example:

UPDATE

...
...
categories = (map['categories'] as List)?.map((item) => item as String)?.toList();
...
...

enter image description here

like image 32
Hian Avatar answered Nov 11 '22 07:11

Hian


Easy Answer:

You can use the spread operator, like [...json["data"]].

Full example:

final Map<dynamic, dynamic> json = {
  "name": "alice",
  "data": ["foo", "bar", "baz"],
};

// method 1, cast while mapping:
final data1 = (json["data"] as List)?.map((e) => e as String)?.toList();
print("method 1 prints: $data1");

// method 2, use spread operator:
final data2 = [...json["data"]];
print("method 2 prints: $data2");

Output:

flutter: method 1 prints: [foo, bar, baz]
flutter: method 2 prints: [foo, bar, baz]
like image 17
user1032613 Avatar answered Nov 11 '22 08:11

user1032613