Home > Back-end >  How to correctly defines types inside a Dart Map
How to correctly defines types inside a Dart Map

Time:11-17

so I am currently learning Dart (Flutter) and I have come to something I can't really understand. So I'm hoping that someone will be able to point out the obvious thing here :)

If I write my code like this:

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: QuizPage(
          title: 'Quiz APP',
          questions: [
            {'question': 'Color?', 'answers': ["Red", "Blue", "Green", "Black"]},
            {'question': 'Animal?', 'answers': ["Cat", "Dog", "Snake", "Rabbit"]},
          ]),
    );
  }
}

class QuizPage extends StatefulWidget {
  QuizPage({super.key, required this.title, required this.questions});

  final String title;
  final List<Map<String, Object>> questions;

  @override
  State<StatefulWidget> createState() {
    return _QuizPageSate();
  }
}

It works, but I have later to cast the answers Object with as List<String>. However, if I directly define the questions type as:

final List<Map<String, List<String>>> questions;

it will not work and throw an error:

The element type 'String' can't be assigned to the map value type 'List<String>'. 

It seems like it doesn't know how to interpret the type I pass in. Do all non "primitive" types inside a Map have to be defined as Object or am I missing something fundamental here?

CodePudding user response:

In your example you declare the following JSON:

[
  {
    'question': 'Color?',
    'answers': [
      "Red", "Blue", "Green", "Black"
    ]
  },
  {
    'question': 'Animal?',
    'answers': [
      "Cat", "Dog", "Snake", "Rabbit"
    ]
  },
]

This, in Dart, is a List of Maps, and those maps have a key of String and a value of either String (the question) or a List of String (the answers).

The problem is this "either", you cannot have a type of either String or List<String>, so you have to use Object or dynamic, which both accept any type.

So, when you used Object, it worked because it accepts anything, but you have to cast it correctly later. And when you used List<String>, the question ('Color?', 'Animal?'), which is not a List<String>, stopped being a valid type.

What you can do to avoid dynamic types is to use classes. Make your QuizPage accept a List<QuizQuestion>, for example.

class QuizQuestion {
   final String question;
   final List<String> answers;

   QuizQuestion(this.question, this.answers);
}

And then do:

QuizPage(
  title: 'Quiz APP',
  questions: [
    QuizQuestion('Color?', ["Red", "Blue", "Green", "Black"]),
    QuizQuestion{'Animal?', ["Cat", "Dog", "Snake", "Rabbit"]),
  ],
),

CodePudding user response:

In your questions list first map contain two key: value. One of the values are String and the other is list, if you define the value as dynamic or Object its ok, but if you set it as list because of first value it through error.

Object or dynamic means you don't know the type and every type is accepted.

So the only option you have is cast your answers to List<String> which you are doing it now.

  • Related