Skip to content

Issue with generic function definition ((String?) => Future<String>' is not a subtype of type '((dynamic) => FutureOr<String?>)?') #52168

Closed
@nblum37

Description

@nblum37

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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions