Dart closure return type problem after migrating to null safety

309

As suggested by jamesdlin, here's what worked for me at least syntactically for now. I'm not sure yet if it's going to work functionally - I haven't build the app yet as I'm still fixing null-safety migration issues.

  Widget _parentMenuSelector() {
    return PopupMenuButton<dynamic>(
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Icon(Icons.content_copy),
            Text('Copy to another menu'),
          ],
        ),
      ),
      onSelected: (dynamic selectedMenu) {
        Map<String, dynamic> selMenu = selectedMenu;
        print(selMenu['id']);
        model!.copyMenuItem(selMenu['id']);
      },
      itemBuilder: (BuildContext context) {
        return model!.restaurant!.restaurantMenus!.values.map((dynamic item) {
          Map<String, dynamic> itemMap = item;
          if (itemMap['name'] != model!.menu!.name) {
            return PopupMenuItem<dynamic>(
              child: Text('Copy to ${itemMap['name']}'),
              value: item,
            );
          } else {
            return PopupMenuItem<dynamic>(
              child: null,
            );
          }
        }).toList();
      },
    );
  }
Share:
309
Ernesto
Author by

Ernesto

Updated on December 01, 2022

Comments

  • Ernesto
    Ernesto over 1 year

    The below code used to work before migrating to Flutter 2 and null safety. I just can't figure out what the correct return type should be. The error I get is:

    The return type 'List<PopupMenuItem<dynamic>?>' isn't a 'List<PopupMenuEntry<dynamic>>', as required by the closure's context.
    

    And the code is:

     Widget _parentMenuSelector() {
        return PopupMenuButton<dynamic>(
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                Icon(Icons.content_copy),
                Text('Copy to another menu'),
              ],
            ),
          ),
          onSelected: (dynamic selectedMenu) {
            Map<String, dynamic> selMenu = selectedMenu;
            print(selMenu['id']);
            model!.copyMenuItem(selMenu['id']);
          },
          itemBuilder: (BuildContext context) {
            return model!.restaurant!.restaurantMenus!.values.map((dynamic item) { //ERROR
              Map<String, dynamic> itemMap = item;                                 //ERROR
              if (itemMap['name'] != model!.menu!.name) {                          //ERROR
                return PopupMenuItem<dynamic>(                                     //ERROR
                  child: Text('Copy to ${itemMap['name']}'),                       //ERROR
                  value: item,                                                     //ERROR
                );                                                                 //ERROR
              }                                                                    //ERROR
            }).toList();                                                           //ERROR
          },
        );
      }
    
    • Benyamin
      Benyamin almost 3 years
      Here remove the type and see what happens Map<String, dynamic> itemMap = item....; =>itemMap = .... where have u declared PopupMenuEntry?
    • jamesdlin
      jamesdlin almost 3 years
      Your callback function contains an if statement, but it doesn't return a value along all code paths. It therefore implicitly returns null if the if-condition isn't met, causing your callback function to return a PopupMenuItem<dynamic>? instead of a PopupMenuItem<dynamic> as expected. Fix your code to return a PopupMenuItem along all code paths, or use .where or .whereType if you want to filter the list.
    • Ernesto
      Ernesto almost 3 years
      @jamesdlin - Thanks for the advice. It worked! Now I just need to figure out what exactly I need to return for that specific path.