Skip to content

Instantly share code, notes, and snippets.

@matanlurey
Last active September 10, 2023 20:23
Show Gist options
  • Save matanlurey/cb41699ff72a41cb9412ef48f47cf824 to your computer and use it in GitHub Desktop.
Save matanlurey/cb41699ff72a41cb9412ef48f47cf824 to your computer and use it in GitHub Desktop.
Example of a Result type in Dart 3.
sealed class Result<T, E> {
const Result();
const factory Result.value(T value) = ValueResult._;
const factory Result.error(E error) = ErrorResult._;
}
final class ValueResult<T, E> extends Result<T, E> {
final T value;
const ValueResult._(this.value);
}
final class ErrorResult<T, E> extends Result<T, E> {
final E error;
const ErrorResult._(this.error);
}
void main() {
final willSucceed = parseInt('5');
// This doesn't work. Two frictions:
// 1. I need to re-add the types (<int, String>) which is not super valuable.
// 2. The else case is not inferred to be ErrorResult, even though it must be.
if (willSucceed is ValueResult<int, String>) {
print('value: ${willSucceed.value}');
} else {
print('error: ${willSucceed.error}');
}
// Let's try if pattern matching (https://dart.dev/language/branches#if-case).
// 1. Works, though still manages to be more characters than if-is.
// 2. The else case is still not inferred to be ErrorResult.
if (willSucceed case ValueResult(value: final value)) {
print('value: $value');
} else {
print('error: ${willSucceed.error}');
}
// Let's try switch pattern matching (https://dart.dev/language/branches#exhaustiveness-checking).
// 1. Works!
// 2. It's definitely the most characters of all the options, but uh, it works.
switch (willSucceed) {
case final ValueResult<int, String> result:
print('value: ${result.value}');
case final ErrorResult<int, String> result:
print('error: ${result.error}');
}
// Let's try the other switch statement (https://dart.dev/language/patterns#switch-statements-and-expressions).
// 1. Works!
// 2. It's still cumbersome to type out both result types.
switch (willSucceed) {
case ValueResult(value: final value):
print('value: $value');
case ErrorResult(error: final error):
print('error: $error');
}
// The shorthand is even nicer.
switch (willSucceed) {
case ValueResult(: final value):
print('value: $value');
case ErrorResult(: final error):
print('error: $error');
}
}
Result<int, String> parseInt(String s) {
final parsed = int.tryParse(s);
return parsed != null ? Result.value(parsed) : Result.error('bad: $s');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment