Skip to content

Modeling a "Result" type is possible, but difficult #3337

Open
@matanlurey

Description

@matanlurey

Playground: https://dartpad.dev/cb41699ff72a41cb9412ef48f47cf824.


I've really enjoyed Dart's 3 class modifiers and pattern matching.

I'm trying to implement a Result<T, E> type, similar to Rust's std::result:

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);
}

As you can see in my playground, it works! It's just a bit more complicated than I'd expect for a sealed type with only two sub-types (I can see how the implementation as-is works for traditional enum-like types). Here are the individual test cases I wrote:

// Doesn't work, the "else" case doesn't promote willSucceed to ErrorResult, despite the fact that it must be?

if (willSucceed is ValueResult<int, String>) {
  print('value: ${willSucceed.value}');
} else {
  print('error: ${willSucceed.error}');
}
// Similar to above.

if (willSucceed case ValueResult(value: final value)) {
  print('value: $value');
} else {
  print('error: ${willSucceed.error}');
}
// Works, but is the most typing.

switch (willSucceed) {
  case final ValueResult<int, String> result:
    print('value: ${result.value}');
  case final ErrorResult<int, String> result:
    print('error: ${result.error}');
}
// Works, and is probably what I'd use.

switch (willSucceed) {
  case ValueResult(: final value):
    print('value: $value');
  case ErrorResult(: final error):
    print('error: $error');
}

Maybe there is a better way to do this I don't know about or this can serve as inspiration for type inference improvements.

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    patternsIssues related to pattern matching.requestRequests to resolve a particular developer problemtype-inferenceType inference, issues or improvements

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions