0

I've got a simplified example below. In practice, I'm passing a list of data objects to a StatefulWidget. I want the Widget to copy the provided list into its state object which will then be filtered through future interactions. The filters use a type parameter so they know what fields they can work with in a callback, for example Filter<MyData>.

So, I'm trying to create a Widget that is aware of the MyData type so it can build the FilterChip Widgets using MyData fields. I tried to achieve this by adding a type parameter to both the StatefulWidget and its State class.

import 'package:flutter/material.dart';

/// Generic type information loss example
class MyWidget<T> extends StatefulWidget {
  final List<T> things;
  const MyWidget({Key? key, required this.things}) : super(key: key);

  @override
  _MyWidgetState createState() => _MyWidgetState<T>();
}

class _MyWidgetState<T> extends State<MyWidget> {
  
  @override
  Widget build(BuildContext context) {
    List<T> things = widget.things; // Compiler error (IDE shows widget.things has a type of List<dynamic>)
    return Container();
  }
}

This code results in:

Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'List<T>'.

So what I don't understand is, why does things in the StatefulWidget class have a type of List<T>, but when referenced through the widget property of the class extendingState<MyWidget>, widget.things has a type of List<dynamic>.

And, as a result, any code in the state class that needs to be aware of the type now breaks. At runtime, the filter callbacks result in errors like:

type '(MyData) => bool' is not a subtype of type '(dynamic) => bool'

Jeff Neet
  • 734
  • 1
  • 8
  • 22
  • I'll leave this question open since it provides a different set of keywords to get to the other answer. (I searched for hours and read dozens of SO posts without finding it.) While the phrasing is a little different the linked answer pointed out what I had overlooked. The type parameter was on the body of the `createState()` method, but not the return type. Even more importantly, while I had the type parameter on the State class, it was missing from the extension. `class _MyWidgetState extends State` to `class _MyWidgetState extends State>` – Jeff Neet Jan 06 '23 at 22:00

1 Answers1

0

I think it is only class MyWidget extends StatefulWidget, without <T>.

Then you don‘t need to copy your list to preserve the list. Just use widget.things, this is considered best practice. The data remains during the rebuilds.

w461
  • 2,168
  • 4
  • 14
  • 40
  • It is possible to write a generic implementation of a StatefulWidget, after reviewing the linked answer, what was missing was the type parameter in two additional places. This article walks through a generic implementation in more detail: https://mobikul.com/generic-type-widget-in-flutter/ – Jeff Neet Jan 06 '23 at 21:55