Result<Success, Failure extends Object> class abstract

Represents the output of an action that can succeed or fail. Holds a value on success and an error on failure.

Result<Person, ApiFailure> fetchPerson(int id) {}

Use Nothing for outputs that still succeed or fail, but have no meaningful success value.

Result<Nothing, DatabaseError> vacuumDatabase() {}

Processing Values and Errors

Process the values by handling both success and failure cases using when.

final result = fetchPerson(12);
result.when(
  success: (person) => state = MyState.personFound(person);
  failure: (error) => state = MyState.error(error);
);

Or create a common type from both cases, also using when.

final result = fetchPerson(12);
final description = result.when(
  success: (person) => 'Found Person ${person.id}';
  failure: (error) => 'Problem finding a person.';
);

Or ignore the error and do something with maybeValue.

final person = result.maybeValue;
if (person != null) {}

Or use exception handling to process both success and failure cases.

try {
  final person = result.valueOrThrow();
} on ApiFailure catch(e) {
  // handle ApiFailure
}

Failure Type Requirements

Failure types must not be nullable so they can be thrown, but they are not intended to be thrown. Use the type that best fits your app.

We recommend transforming lower-level error types into higher level failure types. This makes app-level logic cleaner and makes UI rendering more consistent.

Creating Results

Create the result with named constructors success and failure.

Future<Result<Person, ApiFailure>> fetchPerson(int id) async {
  try {
    final person = await api.getPerson(12);
    return Result.success(person);
  } on TimeoutException {
    return Result.failure(ApiFailure.timeout());
  } on FormatException {
    return Result.failure(ApiFailure.invalidData());
  }
}

Use nothing for a result with no meaningful success value. It is the constant singleton instance of Nothing.

Result<Nothing, DatabaseError> vacuumDatabase() {
  try {
    db.vacuum();
    return Result.success(nothing);
  } on DatabaseError catch(e) {
    return Result.failure(e);
  }
}

Transforming Results

Process and transform this Result into another Result as part of a pipeline using map.

Result<DateTime, ApiFailure> bigDay = fetchPerson(12).map((person) => person.birthday);

Constructors

Result.failure(Failure error)
Create a failure Result, and save error for later processing.
const
factory
Result.success(Success value)
Create a successful Result, and store value for later use.
const
factory

Properties

hashCode int
The hash code for this object.
no setterinherited
isFailure bool
true if the result is a failure, false otherwise.
no setter
isSuccess bool
true if the result is a success, false otherwise.
no setter
maybeError → Failure?
Returns the error for failure and null for success.
no setter
maybeValue → Success?
Returns the value for success and null for failure.
no setter
runtimeType Type
A representation of the runtime type of the object.
no setterinherited

Methods

flatMap<NewSuccess>(Result<NewSuccess, Failure> transform(Success value)) Result<NewSuccess, Failure>
See mapToResult. Aliased for Swift newcomers.
inherited
flatMapError<NewFailure extends Object>(Result<Success, NewFailure> transform(Failure error)) Result<Success, NewFailure>
See mapErrorToResult. Aliased for Swift newcomers.
inherited
flatMapWhen<NewSuccess, NewFailure extends Object>({required Result<NewSuccess, NewFailure> success(Success value), required Result<NewSuccess, NewFailure> failure(Failure error)}) Result<NewSuccess, NewFailure>
See mapToResultWhen. Aliased for Swift newcomers.
inherited
map<NewSuccess>(NewSuccess transform(Success value)) Result<NewSuccess, Failure>
When this Result is a success, transform the value into a new value, and wrap the new value in a Result.success. When this Result is a failure, simply return the failure as-is.
inherited
mapError<NewFailure extends Object>(NewFailure transform(Failure error)) Result<Success, NewFailure>
When this Result is a success, simply return the value as-is. When this Result is a failure, transform the error into a new error, and wrap the new error in a Result.failure.
inherited
mapErrorToResult<NewFailure extends Object>(Result<Success, NewFailure> transform(Failure error)) Result<Success, NewFailure>
When this Result is a success, simply return the value as-is. When this Result is a failure, transform the error into a new Result.
inherited
mapToResult<NewSuccess>(Result<NewSuccess, Failure> transform(Success value)) Result<NewSuccess, Failure>
When this Result is a success, transform the value into a new Result. When this Result is a failure, simply return the failure as-is.
inherited
mapToResultWhen<NewSuccess, NewFailure extends Object>({required Result<NewSuccess, NewFailure> success(Success value), required Result<NewSuccess, NewFailure> failure(Failure error)}) Result<NewSuccess, NewFailure>
When this Result is a success, transform the value into a new Result. When this Result is a failure, transform the error into a new Result.
inherited
mapWhen<NewSuccess, NewFailure extends Object>({required NewSuccess success(Success value), required NewFailure failure(Failure error)}) Result<NewSuccess, NewFailure>
When this Result is a success, transform the value into a new value, and wrap the new value in a Result.success. When this Result is a failure, transform the error into a new error, and wrap the new error in a Result.failure.
inherited
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toString() String
A string representation of this object.
inherited
valueOrThrow() → Success
Returns the value for success and throws the error on failure.
when<TResult extends Object?>({required TResult success(Success value), required TResult failure(Failure error)}) → TResult
This is the primary way to work with the value and error in a Result. Provide a success function which will process the value when the Result was successful, and a failure function which will process the error when the Result is a failure.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited

Static Methods

catching<T, E extends Object>(FutureOr<T> closure()) FutureOr<Result<T, E>>
Creates a success result from the return value of an async closure. Without an explicit type parameters, any object thrown by closure is caught and returned in a failure result. Specifying the type parameters will catch only objects of type E. All others continue uncaught. To specify E Dart requires that you also specify T.