The following code is a simple example of a generically typed class which takes a value and a callback that accepts the value as an argument, and then a version which uses a Record that contains the value.
TestNoRecord works like you would expect, and outputs 3.
TestRecord fails at compile time on this line:
final test = TestRecord(('foo',), (val) => print(val.length));
because it infers a type of Object? for val in the function argument.
TestRecordWorkaround works as expected again, outputting 3.
It seems like TestRecord is unable to infer its generic type when the value is wrapped in a Record. Is this expected? Am I doing something wrong?
void main() {
final testNoRecord = TestNoRecord('foo', (val) => print(val.length));
testNoRecord.go();
final test = TestRecord(('foo',), (val) => print(val.length));
test.go();
final test2 = TestRecordWorkaround('foo', (val) => print(val.length));
test2.go();
}
class TestNoRecord<T> {
final T val;
final Function(T) fn;
TestNoRecord(this.val, this.fn);
void go() {
fn(val);
}
}
class TestRecord<T> {
final (T,) record;
final Function(T) fn;
TestRecord(this.record, this.fn);
void go() {
final (val,) = record;
fn(val);
}
}
class TestRecordWorkaround<T> {
final (T,) record;
final Function(T) fn;
TestRecordWorkaround(T val, this.fn) : record = (val,);
void go() {
final (val,) = record;
fn(val);
}
}
@mraleph you’re right, it does seem to be an issue with the analyzer. Thank you for distilling the repro case in your issue!
@Callmephil yeah, I understand that you can specify the type in the function definition, but you don’t have to do that if the generic type is inferred correctly, because the fn parameter is specified to be a Function(T).
The problem with TestRecord lies in Dart’s type inference: The generic type T is not correctly derived from the record (T), which causes the type of val in the callback function to become Object? This happens because Dart does not have enough context to determine T uniquely. In TestRecordWorkaround, however, T is explicitly derived via the constructor parameter (val), which solves the problem. The behavior is to be expected, since Dart sometimes needs more context for generic types with records.
Using contents of this forum for the purposes of training proprietary AI models is forbidden. Only if your AI model is free & open source, go ahead and scrape. Flutter and the related logo are trademarks of Google LLC. We are not endorsed by or affiliated with Google LLC.