dart-lang / dart-lang/language

Allow `covariant` to be used for arbitrary function types?

Open
#477 5 comments 0 reactions 0 assignees View on GitHub
Dominant language
TeX
Stars
2.9k
Forks
239
Avg merge
2d 18h
Merged PRs (30d)
14

Description

Currently this is rejected by dartanalyzer:

```dart
void Function(covariant dynamic) foo = (int x) {};
```

which complains:

> error • The 'covariant' keyword can only be used for parameters in instance methods or before non-final instance fields at ... • invalid_use_of_covariant
> error • A value of type 'Null Function(int)' can't be assigned to a variable of type 'void Function(dynamic)' at ... • invalid_assignment

I admit that I have little experience with covariance, but why is `covariant` restricted to instance methods? What is intrinsically safer about instance method overrides when the covariant type isn't related to the instance's class?

### Motivation:

A common redux pattern is implementing a reducer like:
```dart
State reducer(State state, dynamic action) {
if (action is FooAction) {
return foo(state, action);
} else if (action is BarAction) {
return bar(state, action);
} else if (action is BazAction) {
return baz(state, action);
}
return state;
}

State foo(State state, FooAction action) {
...
}

State bar(State state, BarAction action) {
...
}
```
I instead want to store this in a `Map` so it can be used like:
```dart
State reducer(State state, dynamic action) {
final handler = reducerTable[action.runtimeType];
if (handler != null) {
return handler(state, action);
}
return state;
}
```
This works, but it has the disadvantage that the handlers must all be declared with `dynamic action` instead of with more specific types:
```dart
State foo(State state, dynamic _action) {
FooAction action = _action as FooAction;
...
}

State bar(State state, dynamic _action) {
BarAction action = _action as BarAction;
...
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.