Description
Hi,
I run into a runtime exception with Dart 2.19.6 (used with Flutter 3.7.12) when running the following code as a test:
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
typedef FunctionProto<T> = FutureOr<String?> Function(T? value);
@immutable
class TestClass<T> {
final FunctionProto<T>? function;
const TestClass({
this.function,
});
}
void main() {
group('Generic function subtype problem', () {
test('Infeasible workaround regarding the use case', () async {
TestClass<String> testClass = TestClass<String>(
function: (value) async {
return 'return some value';
},
);
if (testClass.function != null) {
print('Call function');
String? err = await testClass.function!('handover some value');
print('err: $err');
}
});
test('Ugly workaround 1 -> Linter warning due to unnecessary cast', () async {
TestClass testClass = TestClass<String>(
function: (value) async {
return 'test';
} as FunctionProto<String>,
);
if (testClass.function != null) {
print('Call function');
String? err = await testClass.function!('handover some value');
print('err: $err');
}
});
test('Ugly workaround 2 -> Linter warning due to unnecessary cast', () async {
TestClass testClass = TestClass<String>(
function: (value) async {
return 'test';
} as FunctionProto,
);
if (testClass.function != null) {
print('Call function');
String? err = await testClass.function!('handover some value');
print('err: $err');
}
});
test('Main issue', () async {
TestClass testClass = TestClass<String>(
function: (value) async {
return 'test';
},
);
if (testClass.function != null) {
print('Call function');
String? err = await testClass.function!('handover some value');
print('err: $err');
}
});
});
}
The mentioned code will throw a runtime exception at line 68 at the snippet testClass.validator with the message type '(String?) => Future' is not a subtype of type '((dynamic) => FutureOr<String?>)?'. In my production code, I have a List where the specific type of each entry could vary, that's why the first workaround in my sample code is not feasible. The other two workarounds are helping for now but on the one side unnecessary code and additionally are marked by the linter as unnecessary.
The Flutter team forwarded my issue to the Dart Repository, as it seems to be a Dart-related issue. The original issue is here issue 125387.
Thank you very much!