Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does Dart expect a value of type dynamic instead of T in a generic class

So I’m working on a flutter app and created a generic dropdownbutton class that I want to fill with objects from a database. The dropdownbutton takes a list of these objects, a function to get the display values of them and then shows these display values in the dropdownmenu. Here is the generic dropdownbutton class:

class GenericDropdownButton<T> extends StatefulWidget {
  T? _selectedValue;
  final List<T> _values;
  final String Function(T value) _displayValueGetter;

  GenericDropdownButton(this._values, this._displayValueGetter, {Key? key})
      : super(key: key);

  @override
  State<GenericDropdownButton> createState() => _GenericDropdownButtonState();
}

class _GenericDropdownButtonState<T> extends State<GenericDropdownButton<T>> {
  @override
  Widget build(BuildContext context) {
    return DropdownButton<T>(
      value: widget._selectedValue,
      items: widget._values.map((T value) {
        return DropdownMenuItem<T>(
          value: value,
          child: Text(widget._displayValueGetter(value)),
          //child: Text(value.toString()),
        );
      }).toList(),
      onChanged: (T? newValue) {
        setState(() {
          widget._selectedValue = newValue;
        });
      },
    );
  }
}

I created a simple class for demonstration purposes to pass to the dropdownbutton:

class TestClass {
  int id;
  String name;

  TestClass(this.id, this.name);
}

And I instantiate a dropdownbutton like this:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

class TestPage extends StatefulWidget {
  const TestPage({Key? key}) : super(key: key);

  @override
  State<TestPage> createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Generic dropdown button test'),
      ),
      body: Column(mainAxisSize: MainAxisSize.max, children: <Widget>[
        GenericDropdownButton<TestClass>(
          <TestClass>[TestClass(1, 'One'), TestClass(2, 'Two')],
          (TestClass t) => t.name
        ),
      ]),
    );
  }
}

When I execute this, I get the following error:

Expected a value of type ‘(dynamic) => String’, but got one of type ‘(TestClass$) => String’

Which corresponds to this line:

child: Text(widget._displayValueGetter(value)),

So as far as I understand, dart expects the parameter ‘value’ to be of type ‘dynamic’, although it’s clearly of type ‘T’ (in this case of type ‘TestClass’), since ‘_displayValueGetter’ is of type ‘String Function(T)’. Why does dart expect that and how can I prevent dart from expecting that?

>Solution :

The type wasn’t specified in createState which is why it’s choosing to be dynamic.

Specify it like so:

@override
State<GenericDropdownButton<T>> createState() => _GenericDropdownButtonState<T>();
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading