dart_either 2.2.0
dart_either: ^2.2.0 copied to clipboard
Either monad for Dart language and Flutter framework. Type-safe error handling, railway oriented programming. Supports Monad comprehensions, async map, async flatMap.
2.2.0 Aug 27, 2026 #
Either #
- Side-effect hooks
- Added
onLeftandonRight; each runs an action on one side and returns the originalEither. - Deprecated aliases remain:
tapLeft→onLeft,tap→onRight.
- Added
- Right-side predicate
- Added
isRightAndto match aRightvalue with a predicate. existsremains as a deprecated alias.
- Added
- Nullable extraction
- Added
getOrNullforRightandleftOrNullforLeft. orNullremains as a deprecated alias ofgetOrNull.
- Added
- Fallback values
- Added eager
getOrDefault(value). - Deprecated lazy
getOrElse(() => value); usegetOrDefaultfor an eager fallback orgetOrHandle((left) => value)for a lazy, left-aware fallback.
- Added eager
- Composition
combine: combine matching sides; otherwise return the soleLeft.flatten: convertEither<L, Either<L, R>>toEither<L, R>.merge: extract the value fromEither<T, T>.
EitherEffect, Either.binding, and Either.futureBinding #
- Direct short-circuit
- Added
effect.raise(left)to exit the owning scope withLeft(left). - It avoids an intermediate
Leftand returnsNever, so it works in expressions such asnullable ?? effect.raise('missing'). ensureandensureNotNullnow delegate their short-circuit paths toraise.
- Added
- Variance-safe capability
- Reworked
EitherEffect<L>from a covariant public class into an opaque, contravariant, scope-bound capability. - Unsafe widening that previously compiled is now rejected; safe narrowing is supported.
bindmoved from an instance member toBindEitherEffectExtension. Standard unprefixed imports keepeffect.bind(either)unchanged. Prefixed imports must use the extension override; selective imports must include the extension.
- Reworked
- Scope lifetime
- Capabilities are now revoked when their sync or async binding scope ends.
- Reusing a captured capability afterward throws
StateError. - Swallowing a scope's short-circuit signal and then completing normally now
throws
StateErrorinstead of producingRight.
Import migration for EitherEffect.bind #
The usual unprefixed package import keeps the existing call syntax. With a prefixed import, invoke the named extension explicitly:
import 'package:dart_either/dart_either.dart' as de;
final result = de.Either<String, int>.binding((effect) {
return de.BindEitherEffectExtension(effect).bind(
de.Either<String, int>.right(1),
);
});
For a selective unprefixed import, include BindEitherEffectExtension in the
show list. The Dart SDK constraint remains >=3.0.0 <4.0.0.
Documentation and verification #
- Updated the README, runnable examples, API docs, variance guidance, and binding-scope docs.
- Added regression coverage for:
- new APIs and deprecated aliases;
- covariance widening and rejected external
EitherEffectconstruction; - nested sync/async scopes, capability revocation, and intercepted short-circuits.
- CI now runs the complete suite on every configured Dart SDK and collects stable-SDK coverage.
2.1.0 Mar 07, 2026 #
- Promoted
Either.parSequenceNandEither.parTraverseNfrom experimental to stable. - Added complete API docs and examples for
Either.parSequenceNandEither.parTraverseN. - Added unit tests for
Either.parSequenceNandEither.parTraverseN, including concurrency-limit and short-circuit cases. - Added
@useResultannotations to public APIs that should not be ignored (for example:isLeft,isRight,map,flatMap,swap,exists,all,toEitherStream,left,right, and others).
API migration notes #
Either.parSequenceNchanged from positional parameters to named parameters:// Before (2.0.0) Either.parSequenceN<String, int>(functions, n); // Now (2.1.0) Either.parSequenceN<String, int>( functions: functions, maxConcurrent: n, );Either.parTraverseNchanged from positional parameters to named parameters:// Before (2.0.0) Either.parTraverseN<String, int, int>(values, mapper, n); // Now (2.1.0) Either.parTraverseN<String, int, int>( values: values, mapper: mapper, maxConcurrent: n, );maxConcurrentcontrols concurrency.- Pass a number (for example
2) to limit concurrency. - Pass
nullfor unlimited concurrency.
- Pass a number (for example
2.0.0 Sep 01, 2024 #
-
Require Dart 3.0.0 or higher
>=3.0.0 <4.0.0. -
Make
Eithera sealed class,EitherEffecta sealed class, andControlErrora final class. Now you can use exhaustive switch expressions onEitherinstances.final Either<String, int> either = Either.right(10); // Use the `when` method to handle either.when( ifLeft: (l) => print('Left: $l'), ifRight: (r) => print('Right: $r'), ); // Prints Right: Either.Right(10) // Or use Dart 3.0 switch expression syntax 🤘 print( switch (either) { Left() => 'Left: $either', Right() => 'Right: $either', }, ); // Prints Right: Either.Right(10)
1.0.0 Aug 23, 2022 #
- This is our first stable release.
0.0.1 Apr 27, 2021 #
- Initial version, created by Stagehand