I'm working on my first Flutter project having spent many years on Objective-C and Swift so I'm very much learning the quirks of Dart vs the languages I'm familiar with. Currently I'm trying to follow the patterns I'm seeing in Dart and Flutter to add a builder to a class like this:

// Type def of builder closure.
typedef RecordWidgetBuilder<T> = Widget Function(@required T);

// Widget to display a list of records
class GroupedByDateWidget<T> extends StatefulWidget {
  final List<T> items;
  final RecordWidgetBuilder<T> widgetBuilder;

  GroupedByDateWidget({@required this.items, @required this.widgetBuilder});

  @override
  _GroupedByDateWidgetState createState() => _GroupedByDateWidgetState(items: items, widgetBuilder: widgetBuilder);
}

class _GroupedByDateWidgetState<Item> extends State<GroupedByDateWidget> {
  final List<Item> items;
  final RecordWidgetBuilder<Item> widgetBuilder;

  _GroupedByDateWidgetState({@required this.items, @required this.widgetBuilder});

  // ... Rest of class
}

I then have this widget class that I want the closure to use:

// Widget that displays a record.
class SummarisedWorkRecordWidget extends StatelessWidget {

  final WorkRecord record;

  SummarisedWorkRecordWidget(this.record);

  // ... rest of class

Then I'm trying to use these classes like this:

class _RecordViewState extends State<RecordView> {
  @override
  Widget build(BuildContext context) {
    return GroupedByDateWidget<WorkRecord>(
      items: [WorkRecord(), WorkRecord()],
      widgetBuilder: (record) => SummarisedWorkRecordWidget(record),
    );
  }
}

It compiles, but when I run this I get this error:

The following _TypeError was thrown building RecordView(state: _RecordViewState#ade05):
type '(WorkRecord) => SummarisedWorkRecordWidget' is not a subtype of type '(dynamic) => Widget'

The relevant error-causing widget was: 
  RecordView file:///Users/derekclarkson/Work/projects/FWO/record_my_hours/lib/HomePage.dart:37:13
When the exception was thrown, this was the stack: 
#0      GroupedByDateWidget.createState (package:record_my_hours/widgets/GroupedByDateWidget.dart:17:24)
#1      new StatefulElement (package:flutter/src/widgets/framework.dart:4764:24)
...

At this point I'm assuming that closures cannot match on inherited types, but that seem to clash with what I'm seeing in the APIs. Can anyone shed some light on why this isn't working an how to address it?


Solution 1: drekka

Solved it. The problem turned out to be that when I created the _GroupedByDateWidget State instance I didn't also specify the generic qualification to it that I'd added. So it instantiated a state with an dynamic generic and failed.

So:

  @override
  _GroupedByDateWidgetState createState() => _GroupedByDateWidgetState(items: items, widgetBuilder: widgetBuilder);

Should have been:

  @override
  _GroupedByDateWidgetState createState() => _GroupedByDateWidgetState<Item>(items: items, widgetBuilder: widgetBuilder);

Small thing.