philiprehberger_result_type 0.4.0 copy "philiprehberger_result_type: ^0.4.0" to clipboard
philiprehberger_result_type: ^0.4.0 copied to clipboard

Rust-style Result type for type-safe error handling with pattern matching

philiprehberger_result_type #

Tests pub package Last updated

philiprehberger_result_type

Rust-style Result type for type-safe error handling with pattern matching

Requirements #

  • Dart >= 3.6

Installation #

Add to your pubspec.yaml:

dependencies:
  philiprehberger_result_type: ^0.4.0

Then run:

dart pub get

Usage #

import 'package:philiprehberger_result_type/philiprehberger_result_type.dart';

Result<int, String> divide(int a, int b) {
  if (b == 0) return Result.err('Division by zero');
  return Result.ok(a ~/ b);
}

Pattern Matching #

final result = divide(10, 2);

final message = result.when(
  ok: (value) => 'Result: $value',
  err: (error) => 'Error: $error',
);
print(message); // Result: 5

Fold #

A positional alternative to when() for terser destructuring.

final message = divide(10, 2).fold(
  (value) => 'Result: $value',
  (error) => 'Error: $error',
);

Swap #

Swap the Ok and Err variants — useful for inverting validation results.

final swapped = Result<int, String>.ok(42).swap();
print(swapped); // Err(42)

final inverted = Result<int, String>.err('missing').swap();
print(inverted); // Ok(missing)

Transformations #

// Map success values
final doubled = Result<int, String>.ok(5).map((v) => v * 2);
print(doubled); // Ok(10)

// Chain operations
final chained = Result<int, String>.ok(10)
    .flatMap((v) => v > 0 ? Result.ok(v) : Result.err('must be positive'));

// Transform errors
final mapped = Result<int, String>.err('not found')
    .mapErr((e) => 'Error: $e');

Async Error Handling #

final result = await Result.tryAsync(
  () async => fetchDataFromApi(),
  (error, stack) => 'Request failed: $error',
);

Collecting Results #

final results = [Result<int, String>.ok(1), Result.ok(2), Result.ok(3)];
final collected = Result.collect(results);
print(collected); // Ok([1, 2, 3])

final mixed = [Result<int, String>.ok(1), Result.err('bad')];
final failed = Result.collect(mixed);
print(failed); // Err(bad)

Unwrapping #

final ok = Result<int, String>.ok(42);
print(ok.unwrap());      // 42
print(ok.unwrapOr(0));   // 42

final err = Result<int, String>.err('fail');
print(err.unwrapOr(0));  // 0
// err.unwrap();          // throws StateError

Unwrap with Lazy Default #

final result = Err<int, String>('missing');
final value = result.unwrapOrElse((e) => e.length);
print(value); // 7

Expect #

final result = Result<int, String>.ok(42);
print(result.expect('value must exist')); // 42

// On Err, throws StateError with custom message:
// Result<int, String>.err('fail').expect('value must exist');

Sync Error Handling #

final result = Result.trySync(
  () => int.parse('42'),
  (error) => 'parse failed: $error',
);
print(result); // Ok(42)

Filtering #

final result = Result<int, String>.ok(5)
    .filter((v) => v > 0, (v) => 'expected positive, got $v');
print(result); // Ok(5)

final filtered = Result<int, String>.ok(-1)
    .filter((v) => v > 0, (v) => 'expected positive, got $v');
print(filtered); // Err(expected positive, got -1)

Flattening Nested Results #

final nested = Result<Result<int, String>, String>.ok(Result.ok(42));
final flat = Result.flatten(nested);
print(flat); // Ok(42)

final nestedErr = Result<Result<int, String>, String>.err('outer error');
final flatErr = Result.flatten(nestedErr);
print(flatErr); // Err(outer error)

Zipping Results #

final a = Result<int, String>.ok(1);
final b = Result<int, String>.ok(2);
final zipped = Result.zip(a, b);
print(zipped); // Ok((1, 2))

API #

Method Description
Result.ok(T value) Create a success result
Result.err(E error) Create a failure result
isOk Whether this is an Ok result
isErr Whether this is an Err result
okOrNull Success value or null
errOrNull Error value or null
unwrap() Get value or throw StateError
unwrapOr(T default) Get value or return default
unwrapOrElse(T Function(E) fn) Get value or compute default from error
expect(String message) Get value or throw StateError with message
map(U Function(T) f) Transform success value
mapErr(F Function(E) f) Transform error value
flatMap(Result<U,E> Function(T) f) Chain Result-producing operation
filter(predicate, orElse) Keep Ok if predicate passes, else convert to Err
when({ok, err}) Exhaustive pattern match
fold(onOk, onErr) Reduce to a single value using positional callbacks
swap() Convert Ok↔Err
Result.trySync(fn, onError) Wrap sync operation into Result
Result.tryAsync(fn, onError) Wrap async operation into Result
Result.collect(results) Combine list of Results
Result.flatten(nested) Unwrap nested Result<Result<T,E>,E> into Result<T,E>
Result.zip(a, b) Combine two Results into a record

Development #

dart pub get
dart analyze --fatal-infos
dart test

Support #

If you find this project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License #

MIT

1
likes
160
points
90
downloads

Documentation

API reference

Publisher

verified publisherphiliprehberger.com

Weekly Downloads

Rust-style Result type for type-safe error handling with pattern matching

Homepage
Repository (GitHub)
View/report issues

License

MIT (license)

More

Packages that depend on philiprehberger_result_type