Skip to content

Runtime Error on Inferred Type For Closure In List with orElse #60009

@caseycrogers

Description

@caseycrogers

Using orElse with a list of closures with inferred type produces a runtime type error:
TypeError: Instance of '() => (String?) => Null': type '() => (String?) => Null' is not a subtype of type '(() => (dynamic) => String?)?'

void main() {
  final badAppleValidator = (input) => input == 'apple' ? 'Apple is a banned word' : null;
  
  final List<String? Function(String?)> validatorsWithExplicitType = [
    badAppleValidator,
  ];

  final validatorsWithInferredType = [
    badAppleValidator,
  ];

  print('Testing with explicit type!');
  print('Runtime type: ${validatorsWithExplicitType.runtimeType}'); // Runtime type: List<(String?) => String?>
  print(validatorsWithExplicitType.validate('moose'));

  print('Testing with inferred type!');
  print('Runtime type: ${validatorsWithInferredType.runtimeType}'); // List<(Dynamic) => String?>
  // This line hits the `orElse` clause and produces the following runtime error:
  //   TypeError: Instance of '() => (String?) => Null': type '() => (String?) => Null'
  //   is not a subtype of type '(() => (dynamic) => String?)?'
  print(validatorsWithInferredType.validate('moose'));
}

extension RunValidations<T> on List<String? Function(String?)> { 
  String? validate(String input) {
    return firstWhere((vFunc) => vFunc.call(input) != null, orElse: () => (_) => null).call(input);
  }
}

Note that my construction of this bug is pretty awkward, the correct solution in my code was to refactor the validate method to be more readable and not to hit the bug, but I figured I'd file this issue anyway as this feels like a bug or limitation in the type inferrence.

  String? validate(String input) {
    return map((vFunc) => vFunc.call(input)).firsWhere((error) => error != null, orElse: (_) => null);
  }

Metadata

Metadata

Assignees

No one assigned

    Labels

    closed-as-intendedClosed as the reported issue is expected behaviorlegacy-area-analyzerUse area-devexp instead.triage-automationSee https://github.com/dart-lang/ecosystem/tree/main/pkgs/sdk_triage_bot.type-bugIncorrect behavior (everything from a crash to more subtle misbehavior)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions