dart-lang / dart-lang/language

NNBD support for generic functions where the result nullability depends on if an optional parameter is passed or not

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

Description

A common pattern in Dart is to have an "orElse" callback on functions that needs to have a fallback behavior.

A concrete example is the `Iterable.firstWhere`:

```dart
final value = [1, 2, 3].firstWhere((i) => , orElse: () => )
```

Now, this is not specific to `Iterable.firstWhere` and is very common to Dart in general.\
NNBD doesn't cause any issue with `Iterable.firstWhere` specifically, as by default, it will throw if it needs a fallback but no `orElse` was provided.

The problem comes with a variant of that pattern, where instead of throwing, the default behavior of their `orElse` would be: `() => null`.

A typical implementation would be:

```dart
T doSomething({T orElse()}) {
// some logic

if (orElse != null) {
return orElse();
} else {
return null;
}
}
```

**The issue with that variant is that it is impossible to migrate to NNBD** without some inconvenient change.

This pattern gets stuck between two un-ideal solutions:
- either make `orElse` required:
```dart
T doSomething({required T orElse()});
```

This is not ideal because it creates a lot of duplicate code.\
We suddenly have to add tons of `orElse: () => null`.

- or make the return type **always** nullable:
```dart
T? doSomething({T orElse()});
```

This is not ideal either because if an `orElse` **is** specified, then the result may effectively never be null but will still be considered as nullable because of a language limitation.

So in the end, with NNBD enabled we either have pointless boilerplate or an incorrectly inferred type.

Contributor guide

Open the contributing guide

Research direction

Start with the NNBD rules and the generic-function examples in the issue, then compare them with the Iterable.firstWhere optional orElse pattern. Determine whether the language can express a result whose nullability depends on whether the optional callback is supplied; done requires a documented language decision addressing both the boilerplate and always-nullable alternatives.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.