Last active
September 10, 2023 20:23
-
-
Save matanlurey/cb41699ff72a41cb9412ef48f47cf824 to your computer and use it in GitHub Desktop.
Example of a Result type in Dart 3.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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