'How to extract Left or Right easily from Either type in Dart (Dartz)

I am looking to extract a value easily from a method that return a type Either<Exception, Object>.

I am doing some tests but unable to test easily the return of my methods.

For example:

final Either<ServerException, TokenModel> result = await repository.getToken(...);

To test I am able to do that

expect(result, equals(Right(tokenModelExpected))); // => OK

Now how can I retrieve the result directly?

final TokenModel modelRetrieved = Left(result); ==> Not working..

I found that I have to cast like that:

final TokenModel modelRetrieved = (result as Left).value; ==> But I have some linter complain, that telling me that I shouldn't do as to cast on object...

Also I would like to test the exception but it's not working, for example:

expect(result, equals(Left(ServerException()))); // => KO

So I tried this

expect(Left(ServerException()), equals(Left(ServerException()))); // => KO as well, because it says that the instances are different.


Solution 1:[1]

Ok here the solutions of my problems:

To extract/retrieve the data

final Either<ServerException, TokenModel> result = await repository.getToken(...);
result.fold(
 (exception) => DoWhatYouWantWithException, 
 (tokenModel) => DoWhatYouWantWithModel
);

//Other way to 'extract' the data
if (result.isRight()) {
  final TokenModel tokenModel = result.getOrElse(null);
}

To test the exception

//You can extract it from below, or test it directly with the type
expect(() => result, throwsA(isInstanceOf<ServerException>()));

Solution 2:[2]

I can't post a comment... But maybe you could look at this post. It's not the same language, but looks like it's the same behaviour.

Good luck.

Solution 3:[3]

Another way to extract the value is simply to convert to Option, then to a dart nullable:

final Either<Exception, String> myEither = Right("value");

final String? myValue = myEither.toOption().toNullable();

If you like you can define a simple extension to shortcut this:

extension EitherHelpers<L, R> on Either<L, R> {
  R? unwrapRight() {
    return toOption().toNullable();
  }
}

Solution 4:[4]

Friends,

just create dartz_x.dart like this one.

import 'package:dartz/dartz.dart';

extension EitherX<L, R> on Either<L, R> {
  R asRight() => (this as Right).value; //
  L asLeft() => (this as Left).value;
}

And use like that.

import 'dartz_x.dart';

void foo(Either<Error, String> either) {
  if (either.isLeft()) {
    final Error error = either.asLeft();
    // some code
  } else {
    final String text = either.asRight();
    // some code
  }
}

Solution 5:[5]

extension EitherExtension<L, R> on Either<L, R> {
  R? getRight() => fold<R?>((_) => null, (r) => r);
  L? getLeft() => fold<L?>((l) => l, (_) => null);
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Maurice
Solution 2 user8939092
Solution 3
Solution 4
Solution 5 jakobleck