Skip to content

[feature request] If Either<Failure, Success>, how can I know what kind of Failure happened. #119

@JCKodel

Description

@JCKodel

Scenario:

  • I have a method that returns Either<Failure, Success>.
  • Failure is a base class for "I don't have a clue what happened"
  • I can extend Failure to be more precise, for instance:
class NumberOutOfRangeFailure extends Failure {
  const NumberOutOfRangeFailure({required this.minValue, required this.maxValue});

  final int minValue;
  final int maxValue;
}
  • So, when needed, I can return const Left(NumberOutOfRangeFailure(minValue: 1, maxValue: 99)), meaning: you can only chose between numbers 1 and 99
  • Now, how can I display an error message to the user, since my method returns the base Failure class, without using if or switch?

What about:

static void _dispatchCommand({required BuildContext context, required Command command}) {
  final result = command.dispatch(context);

  result.leftMap(
    (failure) {
      final errorMessage = match<Failure, String>(failure)
          .when<GetNumberedQuoteCommandEmptyNumberFailure>((f) => "Number should not be empty")
          .when<GetNumberedQuoteCommandInvalidNumberFormatFailure>((f) => "Number is not correctly formatted")
          .when<NumberShouldBePositiveFailure>((f) => "Number should be positive")
          .when<NumberShouldBeLessThan100Failure>((f) => "Number should be < 100")
          .when<NumberOutOfRangeFailure>((f) => "Number should be between ${f.minValue} and ${f.maxValue}")
          .otherwise((f) => "Unknown ${f} error");

      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(errorMessage),
        ),
      );
    },
  );
}

In the above code, I just ignore the Success (right), because, well, I don't need to inform the user about it, but for Failure (left), I can test it using generics and have typed failures to create my error message string (notice how I interpolate the minValue and maxValue in the error message).

How?

Using this code (based on #48):

extension Matching<L, R> on Either<L, R> {
  Either<L, R> on(bool Function(R r) predicate, L Function(R r) value) => flatMap((r) => predicate(r) ? left<L, R>(value(r)) : right<L, R>(r));
  Either<L, R> when<T extends R>(L Function(T r) value) => flatMap((r) => r is T ? left<L, R>(value(r)) : right<L, R>(r));
  L otherwise(L Function(R r) transformation) => fold(id, transformation);
}

Either<Result, A> match<A, Result>(A a) => right(a);

So now I can filter my result (by bool predicate), or I can match types using my when extension.

Anyway, my feature request is to incorporate that when, on and otherwise into Either<L, R>.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions