Either
The idea
An Either represents a value in one of two states:
Left: a failure (often a business error)Right: a success
The goal is to express error paths in the type, without exceptions, and compose steps without piling up if and try/catch.
Imports
The library exposes the E namespace (alias of DEither) from the main entry point, or via direct import.
import { E, unwrap } from "@duplojs/utils";
// or (tree-shaking friendly)
import * as E from "@duplojs/utils/either";The @duplojs/utils twist: required information
In this library, both Left and Right carry information (a string literal) that contextualizes the business case, for example:
"user.created""emailAlreadyExists""validationFailed"
This information is available at runtime and in the type, which enables precise matching with E.hasInformation.
import { E } from "@duplojs/utils";
const created = E.right(
"user.created",
{
userId: "usr_1",
},
);
const conflict = E.left(
"emailAlreadyExists",
{
email: "[email protected]",
},
);Create an Either
Base constructors:
E.right(info, value)/E.left(info, value)- shortcuts:
E.success(value),E.ok(),E.error(value),E.fail()
Read / match an Either
Most used helpers:
E.isRight/E.isLeftto branchE.hasInformation(info)to target a specific caseunwrapto extract the payload
A typical example: filter a union of errors/successes using the information.
import { E, unwrap } from "@duplojs/utils";
const result = E.left(
"emailAlreadyExists",
{
email: "[email protected]",
},
);
if (E.isLeft(result) && E.hasInformation(result, "emailAlreadyExists")) {
const payload = unwrap(result);
// payload.email -> string
}Compose success-oriented pipelines
When you want to chain transformations as long as it stays a Right:
E.rightPipefor syncE.rightAsyncPipefor async (promises andFuture)
To aggregate multiple Either:
E.groupreturns the firstLeft, otherwise aRightwith all valuesE.asyncGroupdoes the same while accepting promises /Future
Variants and tools around Either
The library provides wrappers that directly produce specialized Either:
E.bool(value):Rightif truthy, otherwiseLeftE.nullish(value): handlesnull | undefinedE.nullable(value): handlesnullE.optional(value): handlesundefinedE.future(value): wraps a value / promise / either in aFuture(Either-typed Promise)
Each variant comes with its own helpers (E.isNullishEmpty, E.whenIsOptionalFilled, E.whenIsBoolFalsy, etc.) to match without losing typing.
