- docs
- std
- result
@ozaco/std
import from
@ozaco/std/resultResult
Two values instead of an exception. A Result<T, E> is either a success carrying a value or
a failure carrying an error, a message and a trail of causes — so what can go wrong is part
of the type, and the caller narrows it rather than guessing.
Building the two sides
succeed wraps a value. fail takes the error, an optional message, and any number of causes:
the breadcrumbs that say where it came from.
const ok = succeed(42)
const bad = fail('E_NOT_FOUND', 'no row with that id', 'users.findById')
// from examples/std/result.test.ts
The error is whatever you want it to be — a string code, an Error, a tagged object. Only the
shape around it is fixed.
Narrowing
isSuccess and isFailure are type guards, so a check narrows the union for the rest of the
block. isResult answers whether a value is one at all, which matters at the edges where
something arrives untyped.
if (isResult(value) && isSuccess(value)) {
// value is Result.Success<unknown> here
}
// from examples/std/result.test.ts
Taking the value out
unwrap reads the success. Given a second argument it uses that instead when the result failed;
given none, a failure is raised — it is the failure itself that comes out, not a wrapper.
const rows = unwrap(succeed([1, 2, 3]))
const missing = unwrap(fail('E_EMPTY'), [])
// from examples/std/result.test.ts
- ›
unwrap(result)on a failure throws. Reach for the default form, or narrow first. - ›
unwrapalso accepts a promise of a result and gives you a promise back.
Lifting
auto meets a value wherever it is: a plain value becomes a success, an existing result passes
through unchanged, and a second argument is the fallback for a failure.
const lifted = auto(7)
const passed = auto(succeed(7))
const defaulted = auto(fail('E_GONE'), 0)
// from examples/std/result.test.ts
Catching what throws
throwable runs a callback and settles the outcome instead of letting it escape — the same for
a synchronous throw and a rejected promise.
const parsed = throwable(() => JSON.parse('{ not json') as unknown)
// from examples/std/result.test.ts
Causes
A failure carries a causes array. asFailure turns a caught error into one, and appendCauses
adds to the trail as the failure travels up, so the final value says how it got there.
const low = asFailure(new Error('ECONNREFUSED'), 'pool.acquire')
const high = appendCauses(low, 'users.findById')
// from examples/std/result.test.ts
Maybe
The optional half of the module: just holds a value, nothing holds none, and isJust /
isNothing narrow between them. It is for absence, where Result is for failure.
const found = just('ada')
const absent = nothing<string>()
// from examples/std/result.test.ts