simple-monad
    Preparing search index...

    04 — Domain operation (ok() + the toolkit)

    A domain operation with business rules: a valueless success (ok()Ok<void>, when the action itself is the result), tagged failures with payloads, and reading a failure back with the static unwrap* toolkit.

    Run it: node examples/04-domain-operation.ts

    /**
    * Example 04 — a domain operation with business rules (`ok()` + the toolkit).
    *
    * Shows a *valueless* success (`ok()` → `Ok<void>`, when the action itself is the
    * result and there's nothing to return), tagged failures with payloads, and
    * reading a failure back with the static `unwrap*` toolkit.
    */
    import { bad, type Bad, ok, type Ok, Result } from "simple-monad";

    interface Account {
    balance: number;
    frozen: boolean;
    }

    type WithdrawError =
    | Bad<"account_frozen", void>
    | Bad<"insufficient_funds", { balance: number; requested: number }>;

    function withdraw(
    account: Account,
    amount: number,
    ): Ok<void> | WithdrawError {
    if (account.frozen) return bad("account_frozen");
    if (amount > account.balance) {
    return bad("insufficient_funds", {
    balance: account.balance,
    requested: amount,
    });
    }
    account.balance -= amount;
    return ok(); // success carries no value — the side effect is the result
    }

    const account: Account = { balance: 100, frozen: false };

    console.log(`Input: ${JSON.stringify(account)}, amount to withdraw : 150`);
    const denied = withdraw(account, 150);
    if (denied.isBad()) {
    // unwrapBad* pull a precise piece out of the failure (and throw a ResultError
    // if you call them on an Ok — they're the deliberate escape hatch).
    const reason = Result.unwrapBadReason(denied); // "insufficient_funds"
    const detail = Result.unwrapBadValue(denied); // { balance, requested } | undefined
    console.error(`denied (${reason}):`, detail);
    }

    console.log(`Input: ${JSON.stringify(account)}, amount to withdraw : 40`);
    const okWithdraw = withdraw(account, 40);
    console.log(okWithdraw.isOk() ? `✓ new balance ${account.balance}` : "denied");