Skip to content

unthrown


unthrown ​

Facade ​

AsyncResult ​

Defined in: packages/core/src/facade.ts:160

The asynchronous counterpart of Result: an awaitable wrapper carrying the AsyncResultMethods surface, collapsing to a Result<T, E> when await-ed. Shares its name with the companion object above (value and type are one name); this is the type half.

Remarks ​

Combinator callbacks are synchronous. A raw Promise may never enter an AsyncResult method — that would be an un-qualified async boundary, and its rejection would silently become a Defect, skipping the triage that fromPromise forces. To do further async work, re-enter through a qualified boundary and compose it: ar.flatMap((v) => fromPromise(work(v), qualify)). The eliminators (get, …) return promises; the binds (flatMap, flatTap, flatMapErrCases, recoverDefect) additionally accept an AsyncResult. Its combinators are documented one per entry — with their async signatures — on AsyncResultMethods. For "which one do I reach for?", see the Choosing a combinator guide.

To pattern-match an AsyncResult, await it first: match(await ar).

Extends ​

Type Parameters ​

Type ParameterDescription
Tthe success value type.
Ethe modeled error type.

Methods ​

as() ​
ts
as<U>(value): AsyncResult<U, E>;

Defined in: packages/core/src/types.ts:879

Asynchronous as: replaces the value with value.

Type Parameters ​
Type Parameter
U
Parameters ​
ParameterType
valueU
Returns ​

AsyncResult<U, E>

Inherited from ​
ts
AsyncResultMethods.as
bind() ​
ts
bind<K, U, E2>(name, f): AsyncResult<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E | E2>;

Defined in: packages/core/src/types.ts:863

Asynchronous bind (do-notation). f may return a Result or an AsyncResult; its value is bound under name in the accumulating scope.

Type Parameters ​
Type Parameter
K extends string
U
E2
Parameters ​
ParameterType
nameK
f(scope) => | Result<U, E2> | Awaitable<Result<U, E2>> & ReturnAnAsyncResultNotAPromise
Returns ​

AsyncResult<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E | E2>

Inherited from ​
ts
AsyncResultMethods.bind
discard() ​
ts
discard(): AsyncResult<void, E>;

Defined in: packages/core/src/types.ts:881

Asynchronous discard: drops the value, collapsing the success type to void.

Returns ​

AsyncResult<void, E>

Inherited from ​
ts
AsyncResultMethods.discard
ensure() ​
Call Signature ​
ts
ensure<U, E2>(predicate, onFail): AsyncResult<U, E | E2>;

Defined in: packages/core/src/types.ts:889

Asynchronous ensure: validate the success value — and, with a type-guard predicate (this overload), refine it — failing into the modeled channel with Err(onFail(value)). Both callbacks are synchronous (an async onFail is rejected at compile time, NotThenable); a throw in either becomes a Defect.

Type Parameters ​
Type Parameter
U
E2
Parameters ​
ParameterType
predicate(value) => value is U
onFail(value) => E2 & NotThenable<E2>
Returns ​

AsyncResult<U, E | E2>

Inherited from ​
ts
AsyncResultMethods.ensure
Call Signature ​
ts
ensure<E2>(predicate, onFail): AsyncResult<T, E | E2>;

Defined in: packages/core/src/types.ts:894

Boolean form of the asynchronous ensure — validates without refining, keeping T.

Type Parameters ​
Type Parameter
E2
Parameters ​
ParameterType
predicate(value) => boolean
onFail(value) => E2 & NotThenable<E2>
Returns ​

AsyncResult<T, E | E2>

Inherited from ​
ts
AsyncResultMethods.ensure
flatMap() ​
ts
flatMap<U, E2>(f): AsyncResult<U, E | E2>;

Defined in: packages/core/src/types.ts:830

Asynchronous flatMap. Unlike the sync form, f may return a Result or an AsyncResult (never a raw Promise); a throw becomes a Defect.

Type Parameters ​
Type Parameter
U
E2
Parameters ​
ParameterType
f(value) => | Result<U, E2> | Awaitable<Result<U, E2>> & ReturnAnAsyncResultNotAPromise
Returns ​

AsyncResult<U, E | E2>

Remarks ​

The async branch of f's return type is spelled Awaitable<Result<U, E2>> & { flatMap: unknown } rather than AsyncResult<U, E2>: this is what you get by returning an AsyncResult (it satisfies both), but inference runs through the Awaitable then-channel so U/E2 stay precise instead of collapsing to unknown, while the { flatMap: unknown } marker still rejects a bare Promise (it has no flatMap). Just return a Result or an AsyncResult.

Inherited from ​
ts
AsyncResultMethods.flatMap
flatMapErrCases() ​
ts
flatMapErrCases<M>(f): AsyncResult<
  | T
  | OkOf<MatchOut<M>>
  | AsyncOkOf<MatchOut<M>>, 
  | ErrOf<MatchOut<M>>
  | AsyncErrOf<MatchOut<M>>>;

Defined in: packages/core/src/types.ts:915

Asynchronous flatMapErrCases — the same exhaustive ErrMatcher form. Unlike the sync form, a branch may return a Result or an AsyncResult.

Type Parameters ​
Type Parameter
M extends ExhaustiveMatch< | Result<unknown, unknown> | Defect | Awaitable<Result<unknown, unknown>> & ReturnAnAsyncResultNotAPromise>
Parameters ​
ParameterType
f(matcher, defect) => M
Returns ​

AsyncResult< | T | OkOf<MatchOut<M>> | AsyncOkOf<MatchOut<M>>, | ErrOf<MatchOut<M>> | AsyncErrOf<MatchOut<M>>>

Inherited from ​
ts
AsyncResultMethods.flatMapErrCases
flatTap() ​
ts
flatTap<E2>(f): AsyncResult<T, E | E2>;

Defined in: packages/core/src/types.ts:851

Asynchronous flatTap — a failable tap that keeps the original value. f may return a Result or an AsyncResult; its Ok value is discarded, an Err/Defect short-circuits, and a throw becomes a Defect.

Type Parameters ​
Type Parameter
E2
Parameters ​
ParameterType
f(value) => | Result<unknown, E2> | Awaitable<Result<unknown, E2>> & ReturnAnAsyncResultNotAPromise
Returns ​

AsyncResult<T, E | E2>

Inherited from ​
ts
AsyncResultMethods.flatTap
flatTapErrCases() ​
ts
flatTapErrCases<E2>(f): AsyncResult<T, E | E2>;

Defined in: packages/core/src/types.ts:968

Asynchronous flatTapErrCases — the error-channel mirror of flatTap. f may return a Result or an AsyncResult; its Ok value is discarded, an Err/Defect from f threads through, and if f throws — or a branch returns the injected defect(cause) marker, the expression-position form of a throw — the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it.

Type Parameters ​
Type Parameter
E2
Parameters ​
ParameterType
f(matcher, defect) => ExhaustiveMatch< | Result<unknown, E2> | Awaitable<Result<unknown, E2>> & ReturnAnAsyncResultNotAPromise>
Returns ​

AsyncResult<T, E | E2>

Inherited from ​
ts
AsyncResultMethods.flatTapErrCases
get() ​
ts
get(this): Promise<T>;

Defined in: packages/core/src/types.ts:1017

Asynchronous get. Compiles only when the error channel is empty (this: AsyncResult<T, never>); the returned promise rejects on a Defect (rethrowing its cause).

Parameters ​
ParameterType
this[E] extends [never] ? AsyncResult<T, never> : "unthrown: get() needs an empty error channel (E = never) — handle the Err first with recoverErrCases / match / flatMapErrCases, or use getOr / getOrElse / getOrNull / getOrUndefined"
Returns ​

Promise<T>

Inherited from ​
ts
AsyncResultMethods.get
getErr() ​
ts
getErr(this): Promise<E>;

Defined in: packages/core/src/types.ts:1027

Asynchronous getErr. Compiles only when the success channel is empty (this: AsyncResult<never, E>); the returned promise rejects on a Defect (rethrowing its cause).

Parameters ​
ParameterType
this[T] extends [never] ? AsyncResult<never, E> : "unthrown: getErr() needs an empty success channel (T = never) — narrow with isErr() first, or fold with match"
Returns ​

Promise<E>

Inherited from ​
ts
AsyncResultMethods.getErr
getOr() ​
ts
getOr<U>(fallback): Promise<T | U>;

Defined in: packages/core/src/types.ts:1033

Asynchronous getOr.

Type Parameters ​
Type Parameter
U
Parameters ​
ParameterType
fallbackU
Returns ​

Promise<T | U>

Inherited from ​
ts
AsyncResultMethods.getOr
getOrElse() ​
ts
getOrElse<U>(f): Promise<T | U>;

Defined in: packages/core/src/types.ts:1035

Asynchronous getOrElse.

Type Parameters ​
Type Parameter
U
Parameters ​
ParameterType
f(error) => U
Returns ​

Promise<T | U>

Inherited from ​
ts
AsyncResultMethods.getOrElse
getOrNull() ​
ts
getOrNull(): Promise<T | null>;

Defined in: packages/core/src/types.ts:1037

Asynchronous getOrNull.

Returns ​

Promise<T | null>

Inherited from ​
ts
AsyncResultMethods.getOrNull
getOrThrow() ​
ts
getOrThrow(this): Promise<T>;

Defined in: packages/core/src/types.ts:1046

Asynchronous getOrThrow — the returned promise rejects with the modeled error on Err (or the original cause on a Defect), rather than throwing synchronously. Gated the same way: it compiles only when the error channel is non-empty (E is not never).

Parameters ​
ParameterType
this[E] extends [never] ? "unthrown: getOrThrow is unnecessary here — the Err channel is empty (E = never), so there is nothing to throw. Use get() instead." : AsyncResult<T, E>
Returns ​

Promise<T>

Inherited from ​
ts
AsyncResultMethods.getOrThrow
getOrUndefined() ​
ts
getOrUndefined(): Promise<T | undefined>;

Defined in: packages/core/src/types.ts:1039

Asynchronous getOrUndefined.

Returns ​

Promise<T | undefined>

Inherited from ​
ts
AsyncResultMethods.getOrUndefined
let() ​
ts
let<K, U>(name, f): AsyncResult<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E>;

Defined in: packages/core/src/types.ts:874

Asynchronous let (do-notation). f returns a plain value, bound under name. An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type Parameter
K extends string
U
Parameters ​
ParameterType
nameK
f(scope) => U & NotThenable<U>
Returns ​

AsyncResult<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E>

Inherited from ​
ts
AsyncResultMethods.let
map() ​
ts
map<U>(f): AsyncResult<U, E>;

Defined in: packages/core/src/types.ts:816

Asynchronous map: transforms the success value with f. f is synchronous; a throw becomes a Defect. An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type Parameter
U
Parameters ​
ParameterType
f(value) => U & NotThenable<U>
Returns ​

AsyncResult<U, E>

Inherited from ​
ts
AsyncResultMethods.map
mapErrCases() ​
ts
mapErrCases<M>(f, ..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCases): AsyncResult<T, Exclude<MatchOut<M>, Defect>>;

Defined in: packages/core/src/types.ts:904

Asynchronous mapErrCases — the same exhaustive ErrMatcher form; the combinator calls .exhaustive(). Branches are synchronous — an async branch is a compile error, as on the sync surface.

Type Parameters ​
Type Parameter
M extends ExhaustiveMatch<unknown>
Parameters ​
ParameterType
f(matcher, defect) => M
..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCasesSyncBranches<MatchOut<M>, E>
Returns ​

AsyncResult<T, Exclude<MatchOut<M>, Defect>>

Inherited from ​
ts
AsyncResultMethods.mapErrCases
match() ​
ts
match<ROk, RDefect, M>(cases): Promise<ROk | RDefect | MatchOut<M>>;

Defined in: packages/core/src/types.ts:1007

Asynchronous match. Handlers are synchronous (the errCases handler returns an exhaustive ErrMatcher builder, no defect helper); resolves to a Promise of the folded value.

Type Parameters ​
Type Parameter
ROk
RDefect
M extends ExhaustiveMatch<unknown>
Parameters ​
ParameterType
cases{ defect: (cause) => RDefect; errCases: (matcher) => M; ok: (value) => ROk; }
cases.defect(cause) => RDefect
cases.errCases(matcher) => M
cases.ok(value) => ROk
Returns ​

Promise<ROk | RDefect | MatchOut<M>>

Inherited from ​
ts
AsyncResultMethods.match
recoverDefect() ​
ts
recoverDefect<U, E2>(f): AsyncResult<T | U, E | E2>;

Defined in: packages/core/src/types.ts:981

Asynchronous recoverDefect. f may return a Result or an AsyncResult.

Type Parameters ​
Type Parameter
U
E2
Parameters ​
ParameterType
f(cause) => | Result<U, E2> | AsyncResult<U, E2>
Returns ​

AsyncResult<T | U, E | E2>

Inherited from ​
ts
AsyncResultMethods.recoverDefect
recoverErrCases() ​
ts
recoverErrCases<M>(f, ..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCases): AsyncResult<T | Exclude<MatchOut<M>, Defect>, never>;

Defined in: packages/core/src/types.ts:933

Asynchronous recoverErrCases — the same exhaustive ErrMatcher form. Branches are synchronous; a throw becomes a Defect.

Type Parameters ​
Type Parameter
M extends ExhaustiveMatch<unknown>
Parameters ​
ParameterType
f(matcher, defect) => M
..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCasesSyncBranches<MatchOut<M>, T | E>
Returns ​

AsyncResult<T | Exclude<MatchOut<M>, Defect>, never>

Inherited from ​
ts
AsyncResultMethods.recoverErrCases
tap() ​
ts
tap<R>(f): AsyncResult<T, E>;

Defined in: packages/core/src/types.ts:844

Asynchronous tap. f is synchronous; a throw becomes a Defect. An async callback is rejected at compile time (NotThenable) — and so is a returned AsyncResult (it is awaitable). Beware the near-miss: calling an AsyncResult-returning effect inside the callback without returning it compiles and leaves the effect floating — fire-and-forget, never awaited, its Err/Defect unobserved. If the effect returns a Result/AsyncResult, use flatTap.

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterType
f(value) => R & NotThenable<R>
Returns ​

AsyncResult<T, E>

Inherited from ​
ts
AsyncResultMethods.tap
tapDefect() ​
ts
tapDefect<R>(f): AsyncResult<T, E>;

Defined in: packages/core/src/types.ts:990

Asynchronous tapDefect. If f throws, the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterType
f(cause) => R & NotThenable<R>
Returns ​

AsyncResult<T, E>

Inherited from ​
ts
AsyncResultMethods.tapDefect
tapErrCases() ​
ts
tapErrCases<R>(f): AsyncResult<T, E>;

Defined in: packages/core/src/types.ts:952

Asynchronous tapErrCases. f is synchronous; if it throws — or a branch returns the injected defect(cause) marker, the expression-position form of a throw — the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async branch is rejected at compile time (NotThenable on the builder output) — other branch results are discarded, so a rejected Promise would float unobserved. The tap fire-and-forget caveat applies here too — a failable effect belongs in flatTapErrCases.

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterType
f(matcher, defect) => ExhaustiveMatch<R & NotThenable<R>>
Returns ​

AsyncResult<T, E>

Inherited from ​
ts
AsyncResultMethods.tapErrCases
tapFailure() ​
ts
tapFailure<R>(f): AsyncResult<T, E>;

Defined in: packages/core/src/types.ts:1000

Asynchronous tapFailure — the cross-channel observer. f receives the narrowed failure variant (FailureView); if it throws, the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterType
f(failure) => R & NotThenable<R>
Returns ​

AsyncResult<T, E>

Inherited from ​
ts
AsyncResultMethods.tapFailure
then() ​
ts
then<R>(onfulfilled?): PromiseLike<R>;

Defined in: packages/core/src/types.ts:787

Type Parameters ​
Type ParameterDefault type
RResult<T, E>
Parameters ​
ParameterType
onfulfilled?((value) => R | PromiseLike<R>) | null
Returns ​

PromiseLike<R>

Inherited from ​
ts
Awaitable.then

Result ​

ts
type Result<T, E> = 
  | OkView<T, E>
  | ErrView<E, T>
  | DefectView<T, E>;

Defined in: packages/core/src/facade.ts:59

The core type of the library: a computation that has either succeeded with a value of type T or failed with a modeled error of type E. Shares its name with the companion object above (the value and type are one name); this is the type half.

Type Parameters ​

Type ParameterDescription
Tthe success value type.
Ethe modeled error type (only anticipated domain failures).

Remarks ​

A Result is a discriminated union of three variants, distinguished by a tag of "Ok" | "Err" | "Defect":

  • Ok — a success carrying a value: T.
  • Err — a modeled, anticipated failure carrying an error: E.
  • Defect — an unmodeled failure carrying an unknown cause. A Defect never appears in E; it is the library's third, out-of-band channel.

Because it is a real union, you can match it natively (a switch on tag, or the built-in match(...).with({ tag: "Ok" }, …).exhaustive()), and it carries the full method surface for fluent chaining. Either way, the payload (value/error/cause) is only reachable after you narrow — so "check before you access" still holds.

TypeDoc can't list a union's methods on this alias: its fluent combinators (map, flatMap, match, get, …) are documented one per entry on ResultMethods — the shared method surface every variant carries. For "which one do I reach for?", see the Choosing a combinator guide.

Example ​

ts
import { Ok, Err, type Result } from "unthrown";

function half(n: number): Result<number, "odd"> {
  return n % 2 === 0 ? Ok(n / 2) : Err("odd");
}

const message = half(10).match({
  ok: (n) => `got ${n}`,
  // every case of `E` named — here the one literal it holds
  errCases: (matcher) => matcher.with("odd", () => "failed: odd"),
  defect: (cause) => `bug: ${String(cause)}`,
});

AsyncResult ​

ts
const AsyncResult: object;

Defined in: packages/core/src/facade.ts:160

Companion object grouping the AsyncResult-producing entry points under the matching namespace: AsyncResult.Ok, AsyncResult.Err, AsyncResult.Do, AsyncResult.fromExecutor, AsyncResult.fromPromise, AsyncResult.fromSafePromise, AsyncResult.all, AsyncResult.allFromDict, AsyncResult.validateAll, AsyncResult.validateAllFromDict.

Type Declaration ​

Constructors ​

NameTypeDefault valueDefined in
Err()<E>(error) => AsyncResult<never, E>ErrAsyncpackages/core/src/facade.ts:162
Ok(){ (): AsyncResult<void, never>; <T> (value): AsyncResult<T, never>; }OkAsyncpackages/core/src/facade.ts:161

Interop ​

NameTypeDefined in
fromExecutor()<T, E>(executor) => AsyncResult<T, E>packages/core/src/facade.ts:164
fromPromise()<T, R>(promise, qualify, ..._guard) => AsyncResult<T, Exclude<R, Defect>>packages/core/src/facade.ts:165
fromSafePromise()<T>(promise) => AsyncResult<T, never>packages/core/src/facade.ts:166

Do-notation ​

NameTypeDefault valueDefined in
Do()() => AsyncResult<{ }, never>DoAsyncpackages/core/src/facade.ts:163

Aggregate ​

NameTypeDefault valueDefined in
all()<Rs>(results) => AsyncResult<AllOk<Rs, { [K in string | number | symbol]: AsyncOkOf<Rs[K]> }>, AsyncErrOf<Rs[number]>>allAsyncpackages/core/src/facade.ts:167
allFromDict()<R>(results) => AsyncResult<{ [K in string | number | symbol]: AsyncOkOf<R[K]> }, AsyncErrOf<R[keyof R]>>allFromDictAsyncpackages/core/src/facade.ts:168
validateAll()<Rs, E2>(results, merge) => AsyncResult<AllOk<Rs, { [K in string | number | symbol]: AsyncOkOf<Rs[K]> }>, E2>validateAllAsyncpackages/core/src/facade.ts:169
validateAllFromDict()<R, E2>(results, merge) => AsyncResult<{ [K in string | number | symbol]: AsyncOkOf<R[K]> }, E2>validateAllFromDictAsyncpackages/core/src/facade.ts:170

Remarks ​

The async sibling of Result. Statics are grouped by what they return, so the pre-lifted constructors, fromExecutor, fromPromise/fromSafePromise, and the async aggregates sit here rather than on Result; the namespace already conveys "async", so the members drop the Async suffix their free functions carry (AsyncResult.Ok is OkAsync; AsyncResult.Err is ErrAsync; AsyncResult.Do is DoAsync; AsyncResult.all is allAsync; AsyncResult.allFromDict is allFromDictAsync; AsyncResult.validateAll is validateAllAsync). Like Result, the free functions remain the primary, tree-shakeable API; the value AsyncResult and the type AsyncResult share one name.

Example ​

ts
import { AsyncResult } from "unthrown";
const user = await AsyncResult.fromPromise(
  fetchUser(id),
  (c, defect) => defect(c),
);
user.get(); // => the fetched user (on success)

Result ​

ts
const Result: object;

Defined in: packages/core/src/facade.ts:59

Companion object grouping the Result-producing entry points under a single, discoverable namespace: Result.Ok, Result.Err, Result.Do, Result.fromNullable, Result.fromThrowable, Result.fromSafeThrowable, Result.all, Result.allFromDict, Result.validateAll, Result.validateAllFromDict, Result.isOk, Result.isErr, Result.isDefect, Result.isResult.

Type Declaration ​

Constructors ​

NameTypeDefined in
Err()<E>(error) => Result<never, E>packages/core/src/facade.ts:61
Ok(){ (): Result<void, never>; <T> (value): Result<T, never>; }packages/core/src/facade.ts:60

Interop ​

NameTypeDefined in
fromNullable()<T, E>(value, onAbsent) => Result<NonNullable<T>, E>packages/core/src/facade.ts:63
fromSafeThrowable()<A, T>(fn) => (...args) => Result<T, never>packages/core/src/facade.ts:65
fromThrowable()<A, T, R>(fn, qualify) => (...args) => Result<T, Exclude<R, Defect>>packages/core/src/facade.ts:64

Do-notation ​

NameTypeDefined in
Do()() => Result<{ }, never>packages/core/src/facade.ts:62

Guards ​

NameTypeDefined in
isDefect()<T, E>(r) => r is DefectView<T, E>packages/core/src/facade.ts:72
isErr()<T, E>(r) => r is ErrView<E, T>packages/core/src/facade.ts:71
isOk()<T, E>(r) => r is OkView<T, E>packages/core/src/facade.ts:70
isResult()(x) => x is Result<unknown, unknown>packages/core/src/facade.ts:73

Aggregate ​

NameTypeDefined in
all()<Rs>(results) => Result<AllOk<Rs, { [K in string | number | symbol]: OkOf<Rs[K]> }>, ErrOf<Rs[number]>>packages/core/src/facade.ts:66
allFromDict()<R>(results) => Result<{ [K in string | number | symbol]: OkOf<R[K]> }, ErrOf<R[keyof R]>>packages/core/src/facade.ts:67
validateAll()<Rs, E2>(results, merge) => Result<AllOk<Rs, { [K in string | number | symbol]: OkOf<Rs[K]> }>, E2>packages/core/src/facade.ts:68
validateAllFromDict()<R, E2>(results, merge) => Result<{ [K in string | number | symbol]: OkOf<R[K]> }, E2>packages/core/src/facade.ts:69

Remarks ​

Purely additive sugar — each member is the corresponding free function. The free functions remain the primary, tree-shakeable API; importing only { Ok } never pulls this object in. The value Result and the type Result share one name (the companion-object pattern).

The async entry points live on the sibling AsyncResult companion (AsyncResult.fromPromise, AsyncResult.all, …), grouped by what they return — a static lives in exactly one namespace.

Example ​

ts
import { Result } from "unthrown";
Result.Ok(1).flatMap((n) => Result.Ok(n + 1)).get(); // => 2

Types ​

DefectView ​

Defined in: packages/core/src/types.ts:738

The Defect variant of a Result: an unmodeled failure carrying a cause. This is what a successful isDefect guard narrows to, exposing .cause. It also carries the shared fluent surface (ResultMethods).

Example ​

ts
if (r.isDefect()) r.cause; // r: DefectView<T, E> here — .cause is `unknown`

Extends ​

Type Parameters ​

Type ParameterDefault type
Tnever
Enever

Properties ​

PropertyModifierTypeDefined in
causereadonlyunknownpackages/core/src/types.ts:740
tagreadonly"Defect"packages/core/src/types.ts:739

Methods ​

as() ​
ts
as<U>(value): Result<U, E>;

Defined in: packages/core/src/types.ts:288

Replace the success value with a constant value.

Runs only on Ok; Err and Defect pass through.

Type Parameters ​
Type ParameterDescription
Uthe replacement value type.
Parameters ​
ParameterType
valueU
Returns ​

Result<U, E>

Inherited from ​
ts
ResultMethods.as
bind() ​
ts
bind<K, U, E2>(name, f): Result<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E | E2>;

Defined in: packages/core/src/types.ts:261

Do-notation: run f for a Result and bind its value under name in an accumulating object scope.

Type Parameters ​
Type ParameterDescription
K extends stringthe key the bound value is stored under.
Uthe bound value type.
E2the error type f may introduce.
Parameters ​
ParameterTypeDescription
nameKthe scope key.
f(scope) => Result<U, E2>produces a Result from the accumulated scope.
Returns ​

Result<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E | E2>

Remarks ​

Begin a chain with Do (an empty object scope) and grow it step by step. f receives the scope accumulated so far and returns a Result; on Ok the value is added as { ...scope, [name]: value }, on Err/Defect the chain short-circuits. Errors union (E | E2). A throw becomes a Defect — as does calling bind on a non-object or non-plain scope (e.g. Ok(5).bind, or a class instance whose getters the merge would drop), which is misuse: the scope is always a plain object inside a real Do() chain. (let is the pure-value counterpart.)

Inherited from ​
ts
ResultMethods.bind
discard() ​
ts
discard(): Result<void, E>;

Defined in: packages/core/src/types.ts:297

Drop the success value, collapsing the success type to void.

The named form of map(() => undefined). Runs only on Ok (the value is replaced with undefined); Err and Defect pass through. Unlike as(undefined) — which produces Result<undefined, E> — the success type is void: the value's story ends here.

Returns ​

Result<void, E>

Inherited from ​
ts
ResultMethods.discard
ensure() ​
Call Signature ​
ts
ensure<U, E2>(predicate, onFail): Result<U, E | E2>;

Defined in: packages/core/src/types.ts:332

Validate the success value — keep the Ok when predicate holds, otherwise fail into the modeled channel with Err(onFail(value)).

Type Parameters ​
Type ParameterDescription
Uthe refined success type (type-guard form).
E2the error type onFail produces.
Parameters ​
ParameterTypeDescription
predicate(value) => value is Uthe check; a type guard refines T to U.
onFail(value) => E2 & NotThenable<E2>maps the failing value to the modeled error.
Returns ​

Result<U, E | E2>

Remarks ​

The named form of flatMap((v) => (p(v) ? Ok(v) : Err(e))). With a type-guard predicate ((v): v is U) the success type is refined to U on the way through (this overload). Runs only on Ok — a passing value flows through as the same Ok; Err and Defect pass through untouched. A throw in predicate or onFail becomes a Defect.

Both callbacks are synchronous: an async onFail is rejected at compile time (NotThenable), and an async predicate does not type-check either — its Promise<boolean> is not a boolean (and, being truthy, would have silently always passed).

Example ​
ts
// boolean form: gate a value
Ok(-1).ensure((n) => n > 0, (n) => `negative: ${n}`); // Err("negative: -1")

// type-guard form: refine the success type
declare const r: Result<string | number, "e">;
const s = r.ensure(
  (v): v is string => typeof v === "string",
  () => "not_a_string" as const,
); // Result<string, "e" | "not_a_string">
Inherited from ​
ts
ResultMethods.ensure
Call Signature ​
ts
ensure<E2>(predicate, onFail): Result<T, E | E2>;

Defined in: packages/core/src/types.ts:340

Boolean form of ensure — validates without refining, keeping the success type T.

Type Parameters ​
Type Parameter
E2
Parameters ​
ParameterType
predicate(value) => boolean
onFail(value) => E2 & NotThenable<E2>
Returns ​

Result<T, E | E2>

Inherited from ​
ts
ResultMethods.ensure
flatMap() ​
ts
flatMap<U, E2>(f): Result<U, E | E2>;

Defined in: packages/core/src/types.ts:204

Sequence a dependent, Result-returning step (monadic bind).

Runs f only on Ok; Err and Defect pass through. The error channels combine, widening to E | E2. If f throws, the throw becomes a Defect.

Type Parameters ​
Type ParameterDescription
Uthe success type of the next step.
E2the error type the next step may introduce.
Parameters ​
ParameterTypeDescription
f(value) => Result<U, E2>produces the next Result from the current success value.
Returns ​

Result<U, E | E2>

Inherited from ​
ts
ResultMethods.flatMap
flatMapErrCases() ​
ts
flatMapErrCases<M>(f): Result<T | OkOf<MatchOut<M>>, ErrOf<MatchOut<M>>>;

Defined in: packages/core/src/types.ts:397

Sequence from an Err by producing another Result — the error-channel mirror of flatMap, matching the error exhaustively (ErrMatcher; the combinator calls .exhaustive()).

Each branch returns a Result; the outgoing channels are the unions of the branch-returned Results' channels. A branch may return defect(cause). Runs only on Err; Ok and Defect pass through.

Type Parameters ​
Type ParameterDescription
M extends ExhaustiveMatch<Result<unknown, unknown> | Defect>the exhaustive builder the callback returns.
Parameters ​
ParameterTypeDescription
f(matcher, defect) => Mbuilds the match; each branch produces a fallback Result.
Returns ​

Result<T | OkOf<MatchOut<M>>, ErrOf<MatchOut<M>>>

Inherited from ​
ts
ResultMethods.flatMapErrCases
flatTap() ​
ts
flatTap<E2>(f): Result<T, E | E2>;

Defined in: packages/core/src/types.ts:240

Run a failable side effect on the success value, keeping the original value but threading the effect's error.

Type Parameters ​
Type ParameterDescription
E2the error type the effect may introduce.
Parameters ​
ParameterTypeDescription
f(value) => Result<unknown, E2>the failable side effect; its Ok value is ignored.
Returns ​

Result<T, E | E2>

Remarks ​

This is to tap what flatMap is to map: f returns a Result, but its success value is discarded — on success the original value flows through (Result<T, E | E2>), while an Err (or Defect) from f short-circuits. Runs only on Ok; Err and Defect pass through. If f throws, the throw becomes a Defect. Use it for a validation or write whose result matters but whose value you don't need.

Inherited from ​
ts
ResultMethods.flatTap
flatTapErrCases() ​
ts
flatTapErrCases<E2>(f): Result<T, E | E2>;

Defined in: packages/core/src/types.ts:478

Run a failable side effect on the error, keeping the original error but threading the effect's own error — matched exhaustively (ErrMatcher).

Type Parameters ​
Type Parameter
E2
Parameters ​
ParameterTypeDescription
f(matcher, defect) => ExhaustiveMatch<Result<unknown, E2>>builds the match; each branch is a failable effect (its Ok is ignored).
Returns ​

Result<T, E | E2>

Remarks ​

The error-channel mirror of flatTap: each branch returns a Result whose success value is discarded — on the effect's Ok the original Err flows through, while an Err/Defect from a branch short-circuits and threads its error. Note the asymmetry with a throw: a branch that returns a Defect-state Result replaces the original Err (Defect-dominance, the short-circuit rule — it is not aggregated), whereas a branch that throws produces a Defect aggregating [thrown, original failure] (observing a failure by throwing never destroys it). A branch returning the injected defect(cause) marker — reachable under a returnType pin — follows the throw rule, since it is the lint-clean, expression-position form of one.

Inherited from ​
ts
ResultMethods.flatTapErrCases
get() ​
ts
get(this): T;

Defined in: packages/core/src/types.ts:583

Extract the success value.

Parameters ​
ParameterType
this[E] extends [never] ? Result<T, never> : "unthrown: get() needs an empty error channel (E = never) — handle the Err first with recoverErrCases / match / flatMapErrCases, or use getOr / getOrElse / getOrNull / getOrUndefined"
Returns ​

T

the Ok value.

Remarks ​

Compiles only when the error channel is empty (E = never) — eliminate modeled errors first (match / recoverErrCases / flatMapErrCases), or reach for the getOr / getOrElse / getOrNull / getOrUndefined family (which recover an Err). The gate is a this type that becomes an explanatory string when E is not never, so the compile error names the fix.

E = never empties only the modeled error channel — a Defect can still be present, and get() rethrows its original cause (it panics); Result<T, never> does not mean get() cannot throw.

Inherited from ​
ts
ResultMethods.get
getErr() ​
ts
getErr(this): E;

Defined in: packages/core/src/types.ts:601

Extract the modeled error.

Parameters ​
ParameterType
this[T] extends [never] ? Result<never, E> : "unthrown: getErr() needs an empty success channel (T = never) — narrow with isErr() first, or fold with match"
Returns ​

E

the Err value.

Remarks ​

Compiles only when the success channel is empty (T = never) — eliminate the success case first. T = never is rarely the case in practice (a Result you hold usually still has a success type), so to inspect an error prefer an isErr() guard or, in tests, @unthrown/vitest's toBeErrWith. A Defect still rethrows its original cause (a defect is a bug, not an absent value), so this does not mean getErr() can't throw.

Inherited from ​
ts
ResultMethods.getErr
getOr() ​
ts
getOr<U>(fallback): T | U;

Defined in: packages/core/src/types.ts:614

The success value, or fallback on Err.

Type Parameters ​
Type ParameterDescription
Uthe fallback type (may differ from T; the return widens to `T
Parameters ​
ParameterTypeDescription
fallbackUreturned when the result is an Err (may be a different type; the return widens to `T
Returns ​

T | U

Throws ​

Re-throws on a Defect — a Defect is a bug, not an absent value, so it is never silently replaced.

Inherited from ​
ts
ResultMethods.getOr
getOrElse() ​
ts
getOrElse<U>(f): T | U;

Defined in: packages/core/src/types.ts:622

The success value, or f(error) on Err.

Type Parameters ​
Type ParameterDescription
Uthe fallback type (may differ from T; the return widens to `T
Parameters ​
ParameterTypeDescription
f(error) => Ulazily computes the fallback from the error (may return a different type; the return widens to `T
Returns ​

T | U

Throws ​

Re-throws on a Defect.

Inherited from ​
ts
ResultMethods.getOrElse
getOrNull() ​
ts
getOrNull(): T | null;

Defined in: packages/core/src/types.ts:628

The success value, or null on Err.

Returns ​

T | null

Throws ​

Re-throws on a Defect.

Inherited from ​
ts
ResultMethods.getOrNull
getOrThrow() ​
ts
getOrThrow(this): T;

Defined in: packages/core/src/types.ts:666

The success value, or throw the modeled error on Err.

Parameters ​
ParameterType
this[E] extends [never] ? "unthrown: getOrThrow is unnecessary here — the Err channel is empty (E = never), so there is nothing to throw. Use get() instead." : Result<T, E>
Returns ​

T

the Ok value.

Remarks ​

A deliberate escape hatch off the errors-as-values model — it throws the Err value as-is at the call site, so a caller of the enclosing function sees a throw rather than a channel. Its home is tests and scripts, where "this Result had better be Ok" is the assertion and a throw is the correct failure mode.

In production code, fold the error channel instead: recoverErrCases empties E, so get compiles and a case routed to the injected defect(...) panics with its original cause — with every case still named. match and flatMapErrCases are the other two ways to keep the error a value. @unthrown/oxlint's opt-in no-get-or-throw rule enforces this, exempting test files through an oxlint overrides entry.

Type-gated as the complement of get: it compiles only when the error channel is non-empty (E is not never) — there must be a modeled error for it to throw. On a Result<T, never> there is nothing to throw, so getOrThrow does not compile; use get() (which gates the other way). Together they partition extraction by the error channel's state, with no overlap.

Throws ​

the modeled error on Err; re-throws the original cause on a Defect (a panic, like the rest of the getOr… family).

Inherited from ​
ts
ResultMethods.getOrThrow
getOrUndefined() ​
ts
getOrUndefined(): T | undefined;

Defined in: packages/core/src/types.ts:634

The success value, or undefined on Err.

Returns ​

T | undefined

Throws ​

Re-throws on a Defect.

Inherited from ​
ts
ResultMethods.getOrUndefined
isDefect() ​
ts
isDefect(): this is DefectView<T, E>;

Defined in: packages/core/src/types.ts:677

Whether this result is a Defect — narrows this to its DefectView on true.

Returns ​

this is DefectView<T, E>

Inherited from ​
ts
ResultMethods.isDefect
isErr() ​
ts
isErr(): this is ErrView<E, T>;

Defined in: packages/core/src/types.ts:675

Whether this result is Err — narrows this to its ErrView on true.

Returns ​

this is ErrView<E, T>

Inherited from ​
ts
ResultMethods.isErr
isOk() ​
ts
isOk(): this is OkView<T, E>;

Defined in: packages/core/src/types.ts:673

Whether this result is Ok — narrows this to its OkView on true.

Returns ​

this is OkView<T, E>

Inherited from ​
ts
ResultMethods.isOk
let() ​
ts
let<K, U>(name, f): Result<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E>;

Defined in: packages/core/src/types.ts:280

Do-notation: run f for a plain value and bind it under name in the accumulating object scope. The pure-value counterpart of bind.

Type Parameters ​
Type ParameterDescription
K extends stringthe key the value is stored under.
Uthe value type.
Parameters ​
ParameterTypeDescription
nameKthe scope key.
f(scope) => U & NotThenable<U>computes a value from the accumulated scope.
Returns ​

Result<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E>

Remarks ​

f receives the scope and returns a value (not a Result); it is added as { ...scope, [name]: value }. Runs only on Ok; Err/Defect pass through. A throw becomes a Defect. An async callback is rejected at compile time (NotThenable).

Inherited from ​
ts
ResultMethods.let
map() ​
ts
map<U>(f): Result<U, E>;

Defined in: packages/core/src/types.ts:193

Transform the success value with f.

Runs f only on Ok; Err and Defect pass through untouched. If f throws, the thrown value is captured as a Defect.

An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type ParameterDescription
Uthe mapped success type.
Parameters ​
ParameterTypeDescription
f(value) => U & NotThenable<U>maps the current success value to a new one.
Returns ​

Result<U, E>

Inherited from ​
ts
ResultMethods.map
mapErrCases() ​
ts
mapErrCases<M>(f, ..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCases): Result<T, Exclude<MatchOut<M>, Defect>>;

Defined in: packages/core/src/types.ts:379

Transform the modeled error by matching it exhaustively.

Type Parameters ​
Type ParameterDescription
M extends ExhaustiveMatch<unknown>the exhaustive builder the callback returns.
Parameters ​
ParameterTypeDescription
f(matcher, defect) => Mbuilds the match over the error (returns the un-terminated builder).
..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCasesSyncBranches<MatchOut<M>, E>compile-time only; never pass it. Empty for synchronous branches; an async branch demands this impossible argument, so the call fails to compile (its name is the fix).
Returns ​

Result<T, Exclude<MatchOut<M>, Defect>>

Remarks ​

The callback receives match(error) (an ErrMatcher) and the injected defect helper. Chain .with(pattern, handler) and return the un-terminated builder — mapErrCases calls .exhaustive() itself, so a missing case is a compile error at the call site (there is no .exhaustive() to forget, and no way to slip in .otherwise()). The outgoing error type is the union of the branch returns with the Defect arm subtracted (Exclude<O, Defect>) — a branch returning defect(cause) converts that case to a Defect and drops it from E. Runs only on Err; Ok and Defect pass through. A branch that throws also becomes a Defect. Branches are synchronous: an async branch is a compile error (its Promise would land in E un-triaged), and a thenable slipped past the types becomes a Defect.

Name every case. Match on anything the matcher supports — _tag, code, structural shape, guards — and group the cases that share a handler with .with(a, b, handler). .with(P._, …) is the wildcard escape hatch, not the default: it makes any match exhaustive, so it also absorbs every case E grows later. Two uses are sanctioned — a helper generic in E, where no arm list can prove exhaustiveness against an unresolved type parameter, and an E that is a single type rather than a union of cases (see P for both). @unthrown/oxlint's no-catch-all-pattern (in its recommended preset) flags the rest.

Inherited from ​
ts
ResultMethods.mapErrCases
match() ​
ts
match<ROk, RDefect, M>(cases): ROk | RDefect | MatchOut<M>;

Defined in: packages/core/src/types.ts:562

Exhaustively fold all three runtime states into a single value.

Type Parameters ​
Type ParameterDescription
ROkthe ok handler return type.
RDefectthe defect handler return type.
M extends ExhaustiveMatch<unknown>the exhaustive builder the errCases handler returns.
Parameters ​
ParameterTypeDescription
cases{ defect: (cause) => RDefect; errCases: (matcher) => M; ok: (value) => ROk; }the ok/defect handlers plus the errCases matcher builder.
cases.defect(cause) => RDefect-
cases.errCases(matcher) => M-
cases.ok(value) => ROk-
Returns ​

ROk | RDefect | MatchOut<M>

Remarks ​

Exactly one handler runs. Together with the throw-to-Defect guarantee, this is typically the single place a pipeline is handled at the edge — mapping Ok/Err/Defect to (for example) 2xx / 4xx / 5xx with no try/catch.

The errCases handler does not take a single blanket callback: it receives match(error) (an ErrMatcher) and matches the error exhaustively, exactly like the error combinators — which is why the key carries the same …Cases suffix. Chain .with(pattern, handler) and return the un-terminated builder — match calls .exhaustive() itself, so a missing case is a compile error at the call site (no .exhaustive() to forget). Folding at the edge names every case too — .with(P._, …) is the wildcard escape hatch, not the default. Unlike the combinators the branches receive no defect helper — match is total elimination to a value, with no Defect output channel; the defect case handles a Result that already carries one. (A Result is also a discriminated union — for richer whole-Result matching, match(result).with(…).)

Inherited from ​
ts
ResultMethods.match
recoverDefect() ​
ts
recoverDefect<U, E2>(f): Result<T | U, E | E2>;

Defined in: packages/core/src/types.ts:498

Recover from a Defect — the only combinator that can touch one.

Type Parameters ​
Type ParameterDescription
Ua success type the recovery may produce.
E2an error type the recovery may produce.
Parameters ​
ParameterTypeDescription
f(cause) => Result<U, E2>maps the Defect's unknown cause to a recovering Result.
Returns ​

Result<T | U, E | E2>

Remarks ​

Runs f only when a Defect is present, re-entering the modeled world by returning a Result (an Ok or a fresh Err). Ok and Err pass through. Recovering a Defect should be rare: usually you let it bubble to the edge. If f throws, the throw becomes a new Defect.

Inherited from ​
ts
ResultMethods.recoverDefect
recoverErrCases() ​
ts
recoverErrCases<M>(f, ..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCases): Result<T | Exclude<MatchOut<M>, Defect>, never>;

Defined in: packages/core/src/types.ts:421

Recover from an Err by producing a success value, emptying the error channel — matching the error exhaustively (ErrMatcher). Pairs with recoverDefect.

Type Parameters ​
Type ParameterDescription
M extends ExhaustiveMatch<unknown>the exhaustive builder the callback returns.
Parameters ​
ParameterTypeDescription
f(matcher, defect) => Mbuilds the match; each branch produces a success value.
..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCasesSyncBranches<MatchOut<M>, T | E>compile-time only; never pass it. Empty for synchronous branches; an async branch demands this impossible argument, so the call fails to compile (its name is the fix).
Returns ​

Result<T | Exclude<MatchOut<M>, Defect>, never>

Remarks ​

The result type is Result<T | U, never>, but never describes only the error channel — a Defect can still be present at runtime. A branch may return defect(cause) (which stays a Defect, not a recovery). Runs only on Err; Ok and Defect pass through. Branches are synchronous: an async branch is a compile error, and a thenable slipped past the types becomes a Defect.

Inherited from ​
ts
ResultMethods.recoverErrCases
tap() ​
ts
tap<R>(f): Result<T, E>;

Defined in: packages/core/src/types.ts:223

Run a side effect on the success value and pass the Result through unchanged.

Runs only on Ok. If f throws, the throw becomes a Defect. An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterTypeDescription
f(value) => R & NotThenable<R>the side effect (its return value is ignored).
Returns ​

Result<T, E>

Remarks ​

f's return value is ignored — a Result returned by the effect compiles but is discarded, Err and all. If the effect can fail, sequence it instead of tapping it: a Result-returning effect goes in flatTap; an AsyncResult-returning effect cannot be sequenced from the sync surface — lift the chain with toAsync and use the async flatTap (which accepts both).

Inherited from ​
ts
ResultMethods.tap
tapDefect() ​
ts
tapDefect<R>(f): Result<T, E>;

Defined in: packages/core/src/types.ts:508

Run a side effect on a present Defect's cause (e.g. logging) and pass the Defect through unchanged. If f throws, the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterTypeDescription
f(cause) => R & NotThenable<R>the side effect over the unknown cause.
Returns ​

Result<T, E>

Inherited from ​
ts
ResultMethods.tapDefect
tapErrCases() ​
ts
tapErrCases<R>(f): Result<T, E>;

Defined in: packages/core/src/types.ts:450

Run a side effect on the error — matched exhaustively (ErrMatcher) — and pass the Result through unchanged.

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterTypeDescription
f(matcher, defect) => ExhaustiveMatch<R & NotThenable<R>>builds the match; branch returns are ignored, bar defect(cause).
Returns ​

Result<T, E>

Remarks ​

The callback builds a match whose branches run side effects; their return values are ignored and the original Err flows through. Exhaustive like the transformers, and like them it wants every case named — .with(P._, …) remains the wildcard escape hatch. If a branch throws, the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async branch is rejected at compile time (NotThenable on the builder output): because the branch results are discarded, a returned Promise would float unobserved and its rejection would vanish. The one branch return that is not discarded is the injected defect(cause) marker: it is the lint-clean, expression-position form of a throw, so it follows the throw rule above (an AggregateError of [the branch's cause, original failure]), never a silent no-op. A failable Result-returning effect belongs in flatTapErrCases.

Inherited from ​
ts
ResultMethods.tapErrCases
tapFailure() ​
ts
tapFailure<R>(f): Result<T, E>;

Defined in: packages/core/src/types.ts:534

Run a side effect on any failure — Err or Defect — and pass the Result through unchanged. The one cross-channel observer, for the shared "it went KO" concern (logging, metrics, rollback) that would otherwise be duplicated across tapErrCases and tapDefect.

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterTypeDescription
f(failure) => R & NotThenable<R>the side effect over the failure variant (its return value is ignored).
Returns ​

Result<T, E>

Remarks ​

f receives the narrowed failure variant (FailureView), not a payload — the payload union E | unknown would collapse to unknown and lose E's typing. Branch on failure.tag to reach the typed payload ("Err" → failure.error: E, "Defect" → failure.cause: unknown), or treat it opaquely for a shared logger. Runs on Err and Defect; Ok passes through. It observes without consuming: the failure flows on unchanged — to also recover, use recoverErrCases / recoverDefect (deliberately separate acts) or match at the edge. If f throws, the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async callback is rejected at compile time (NotThenable).

Inherited from ​
ts
ResultMethods.tapFailure
toAsync() ​
ts
toAsync(): AsyncResult<T, E>;

Defined in: packages/core/src/types.ts:680

Lift this synchronous Result into an AsyncResult.

Returns ​

AsyncResult<T, E>

Inherited from ​
ts
ResultMethods.toAsync

ErrView ​

Defined in: packages/core/src/types.ts:721

The Err variant of a Result: a modeled failure carrying an error. This is what a successful isErr guard narrows to, exposing .error. It also carries the shared fluent surface (ResultMethods).

Remarks ​

Note the parameter order: ErrView<E, T> puts the error type first — the reverse of the <T, E> order used by OkView, DefectView, and Result — because Result<T, E> narrows to ErrView<E, T> (the error is the payload the guard makes reachable). You rarely write it by hand (a failed isErr() narrows to it for you); if you do, mind the flip — ErrView<MyError, MyValue>, not ErrView<MyValue, MyError>.

Example ​

ts
if (r.isErr()) r.error; // r: ErrView<E, T> here — .error is an E

Extends ​

Type Parameters ​

Type ParameterDefault type
E-
Tnever

Properties ​

PropertyModifierTypeDefined in
errorreadonlyEpackages/core/src/types.ts:723
tagreadonly"Err"packages/core/src/types.ts:722

Methods ​

as() ​
ts
as<U>(value): Result<U, E>;

Defined in: packages/core/src/types.ts:288

Replace the success value with a constant value.

Runs only on Ok; Err and Defect pass through.

Type Parameters ​
Type ParameterDescription
Uthe replacement value type.
Parameters ​
ParameterType
valueU
Returns ​

Result<U, E>

Inherited from ​
ts
ResultMethods.as
bind() ​
ts
bind<K, U, E2>(name, f): Result<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E | E2>;

Defined in: packages/core/src/types.ts:261

Do-notation: run f for a Result and bind its value under name in an accumulating object scope.

Type Parameters ​
Type ParameterDescription
K extends stringthe key the bound value is stored under.
Uthe bound value type.
E2the error type f may introduce.
Parameters ​
ParameterTypeDescription
nameKthe scope key.
f(scope) => Result<U, E2>produces a Result from the accumulated scope.
Returns ​

Result<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E | E2>

Remarks ​

Begin a chain with Do (an empty object scope) and grow it step by step. f receives the scope accumulated so far and returns a Result; on Ok the value is added as { ...scope, [name]: value }, on Err/Defect the chain short-circuits. Errors union (E | E2). A throw becomes a Defect — as does calling bind on a non-object or non-plain scope (e.g. Ok(5).bind, or a class instance whose getters the merge would drop), which is misuse: the scope is always a plain object inside a real Do() chain. (let is the pure-value counterpart.)

Inherited from ​
ts
ResultMethods.bind
discard() ​
ts
discard(): Result<void, E>;

Defined in: packages/core/src/types.ts:297

Drop the success value, collapsing the success type to void.

The named form of map(() => undefined). Runs only on Ok (the value is replaced with undefined); Err and Defect pass through. Unlike as(undefined) — which produces Result<undefined, E> — the success type is void: the value's story ends here.

Returns ​

Result<void, E>

Inherited from ​
ts
ResultMethods.discard
ensure() ​
Call Signature ​
ts
ensure<U, E2>(predicate, onFail): Result<U, E | E2>;

Defined in: packages/core/src/types.ts:332

Validate the success value — keep the Ok when predicate holds, otherwise fail into the modeled channel with Err(onFail(value)).

Type Parameters ​
Type ParameterDescription
Uthe refined success type (type-guard form).
E2the error type onFail produces.
Parameters ​
ParameterTypeDescription
predicate(value) => value is Uthe check; a type guard refines T to U.
onFail(value) => E2 & NotThenable<E2>maps the failing value to the modeled error.
Returns ​

Result<U, E | E2>

Remarks ​

The named form of flatMap((v) => (p(v) ? Ok(v) : Err(e))). With a type-guard predicate ((v): v is U) the success type is refined to U on the way through (this overload). Runs only on Ok — a passing value flows through as the same Ok; Err and Defect pass through untouched. A throw in predicate or onFail becomes a Defect.

Both callbacks are synchronous: an async onFail is rejected at compile time (NotThenable), and an async predicate does not type-check either — its Promise<boolean> is not a boolean (and, being truthy, would have silently always passed).

Example ​
ts
// boolean form: gate a value
Ok(-1).ensure((n) => n > 0, (n) => `negative: ${n}`); // Err("negative: -1")

// type-guard form: refine the success type
declare const r: Result<string | number, "e">;
const s = r.ensure(
  (v): v is string => typeof v === "string",
  () => "not_a_string" as const,
); // Result<string, "e" | "not_a_string">
Inherited from ​
ts
ResultMethods.ensure
Call Signature ​
ts
ensure<E2>(predicate, onFail): Result<T, E | E2>;

Defined in: packages/core/src/types.ts:340

Boolean form of ensure — validates without refining, keeping the success type T.

Type Parameters ​
Type Parameter
E2
Parameters ​
ParameterType
predicate(value) => boolean
onFail(value) => E2 & NotThenable<E2>
Returns ​

Result<T, E | E2>

Inherited from ​
ts
ResultMethods.ensure
flatMap() ​
ts
flatMap<U, E2>(f): Result<U, E | E2>;

Defined in: packages/core/src/types.ts:204

Sequence a dependent, Result-returning step (monadic bind).

Runs f only on Ok; Err and Defect pass through. The error channels combine, widening to E | E2. If f throws, the throw becomes a Defect.

Type Parameters ​
Type ParameterDescription
Uthe success type of the next step.
E2the error type the next step may introduce.
Parameters ​
ParameterTypeDescription
f(value) => Result<U, E2>produces the next Result from the current success value.
Returns ​

Result<U, E | E2>

Inherited from ​
ts
ResultMethods.flatMap
flatMapErrCases() ​
ts
flatMapErrCases<M>(f): Result<T | OkOf<MatchOut<M>>, ErrOf<MatchOut<M>>>;

Defined in: packages/core/src/types.ts:397

Sequence from an Err by producing another Result — the error-channel mirror of flatMap, matching the error exhaustively (ErrMatcher; the combinator calls .exhaustive()).

Each branch returns a Result; the outgoing channels are the unions of the branch-returned Results' channels. A branch may return defect(cause). Runs only on Err; Ok and Defect pass through.

Type Parameters ​
Type ParameterDescription
M extends ExhaustiveMatch<Result<unknown, unknown> | Defect>the exhaustive builder the callback returns.
Parameters ​
ParameterTypeDescription
f(matcher, defect) => Mbuilds the match; each branch produces a fallback Result.
Returns ​

Result<T | OkOf<MatchOut<M>>, ErrOf<MatchOut<M>>>

Inherited from ​
ts
ResultMethods.flatMapErrCases
flatTap() ​
ts
flatTap<E2>(f): Result<T, E | E2>;

Defined in: packages/core/src/types.ts:240

Run a failable side effect on the success value, keeping the original value but threading the effect's error.

Type Parameters ​
Type ParameterDescription
E2the error type the effect may introduce.
Parameters ​
ParameterTypeDescription
f(value) => Result<unknown, E2>the failable side effect; its Ok value is ignored.
Returns ​

Result<T, E | E2>

Remarks ​

This is to tap what flatMap is to map: f returns a Result, but its success value is discarded — on success the original value flows through (Result<T, E | E2>), while an Err (or Defect) from f short-circuits. Runs only on Ok; Err and Defect pass through. If f throws, the throw becomes a Defect. Use it for a validation or write whose result matters but whose value you don't need.

Inherited from ​
ts
ResultMethods.flatTap
flatTapErrCases() ​
ts
flatTapErrCases<E2>(f): Result<T, E | E2>;

Defined in: packages/core/src/types.ts:478

Run a failable side effect on the error, keeping the original error but threading the effect's own error — matched exhaustively (ErrMatcher).

Type Parameters ​
Type Parameter
E2
Parameters ​
ParameterTypeDescription
f(matcher, defect) => ExhaustiveMatch<Result<unknown, E2>>builds the match; each branch is a failable effect (its Ok is ignored).
Returns ​

Result<T, E | E2>

Remarks ​

The error-channel mirror of flatTap: each branch returns a Result whose success value is discarded — on the effect's Ok the original Err flows through, while an Err/Defect from a branch short-circuits and threads its error. Note the asymmetry with a throw: a branch that returns a Defect-state Result replaces the original Err (Defect-dominance, the short-circuit rule — it is not aggregated), whereas a branch that throws produces a Defect aggregating [thrown, original failure] (observing a failure by throwing never destroys it). A branch returning the injected defect(cause) marker — reachable under a returnType pin — follows the throw rule, since it is the lint-clean, expression-position form of one.

Inherited from ​
ts
ResultMethods.flatTapErrCases
get() ​
ts
get(this): T;

Defined in: packages/core/src/types.ts:583

Extract the success value.

Parameters ​
ParameterType
this[E] extends [never] ? Result<T, never> : "unthrown: get() needs an empty error channel (E = never) — handle the Err first with recoverErrCases / match / flatMapErrCases, or use getOr / getOrElse / getOrNull / getOrUndefined"
Returns ​

T

the Ok value.

Remarks ​

Compiles only when the error channel is empty (E = never) — eliminate modeled errors first (match / recoverErrCases / flatMapErrCases), or reach for the getOr / getOrElse / getOrNull / getOrUndefined family (which recover an Err). The gate is a this type that becomes an explanatory string when E is not never, so the compile error names the fix.

E = never empties only the modeled error channel — a Defect can still be present, and get() rethrows its original cause (it panics); Result<T, never> does not mean get() cannot throw.

Inherited from ​
ts
ResultMethods.get
getErr() ​
ts
getErr(this): E;

Defined in: packages/core/src/types.ts:601

Extract the modeled error.

Parameters ​
ParameterType
this[T] extends [never] ? Result<never, E> : "unthrown: getErr() needs an empty success channel (T = never) — narrow with isErr() first, or fold with match"
Returns ​

E

the Err value.

Remarks ​

Compiles only when the success channel is empty (T = never) — eliminate the success case first. T = never is rarely the case in practice (a Result you hold usually still has a success type), so to inspect an error prefer an isErr() guard or, in tests, @unthrown/vitest's toBeErrWith. A Defect still rethrows its original cause (a defect is a bug, not an absent value), so this does not mean getErr() can't throw.

Inherited from ​
ts
ResultMethods.getErr
getOr() ​
ts
getOr<U>(fallback): T | U;

Defined in: packages/core/src/types.ts:614

The success value, or fallback on Err.

Type Parameters ​
Type ParameterDescription
Uthe fallback type (may differ from T; the return widens to `T
Parameters ​
ParameterTypeDescription
fallbackUreturned when the result is an Err (may be a different type; the return widens to `T
Returns ​

T | U

Throws ​

Re-throws on a Defect — a Defect is a bug, not an absent value, so it is never silently replaced.

Inherited from ​
ts
ResultMethods.getOr
getOrElse() ​
ts
getOrElse<U>(f): T | U;

Defined in: packages/core/src/types.ts:622

The success value, or f(error) on Err.

Type Parameters ​
Type ParameterDescription
Uthe fallback type (may differ from T; the return widens to `T
Parameters ​
ParameterTypeDescription
f(error) => Ulazily computes the fallback from the error (may return a different type; the return widens to `T
Returns ​

T | U

Throws ​

Re-throws on a Defect.

Inherited from ​
ts
ResultMethods.getOrElse
getOrNull() ​
ts
getOrNull(): T | null;

Defined in: packages/core/src/types.ts:628

The success value, or null on Err.

Returns ​

T | null

Throws ​

Re-throws on a Defect.

Inherited from ​
ts
ResultMethods.getOrNull
getOrThrow() ​
ts
getOrThrow(this): T;

Defined in: packages/core/src/types.ts:666

The success value, or throw the modeled error on Err.

Parameters ​
ParameterType
this[E] extends [never] ? "unthrown: getOrThrow is unnecessary here — the Err channel is empty (E = never), so there is nothing to throw. Use get() instead." : Result<T, E>
Returns ​

T

the Ok value.

Remarks ​

A deliberate escape hatch off the errors-as-values model — it throws the Err value as-is at the call site, so a caller of the enclosing function sees a throw rather than a channel. Its home is tests and scripts, where "this Result had better be Ok" is the assertion and a throw is the correct failure mode.

In production code, fold the error channel instead: recoverErrCases empties E, so get compiles and a case routed to the injected defect(...) panics with its original cause — with every case still named. match and flatMapErrCases are the other two ways to keep the error a value. @unthrown/oxlint's opt-in no-get-or-throw rule enforces this, exempting test files through an oxlint overrides entry.

Type-gated as the complement of get: it compiles only when the error channel is non-empty (E is not never) — there must be a modeled error for it to throw. On a Result<T, never> there is nothing to throw, so getOrThrow does not compile; use get() (which gates the other way). Together they partition extraction by the error channel's state, with no overlap.

Throws ​

the modeled error on Err; re-throws the original cause on a Defect (a panic, like the rest of the getOr… family).

Inherited from ​
ts
ResultMethods.getOrThrow
getOrUndefined() ​
ts
getOrUndefined(): T | undefined;

Defined in: packages/core/src/types.ts:634

The success value, or undefined on Err.

Returns ​

T | undefined

Throws ​

Re-throws on a Defect.

Inherited from ​
ts
ResultMethods.getOrUndefined
isDefect() ​
ts
isDefect(): this is DefectView<T, E>;

Defined in: packages/core/src/types.ts:677

Whether this result is a Defect — narrows this to its DefectView on true.

Returns ​

this is DefectView<T, E>

Inherited from ​
ts
ResultMethods.isDefect
isErr() ​
ts
isErr(): this is ErrView<E, T>;

Defined in: packages/core/src/types.ts:675

Whether this result is Err — narrows this to its ErrView on true.

Returns ​

this is ErrView<E, T>

Inherited from ​
ts
ResultMethods.isErr
isOk() ​
ts
isOk(): this is OkView<T, E>;

Defined in: packages/core/src/types.ts:673

Whether this result is Ok — narrows this to its OkView on true.

Returns ​

this is OkView<T, E>

Inherited from ​
ts
ResultMethods.isOk
let() ​
ts
let<K, U>(name, f): Result<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E>;

Defined in: packages/core/src/types.ts:280

Do-notation: run f for a plain value and bind it under name in the accumulating object scope. The pure-value counterpart of bind.

Type Parameters ​
Type ParameterDescription
K extends stringthe key the value is stored under.
Uthe value type.
Parameters ​
ParameterTypeDescription
nameKthe scope key.
f(scope) => U & NotThenable<U>computes a value from the accumulated scope.
Returns ​

Result<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E>

Remarks ​

f receives the scope and returns a value (not a Result); it is added as { ...scope, [name]: value }. Runs only on Ok; Err/Defect pass through. A throw becomes a Defect. An async callback is rejected at compile time (NotThenable).

Inherited from ​
ts
ResultMethods.let
map() ​
ts
map<U>(f): Result<U, E>;

Defined in: packages/core/src/types.ts:193

Transform the success value with f.

Runs f only on Ok; Err and Defect pass through untouched. If f throws, the thrown value is captured as a Defect.

An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type ParameterDescription
Uthe mapped success type.
Parameters ​
ParameterTypeDescription
f(value) => U & NotThenable<U>maps the current success value to a new one.
Returns ​

Result<U, E>

Inherited from ​
ts
ResultMethods.map
mapErrCases() ​
ts
mapErrCases<M>(f, ..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCases): Result<T, Exclude<MatchOut<M>, Defect>>;

Defined in: packages/core/src/types.ts:379

Transform the modeled error by matching it exhaustively.

Type Parameters ​
Type ParameterDescription
M extends ExhaustiveMatch<unknown>the exhaustive builder the callback returns.
Parameters ​
ParameterTypeDescription
f(matcher, defect) => Mbuilds the match over the error (returns the un-terminated builder).
..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCasesSyncBranches<MatchOut<M>, E>compile-time only; never pass it. Empty for synchronous branches; an async branch demands this impossible argument, so the call fails to compile (its name is the fix).
Returns ​

Result<T, Exclude<MatchOut<M>, Defect>>

Remarks ​

The callback receives match(error) (an ErrMatcher) and the injected defect helper. Chain .with(pattern, handler) and return the un-terminated builder — mapErrCases calls .exhaustive() itself, so a missing case is a compile error at the call site (there is no .exhaustive() to forget, and no way to slip in .otherwise()). The outgoing error type is the union of the branch returns with the Defect arm subtracted (Exclude<O, Defect>) — a branch returning defect(cause) converts that case to a Defect and drops it from E. Runs only on Err; Ok and Defect pass through. A branch that throws also becomes a Defect. Branches are synchronous: an async branch is a compile error (its Promise would land in E un-triaged), and a thenable slipped past the types becomes a Defect.

Name every case. Match on anything the matcher supports — _tag, code, structural shape, guards — and group the cases that share a handler with .with(a, b, handler). .with(P._, …) is the wildcard escape hatch, not the default: it makes any match exhaustive, so it also absorbs every case E grows later. Two uses are sanctioned — a helper generic in E, where no arm list can prove exhaustiveness against an unresolved type parameter, and an E that is a single type rather than a union of cases (see P for both). @unthrown/oxlint's no-catch-all-pattern (in its recommended preset) flags the rest.

Inherited from ​
ts
ResultMethods.mapErrCases
match() ​
ts
match<ROk, RDefect, M>(cases): ROk | RDefect | MatchOut<M>;

Defined in: packages/core/src/types.ts:562

Exhaustively fold all three runtime states into a single value.

Type Parameters ​
Type ParameterDescription
ROkthe ok handler return type.
RDefectthe defect handler return type.
M extends ExhaustiveMatch<unknown>the exhaustive builder the errCases handler returns.
Parameters ​
ParameterTypeDescription
cases{ defect: (cause) => RDefect; errCases: (matcher) => M; ok: (value) => ROk; }the ok/defect handlers plus the errCases matcher builder.
cases.defect(cause) => RDefect-
cases.errCases(matcher) => M-
cases.ok(value) => ROk-
Returns ​

ROk | RDefect | MatchOut<M>

Remarks ​

Exactly one handler runs. Together with the throw-to-Defect guarantee, this is typically the single place a pipeline is handled at the edge — mapping Ok/Err/Defect to (for example) 2xx / 4xx / 5xx with no try/catch.

The errCases handler does not take a single blanket callback: it receives match(error) (an ErrMatcher) and matches the error exhaustively, exactly like the error combinators — which is why the key carries the same …Cases suffix. Chain .with(pattern, handler) and return the un-terminated builder — match calls .exhaustive() itself, so a missing case is a compile error at the call site (no .exhaustive() to forget). Folding at the edge names every case too — .with(P._, …) is the wildcard escape hatch, not the default. Unlike the combinators the branches receive no defect helper — match is total elimination to a value, with no Defect output channel; the defect case handles a Result that already carries one. (A Result is also a discriminated union — for richer whole-Result matching, match(result).with(…).)

Inherited from ​
ts
ResultMethods.match
recoverDefect() ​
ts
recoverDefect<U, E2>(f): Result<T | U, E | E2>;

Defined in: packages/core/src/types.ts:498

Recover from a Defect — the only combinator that can touch one.

Type Parameters ​
Type ParameterDescription
Ua success type the recovery may produce.
E2an error type the recovery may produce.
Parameters ​
ParameterTypeDescription
f(cause) => Result<U, E2>maps the Defect's unknown cause to a recovering Result.
Returns ​

Result<T | U, E | E2>

Remarks ​

Runs f only when a Defect is present, re-entering the modeled world by returning a Result (an Ok or a fresh Err). Ok and Err pass through. Recovering a Defect should be rare: usually you let it bubble to the edge. If f throws, the throw becomes a new Defect.

Inherited from ​
ts
ResultMethods.recoverDefect
recoverErrCases() ​
ts
recoverErrCases<M>(f, ..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCases): Result<T | Exclude<MatchOut<M>, Defect>, never>;

Defined in: packages/core/src/types.ts:421

Recover from an Err by producing a success value, emptying the error channel — matching the error exhaustively (ErrMatcher). Pairs with recoverDefect.

Type Parameters ​
Type ParameterDescription
M extends ExhaustiveMatch<unknown>the exhaustive builder the callback returns.
Parameters ​
ParameterTypeDescription
f(matcher, defect) => Mbuilds the match; each branch produces a success value.
..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCasesSyncBranches<MatchOut<M>, E | T>compile-time only; never pass it. Empty for synchronous branches; an async branch demands this impossible argument, so the call fails to compile (its name is the fix).
Returns ​

Result<T | Exclude<MatchOut<M>, Defect>, never>

Remarks ​

The result type is Result<T | U, never>, but never describes only the error channel — a Defect can still be present at runtime. A branch may return defect(cause) (which stays a Defect, not a recovery). Runs only on Err; Ok and Defect pass through. Branches are synchronous: an async branch is a compile error, and a thenable slipped past the types becomes a Defect.

Inherited from ​
ts
ResultMethods.recoverErrCases
tap() ​
ts
tap<R>(f): Result<T, E>;

Defined in: packages/core/src/types.ts:223

Run a side effect on the success value and pass the Result through unchanged.

Runs only on Ok. If f throws, the throw becomes a Defect. An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterTypeDescription
f(value) => R & NotThenable<R>the side effect (its return value is ignored).
Returns ​

Result<T, E>

Remarks ​

f's return value is ignored — a Result returned by the effect compiles but is discarded, Err and all. If the effect can fail, sequence it instead of tapping it: a Result-returning effect goes in flatTap; an AsyncResult-returning effect cannot be sequenced from the sync surface — lift the chain with toAsync and use the async flatTap (which accepts both).

Inherited from ​
ts
ResultMethods.tap
tapDefect() ​
ts
tapDefect<R>(f): Result<T, E>;

Defined in: packages/core/src/types.ts:508

Run a side effect on a present Defect's cause (e.g. logging) and pass the Defect through unchanged. If f throws, the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterTypeDescription
f(cause) => R & NotThenable<R>the side effect over the unknown cause.
Returns ​

Result<T, E>

Inherited from ​
ts
ResultMethods.tapDefect
tapErrCases() ​
ts
tapErrCases<R>(f): Result<T, E>;

Defined in: packages/core/src/types.ts:450

Run a side effect on the error — matched exhaustively (ErrMatcher) — and pass the Result through unchanged.

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterTypeDescription
f(matcher, defect) => ExhaustiveMatch<R & NotThenable<R>>builds the match; branch returns are ignored, bar defect(cause).
Returns ​

Result<T, E>

Remarks ​

The callback builds a match whose branches run side effects; their return values are ignored and the original Err flows through. Exhaustive like the transformers, and like them it wants every case named — .with(P._, …) remains the wildcard escape hatch. If a branch throws, the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async branch is rejected at compile time (NotThenable on the builder output): because the branch results are discarded, a returned Promise would float unobserved and its rejection would vanish. The one branch return that is not discarded is the injected defect(cause) marker: it is the lint-clean, expression-position form of a throw, so it follows the throw rule above (an AggregateError of [the branch's cause, original failure]), never a silent no-op. A failable Result-returning effect belongs in flatTapErrCases.

Inherited from ​
ts
ResultMethods.tapErrCases
tapFailure() ​
ts
tapFailure<R>(f): Result<T, E>;

Defined in: packages/core/src/types.ts:534

Run a side effect on any failure — Err or Defect — and pass the Result through unchanged. The one cross-channel observer, for the shared "it went KO" concern (logging, metrics, rollback) that would otherwise be duplicated across tapErrCases and tapDefect.

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterTypeDescription
f(failure) => R & NotThenable<R>the side effect over the failure variant (its return value is ignored).
Returns ​

Result<T, E>

Remarks ​

f receives the narrowed failure variant (FailureView), not a payload — the payload union E | unknown would collapse to unknown and lose E's typing. Branch on failure.tag to reach the typed payload ("Err" → failure.error: E, "Defect" → failure.cause: unknown), or treat it opaquely for a shared logger. Runs on Err and Defect; Ok passes through. It observes without consuming: the failure flows on unchanged — to also recover, use recoverErrCases / recoverDefect (deliberately separate acts) or match at the edge. If f throws, the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async callback is rejected at compile time (NotThenable).

Inherited from ​
ts
ResultMethods.tapFailure
toAsync() ​
ts
toAsync(): AsyncResult<T, E>;

Defined in: packages/core/src/types.ts:680

Lift this synchronous Result into an AsyncResult.

Returns ​

AsyncResult<T, E>

Inherited from ​
ts
ResultMethods.toAsync

OkView ​

Defined in: packages/core/src/types.ts:696

The Ok variant of a Result: a success carrying a value. This is what a successful isOk guard narrows to, making .value reachable. It also carries the shared fluent surface (ResultMethods).

Example ​

ts
if (r.isOk()) r.value; // r: OkView<T, E> here — .value is a T

Extends ​

Type Parameters ​

Type ParameterDefault type
T-
Enever

Properties ​

PropertyModifierTypeDefined in
tagreadonly"Ok"packages/core/src/types.ts:697
valuereadonlyTpackages/core/src/types.ts:698

Methods ​

as() ​
ts
as<U>(value): Result<U, E>;

Defined in: packages/core/src/types.ts:288

Replace the success value with a constant value.

Runs only on Ok; Err and Defect pass through.

Type Parameters ​
Type ParameterDescription
Uthe replacement value type.
Parameters ​
ParameterType
valueU
Returns ​

Result<U, E>

Inherited from ​
ts
ResultMethods.as
bind() ​
ts
bind<K, U, E2>(name, f): Result<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E | E2>;

Defined in: packages/core/src/types.ts:261

Do-notation: run f for a Result and bind its value under name in an accumulating object scope.

Type Parameters ​
Type ParameterDescription
K extends stringthe key the bound value is stored under.
Uthe bound value type.
E2the error type f may introduce.
Parameters ​
ParameterTypeDescription
nameKthe scope key.
f(scope) => Result<U, E2>produces a Result from the accumulated scope.
Returns ​

Result<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E | E2>

Remarks ​

Begin a chain with Do (an empty object scope) and grow it step by step. f receives the scope accumulated so far and returns a Result; on Ok the value is added as { ...scope, [name]: value }, on Err/Defect the chain short-circuits. Errors union (E | E2). A throw becomes a Defect — as does calling bind on a non-object or non-plain scope (e.g. Ok(5).bind, or a class instance whose getters the merge would drop), which is misuse: the scope is always a plain object inside a real Do() chain. (let is the pure-value counterpart.)

Inherited from ​
ts
ResultMethods.bind
discard() ​
ts
discard(): Result<void, E>;

Defined in: packages/core/src/types.ts:297

Drop the success value, collapsing the success type to void.

The named form of map(() => undefined). Runs only on Ok (the value is replaced with undefined); Err and Defect pass through. Unlike as(undefined) — which produces Result<undefined, E> — the success type is void: the value's story ends here.

Returns ​

Result<void, E>

Inherited from ​
ts
ResultMethods.discard
ensure() ​
Call Signature ​
ts
ensure<U, E2>(predicate, onFail): Result<U, E | E2>;

Defined in: packages/core/src/types.ts:332

Validate the success value — keep the Ok when predicate holds, otherwise fail into the modeled channel with Err(onFail(value)).

Type Parameters ​
Type ParameterDescription
Uthe refined success type (type-guard form).
E2the error type onFail produces.
Parameters ​
ParameterTypeDescription
predicate(value) => value is Uthe check; a type guard refines T to U.
onFail(value) => E2 & NotThenable<E2>maps the failing value to the modeled error.
Returns ​

Result<U, E | E2>

Remarks ​

The named form of flatMap((v) => (p(v) ? Ok(v) : Err(e))). With a type-guard predicate ((v): v is U) the success type is refined to U on the way through (this overload). Runs only on Ok — a passing value flows through as the same Ok; Err and Defect pass through untouched. A throw in predicate or onFail becomes a Defect.

Both callbacks are synchronous: an async onFail is rejected at compile time (NotThenable), and an async predicate does not type-check either — its Promise<boolean> is not a boolean (and, being truthy, would have silently always passed).

Example ​
ts
// boolean form: gate a value
Ok(-1).ensure((n) => n > 0, (n) => `negative: ${n}`); // Err("negative: -1")

// type-guard form: refine the success type
declare const r: Result<string | number, "e">;
const s = r.ensure(
  (v): v is string => typeof v === "string",
  () => "not_a_string" as const,
); // Result<string, "e" | "not_a_string">
Inherited from ​
ts
ResultMethods.ensure
Call Signature ​
ts
ensure<E2>(predicate, onFail): Result<T, E | E2>;

Defined in: packages/core/src/types.ts:340

Boolean form of ensure — validates without refining, keeping the success type T.

Type Parameters ​
Type Parameter
E2
Parameters ​
ParameterType
predicate(value) => boolean
onFail(value) => E2 & NotThenable<E2>
Returns ​

Result<T, E | E2>

Inherited from ​
ts
ResultMethods.ensure
flatMap() ​
ts
flatMap<U, E2>(f): Result<U, E | E2>;

Defined in: packages/core/src/types.ts:204

Sequence a dependent, Result-returning step (monadic bind).

Runs f only on Ok; Err and Defect pass through. The error channels combine, widening to E | E2. If f throws, the throw becomes a Defect.

Type Parameters ​
Type ParameterDescription
Uthe success type of the next step.
E2the error type the next step may introduce.
Parameters ​
ParameterTypeDescription
f(value) => Result<U, E2>produces the next Result from the current success value.
Returns ​

Result<U, E | E2>

Inherited from ​
ts
ResultMethods.flatMap
flatMapErrCases() ​
ts
flatMapErrCases<M>(f): Result<T | OkOf<MatchOut<M>>, ErrOf<MatchOut<M>>>;

Defined in: packages/core/src/types.ts:397

Sequence from an Err by producing another Result — the error-channel mirror of flatMap, matching the error exhaustively (ErrMatcher; the combinator calls .exhaustive()).

Each branch returns a Result; the outgoing channels are the unions of the branch-returned Results' channels. A branch may return defect(cause). Runs only on Err; Ok and Defect pass through.

Type Parameters ​
Type ParameterDescription
M extends ExhaustiveMatch<Result<unknown, unknown> | Defect>the exhaustive builder the callback returns.
Parameters ​
ParameterTypeDescription
f(matcher, defect) => Mbuilds the match; each branch produces a fallback Result.
Returns ​

Result<T | OkOf<MatchOut<M>>, ErrOf<MatchOut<M>>>

Inherited from ​
ts
ResultMethods.flatMapErrCases
flatTap() ​
ts
flatTap<E2>(f): Result<T, E | E2>;

Defined in: packages/core/src/types.ts:240

Run a failable side effect on the success value, keeping the original value but threading the effect's error.

Type Parameters ​
Type ParameterDescription
E2the error type the effect may introduce.
Parameters ​
ParameterTypeDescription
f(value) => Result<unknown, E2>the failable side effect; its Ok value is ignored.
Returns ​

Result<T, E | E2>

Remarks ​

This is to tap what flatMap is to map: f returns a Result, but its success value is discarded — on success the original value flows through (Result<T, E | E2>), while an Err (or Defect) from f short-circuits. Runs only on Ok; Err and Defect pass through. If f throws, the throw becomes a Defect. Use it for a validation or write whose result matters but whose value you don't need.

Inherited from ​
ts
ResultMethods.flatTap
flatTapErrCases() ​
ts
flatTapErrCases<E2>(f): Result<T, E | E2>;

Defined in: packages/core/src/types.ts:478

Run a failable side effect on the error, keeping the original error but threading the effect's own error — matched exhaustively (ErrMatcher).

Type Parameters ​
Type Parameter
E2
Parameters ​
ParameterTypeDescription
f(matcher, defect) => ExhaustiveMatch<Result<unknown, E2>>builds the match; each branch is a failable effect (its Ok is ignored).
Returns ​

Result<T, E | E2>

Remarks ​

The error-channel mirror of flatTap: each branch returns a Result whose success value is discarded — on the effect's Ok the original Err flows through, while an Err/Defect from a branch short-circuits and threads its error. Note the asymmetry with a throw: a branch that returns a Defect-state Result replaces the original Err (Defect-dominance, the short-circuit rule — it is not aggregated), whereas a branch that throws produces a Defect aggregating [thrown, original failure] (observing a failure by throwing never destroys it). A branch returning the injected defect(cause) marker — reachable under a returnType pin — follows the throw rule, since it is the lint-clean, expression-position form of one.

Inherited from ​
ts
ResultMethods.flatTapErrCases
get() ​
ts
get(this): T;

Defined in: packages/core/src/types.ts:583

Extract the success value.

Parameters ​
ParameterType
this[E] extends [never] ? Result<T, never> : "unthrown: get() needs an empty error channel (E = never) — handle the Err first with recoverErrCases / match / flatMapErrCases, or use getOr / getOrElse / getOrNull / getOrUndefined"
Returns ​

T

the Ok value.

Remarks ​

Compiles only when the error channel is empty (E = never) — eliminate modeled errors first (match / recoverErrCases / flatMapErrCases), or reach for the getOr / getOrElse / getOrNull / getOrUndefined family (which recover an Err). The gate is a this type that becomes an explanatory string when E is not never, so the compile error names the fix.

E = never empties only the modeled error channel — a Defect can still be present, and get() rethrows its original cause (it panics); Result<T, never> does not mean get() cannot throw.

Inherited from ​
ts
ResultMethods.get
getErr() ​
ts
getErr(this): E;

Defined in: packages/core/src/types.ts:601

Extract the modeled error.

Parameters ​
ParameterType
this[T] extends [never] ? Result<never, E> : "unthrown: getErr() needs an empty success channel (T = never) — narrow with isErr() first, or fold with match"
Returns ​

E

the Err value.

Remarks ​

Compiles only when the success channel is empty (T = never) — eliminate the success case first. T = never is rarely the case in practice (a Result you hold usually still has a success type), so to inspect an error prefer an isErr() guard or, in tests, @unthrown/vitest's toBeErrWith. A Defect still rethrows its original cause (a defect is a bug, not an absent value), so this does not mean getErr() can't throw.

Inherited from ​
ts
ResultMethods.getErr
getOr() ​
ts
getOr<U>(fallback): T | U;

Defined in: packages/core/src/types.ts:614

The success value, or fallback on Err.

Type Parameters ​
Type ParameterDescription
Uthe fallback type (may differ from T; the return widens to `T
Parameters ​
ParameterTypeDescription
fallbackUreturned when the result is an Err (may be a different type; the return widens to `T
Returns ​

T | U

Throws ​

Re-throws on a Defect — a Defect is a bug, not an absent value, so it is never silently replaced.

Inherited from ​
ts
ResultMethods.getOr
getOrElse() ​
ts
getOrElse<U>(f): T | U;

Defined in: packages/core/src/types.ts:622

The success value, or f(error) on Err.

Type Parameters ​
Type ParameterDescription
Uthe fallback type (may differ from T; the return widens to `T
Parameters ​
ParameterTypeDescription
f(error) => Ulazily computes the fallback from the error (may return a different type; the return widens to `T
Returns ​

T | U

Throws ​

Re-throws on a Defect.

Inherited from ​
ts
ResultMethods.getOrElse
getOrNull() ​
ts
getOrNull(): T | null;

Defined in: packages/core/src/types.ts:628

The success value, or null on Err.

Returns ​

T | null

Throws ​

Re-throws on a Defect.

Inherited from ​
ts
ResultMethods.getOrNull
getOrThrow() ​
ts
getOrThrow(this): T;

Defined in: packages/core/src/types.ts:666

The success value, or throw the modeled error on Err.

Parameters ​
ParameterType
this[E] extends [never] ? "unthrown: getOrThrow is unnecessary here — the Err channel is empty (E = never), so there is nothing to throw. Use get() instead." : Result<T, E>
Returns ​

T

the Ok value.

Remarks ​

A deliberate escape hatch off the errors-as-values model — it throws the Err value as-is at the call site, so a caller of the enclosing function sees a throw rather than a channel. Its home is tests and scripts, where "this Result had better be Ok" is the assertion and a throw is the correct failure mode.

In production code, fold the error channel instead: recoverErrCases empties E, so get compiles and a case routed to the injected defect(...) panics with its original cause — with every case still named. match and flatMapErrCases are the other two ways to keep the error a value. @unthrown/oxlint's opt-in no-get-or-throw rule enforces this, exempting test files through an oxlint overrides entry.

Type-gated as the complement of get: it compiles only when the error channel is non-empty (E is not never) — there must be a modeled error for it to throw. On a Result<T, never> there is nothing to throw, so getOrThrow does not compile; use get() (which gates the other way). Together they partition extraction by the error channel's state, with no overlap.

Throws ​

the modeled error on Err; re-throws the original cause on a Defect (a panic, like the rest of the getOr… family).

Inherited from ​
ts
ResultMethods.getOrThrow
getOrUndefined() ​
ts
getOrUndefined(): T | undefined;

Defined in: packages/core/src/types.ts:634

The success value, or undefined on Err.

Returns ​

T | undefined

Throws ​

Re-throws on a Defect.

Inherited from ​
ts
ResultMethods.getOrUndefined
isDefect() ​
ts
isDefect(): this is DefectView<T, E>;

Defined in: packages/core/src/types.ts:677

Whether this result is a Defect — narrows this to its DefectView on true.

Returns ​

this is DefectView<T, E>

Inherited from ​
ts
ResultMethods.isDefect
isErr() ​
ts
isErr(): this is ErrView<E, T>;

Defined in: packages/core/src/types.ts:675

Whether this result is Err — narrows this to its ErrView on true.

Returns ​

this is ErrView<E, T>

Inherited from ​
ts
ResultMethods.isErr
isOk() ​
ts
isOk(): this is OkView<T, E>;

Defined in: packages/core/src/types.ts:673

Whether this result is Ok — narrows this to its OkView on true.

Returns ​

this is OkView<T, E>

Inherited from ​
ts
ResultMethods.isOk
let() ​
ts
let<K, U>(name, f): Result<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E>;

Defined in: packages/core/src/types.ts:280

Do-notation: run f for a plain value and bind it under name in the accumulating object scope. The pure-value counterpart of bind.

Type Parameters ​
Type ParameterDescription
K extends stringthe key the value is stored under.
Uthe value type.
Parameters ​
ParameterTypeDescription
nameKthe scope key.
f(scope) => U & NotThenable<U>computes a value from the accumulated scope.
Returns ​

Result<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E>

Remarks ​

f receives the scope and returns a value (not a Result); it is added as { ...scope, [name]: value }. Runs only on Ok; Err/Defect pass through. A throw becomes a Defect. An async callback is rejected at compile time (NotThenable).

Inherited from ​
ts
ResultMethods.let
map() ​
ts
map<U>(f): Result<U, E>;

Defined in: packages/core/src/types.ts:193

Transform the success value with f.

Runs f only on Ok; Err and Defect pass through untouched. If f throws, the thrown value is captured as a Defect.

An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type ParameterDescription
Uthe mapped success type.
Parameters ​
ParameterTypeDescription
f(value) => U & NotThenable<U>maps the current success value to a new one.
Returns ​

Result<U, E>

Inherited from ​
ts
ResultMethods.map
mapErrCases() ​
ts
mapErrCases<M>(f, ..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCases): Result<T, Exclude<MatchOut<M>, Defect>>;

Defined in: packages/core/src/types.ts:379

Transform the modeled error by matching it exhaustively.

Type Parameters ​
Type ParameterDescription
M extends ExhaustiveMatch<unknown>the exhaustive builder the callback returns.
Parameters ​
ParameterTypeDescription
f(matcher, defect) => Mbuilds the match over the error (returns the un-terminated builder).
..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCasesSyncBranches<MatchOut<M>, E>compile-time only; never pass it. Empty for synchronous branches; an async branch demands this impossible argument, so the call fails to compile (its name is the fix).
Returns ​

Result<T, Exclude<MatchOut<M>, Defect>>

Remarks ​

The callback receives match(error) (an ErrMatcher) and the injected defect helper. Chain .with(pattern, handler) and return the un-terminated builder — mapErrCases calls .exhaustive() itself, so a missing case is a compile error at the call site (there is no .exhaustive() to forget, and no way to slip in .otherwise()). The outgoing error type is the union of the branch returns with the Defect arm subtracted (Exclude<O, Defect>) — a branch returning defect(cause) converts that case to a Defect and drops it from E. Runs only on Err; Ok and Defect pass through. A branch that throws also becomes a Defect. Branches are synchronous: an async branch is a compile error (its Promise would land in E un-triaged), and a thenable slipped past the types becomes a Defect.

Name every case. Match on anything the matcher supports — _tag, code, structural shape, guards — and group the cases that share a handler with .with(a, b, handler). .with(P._, …) is the wildcard escape hatch, not the default: it makes any match exhaustive, so it also absorbs every case E grows later. Two uses are sanctioned — a helper generic in E, where no arm list can prove exhaustiveness against an unresolved type parameter, and an E that is a single type rather than a union of cases (see P for both). @unthrown/oxlint's no-catch-all-pattern (in its recommended preset) flags the rest.

Inherited from ​
ts
ResultMethods.mapErrCases
match() ​
ts
match<ROk, RDefect, M>(cases): ROk | RDefect | MatchOut<M>;

Defined in: packages/core/src/types.ts:562

Exhaustively fold all three runtime states into a single value.

Type Parameters ​
Type ParameterDescription
ROkthe ok handler return type.
RDefectthe defect handler return type.
M extends ExhaustiveMatch<unknown>the exhaustive builder the errCases handler returns.
Parameters ​
ParameterTypeDescription
cases{ defect: (cause) => RDefect; errCases: (matcher) => M; ok: (value) => ROk; }the ok/defect handlers plus the errCases matcher builder.
cases.defect(cause) => RDefect-
cases.errCases(matcher) => M-
cases.ok(value) => ROk-
Returns ​

ROk | RDefect | MatchOut<M>

Remarks ​

Exactly one handler runs. Together with the throw-to-Defect guarantee, this is typically the single place a pipeline is handled at the edge — mapping Ok/Err/Defect to (for example) 2xx / 4xx / 5xx with no try/catch.

The errCases handler does not take a single blanket callback: it receives match(error) (an ErrMatcher) and matches the error exhaustively, exactly like the error combinators — which is why the key carries the same …Cases suffix. Chain .with(pattern, handler) and return the un-terminated builder — match calls .exhaustive() itself, so a missing case is a compile error at the call site (no .exhaustive() to forget). Folding at the edge names every case too — .with(P._, …) is the wildcard escape hatch, not the default. Unlike the combinators the branches receive no defect helper — match is total elimination to a value, with no Defect output channel; the defect case handles a Result that already carries one. (A Result is also a discriminated union — for richer whole-Result matching, match(result).with(…).)

Inherited from ​
ts
ResultMethods.match
recoverDefect() ​
ts
recoverDefect<U, E2>(f): Result<T | U, E | E2>;

Defined in: packages/core/src/types.ts:498

Recover from a Defect — the only combinator that can touch one.

Type Parameters ​
Type ParameterDescription
Ua success type the recovery may produce.
E2an error type the recovery may produce.
Parameters ​
ParameterTypeDescription
f(cause) => Result<U, E2>maps the Defect's unknown cause to a recovering Result.
Returns ​

Result<T | U, E | E2>

Remarks ​

Runs f only when a Defect is present, re-entering the modeled world by returning a Result (an Ok or a fresh Err). Ok and Err pass through. Recovering a Defect should be rare: usually you let it bubble to the edge. If f throws, the throw becomes a new Defect.

Inherited from ​
ts
ResultMethods.recoverDefect
recoverErrCases() ​
ts
recoverErrCases<M>(f, ..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCases): Result<T | Exclude<MatchOut<M>, Defect>, never>;

Defined in: packages/core/src/types.ts:421

Recover from an Err by producing a success value, emptying the error channel — matching the error exhaustively (ErrMatcher). Pairs with recoverDefect.

Type Parameters ​
Type ParameterDescription
M extends ExhaustiveMatch<unknown>the exhaustive builder the callback returns.
Parameters ​
ParameterTypeDescription
f(matcher, defect) => Mbuilds the match; each branch produces a success value.
..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCasesSyncBranches<MatchOut<M>, T | E>compile-time only; never pass it. Empty for synchronous branches; an async branch demands this impossible argument, so the call fails to compile (its name is the fix).
Returns ​

Result<T | Exclude<MatchOut<M>, Defect>, never>

Remarks ​

The result type is Result<T | U, never>, but never describes only the error channel — a Defect can still be present at runtime. A branch may return defect(cause) (which stays a Defect, not a recovery). Runs only on Err; Ok and Defect pass through. Branches are synchronous: an async branch is a compile error, and a thenable slipped past the types becomes a Defect.

Inherited from ​
ts
ResultMethods.recoverErrCases
tap() ​
ts
tap<R>(f): Result<T, E>;

Defined in: packages/core/src/types.ts:223

Run a side effect on the success value and pass the Result through unchanged.

Runs only on Ok. If f throws, the throw becomes a Defect. An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterTypeDescription
f(value) => R & NotThenable<R>the side effect (its return value is ignored).
Returns ​

Result<T, E>

Remarks ​

f's return value is ignored — a Result returned by the effect compiles but is discarded, Err and all. If the effect can fail, sequence it instead of tapping it: a Result-returning effect goes in flatTap; an AsyncResult-returning effect cannot be sequenced from the sync surface — lift the chain with toAsync and use the async flatTap (which accepts both).

Inherited from ​
ts
ResultMethods.tap
tapDefect() ​
ts
tapDefect<R>(f): Result<T, E>;

Defined in: packages/core/src/types.ts:508

Run a side effect on a present Defect's cause (e.g. logging) and pass the Defect through unchanged. If f throws, the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterTypeDescription
f(cause) => R & NotThenable<R>the side effect over the unknown cause.
Returns ​

Result<T, E>

Inherited from ​
ts
ResultMethods.tapDefect
tapErrCases() ​
ts
tapErrCases<R>(f): Result<T, E>;

Defined in: packages/core/src/types.ts:450

Run a side effect on the error — matched exhaustively (ErrMatcher) — and pass the Result through unchanged.

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterTypeDescription
f(matcher, defect) => ExhaustiveMatch<R & NotThenable<R>>builds the match; branch returns are ignored, bar defect(cause).
Returns ​

Result<T, E>

Remarks ​

The callback builds a match whose branches run side effects; their return values are ignored and the original Err flows through. Exhaustive like the transformers, and like them it wants every case named — .with(P._, …) remains the wildcard escape hatch. If a branch throws, the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async branch is rejected at compile time (NotThenable on the builder output): because the branch results are discarded, a returned Promise would float unobserved and its rejection would vanish. The one branch return that is not discarded is the injected defect(cause) marker: it is the lint-clean, expression-position form of a throw, so it follows the throw rule above (an AggregateError of [the branch's cause, original failure]), never a silent no-op. A failable Result-returning effect belongs in flatTapErrCases.

Inherited from ​
ts
ResultMethods.tapErrCases
tapFailure() ​
ts
tapFailure<R>(f): Result<T, E>;

Defined in: packages/core/src/types.ts:534

Run a side effect on any failure — Err or Defect — and pass the Result through unchanged. The one cross-channel observer, for the shared "it went KO" concern (logging, metrics, rollback) that would otherwise be duplicated across tapErrCases and tapDefect.

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterTypeDescription
f(failure) => R & NotThenable<R>the side effect over the failure variant (its return value is ignored).
Returns ​

Result<T, E>

Remarks ​

f receives the narrowed failure variant (FailureView), not a payload — the payload union E | unknown would collapse to unknown and lose E's typing. Branch on failure.tag to reach the typed payload ("Err" → failure.error: E, "Defect" → failure.cause: unknown), or treat it opaquely for a shared logger. Runs on Err and Defect; Ok passes through. It observes without consuming: the failure flows on unchanged — to also recover, use recoverErrCases / recoverDefect (deliberately separate acts) or match at the edge. If f throws, the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async callback is rejected at compile time (NotThenable).

Inherited from ​
ts
ResultMethods.tapFailure
toAsync() ​
ts
toAsync(): AsyncResult<T, E>;

Defined in: packages/core/src/types.ts:680

Lift this synchronous Result into an AsyncResult.

Returns ​

AsyncResult<T, E>

Inherited from ​
ts
ResultMethods.toAsync

AsyncErrOf ​

ts
type AsyncErrOf<R> = R extends Awaitable<infer Res> ? ErrOf<Res> : never;

Defined in: packages/core/src/types.ts:1110

Extract the error type E from an AsyncResult type — the async counterpart of ErrOf.

Type Parameters ​

Type ParameterDescription
Rthe AsyncResult type to inspect.

Example ​

ts
type E = AsyncErrOf<AsyncResult<User, NotFound>>; // NotFound

AsyncOkOf ​

ts
type AsyncOkOf<R> = R extends Awaitable<infer Res> ? OkOf<Res> : never;

Defined in: packages/core/src/types.ts:1096

Extract the success type T from an AsyncResult type — the async counterpart of OkOf.

Type Parameters ​

Type ParameterDescription
Rthe AsyncResult type to inspect.

Example ​

ts
type T = AsyncOkOf<AsyncResult<User, NotFound>>; // User

Awaitable ​

ts
type Awaitable<T> = object;

Defined in: packages/core/src/types.ts:786

A success-only thenable: awaitable, but deliberately not a full PromiseLike.

Remarks ​

An AsyncResult's internal promise never rejects, so await-ing one always yields a Result and never throws — there is no rejection channel to model, and none is advertised. At runtime it is still a thenable (the only way await can collapse it), and Promise.all / Promise.resolve will still adopt it — harmlessly, since it settles to a Result and never rejects. What the narrowing prevents is treating it as a full promise: .catch() / .finally() do not type-check, because there is no rejection to handle.

Extended by ​

Type Parameters ​

Type ParameterDescription
Tthe value await resolves to.

Methods ​

then() ​
ts
then<R>(onfulfilled?): PromiseLike<R>;

Defined in: packages/core/src/types.ts:787

Type Parameters ​
Type ParameterDefault type
RT
Parameters ​
ParameterType
onfulfilled?((value) => R | PromiseLike<R>) | null
Returns ​

PromiseLike<R>


ErrMatcher ​

ts
type ErrMatcher<E> = ReturnType<typeof match>;

Defined in: packages/core/src/types.ts:73

The built-in match builder over an error union E, as produced by match(error). This is what an error combinator's callback receives — chain .with(pattern, handler) on it; the combinator itself calls .exhaustive(), so the callback returns the un-terminated builder.

Type Parameters ​

Type ParameterDescription
Ethe error union being matched.

Remarks ​

Named via ReturnType<typeof match<E>> (i.e. Matcher<E, E, never>), keeping this alias stable however the builder evolves.


ErrOf ​

ts
type ErrOf<R> = R extends object ? E : never;

Defined in: packages/core/src/types.ts:1082

Extract the error type E from a Result type — the counterpart of OkOf.

Type Parameters ​

Type ParameterDescription
Rthe Result type to inspect.

Example ​

ts
type E = ErrOf<Result<User, NotFound>>; // NotFound

FailureView ​

ts
type FailureView<E, T> = 
  | ErrView<E, T>
  | DefectView<T, E>;

Defined in: packages/core/src/types.ts:766

A failure variant of a Result: an ErrView or a DefectView. This is what a tapFailure callback receives — the discriminated variant rather than a payload, because the payload union E | unknown would collapse to unknown and lose E's typing. Branch on tag to narrow ("Err" → .error: E, "Defect" → .cause: unknown).

Type Parameters ​

Type ParameterDefault typeDescription
E-the modeled error type.
Tneverthe success value type (phantom here; a failure carries none).

Remarks ​

Like ErrView, the error type comes first (FailureView<E, T>) — the error is the payload you are usually here for, and a shared observer can spell just FailureView<MyError>.

Example ​

ts
const logKo = (f: FailureView<ApiError>) =>
  f.tag === "Err" ? logger.warn(f.error) : logger.error(f.cause);
result.tapFailure(logKo);

Matcher ​

ts
type Matcher<E, Remaining, O, Declared> = object;

Defined in: packages/core/src/matcher.ts:185

The match builder over an input union E. Remaining tracks the cases not yet covered by a .with(…) arm; O accumulates the branch output union. .exhaustive is callable only once Remaining is never — which is what the ExhaustiveMatch constraint requires — and .run() executes it.

Type Parameters ​

Type ParameterDefault typeDescription
E-the full input union being matched.
Remaining-the cases not yet covered.
O-the union of branch return types so far.
DeclaredUnset-

Properties ​

PropertyTypeDescriptionDefined in
exhaustive[Remaining] extends [never] ? () => PinnedOut<Declared, O> : UnhandledCases<Remaining>Terminate the match. Typed callable only when every case is covered (Remaining is never); otherwise it is a branded diagnostic object naming the remaining cases, and the builder fails the ExhaustiveMatch constraint at the combinator call site.packages/core/src/matcher.ts:257
returnType[O] extends [never] ? [Declared] extends [Unset] ? <R>() => Matcher<E, Remaining, never, R> : PinTooLate : PinTooLateDeclare the match's output type up front: every subsequent branch handler is checked against R, and the match evaluates to R instead of the union of whatever the branches happened to return. Remarks Reach for it when the output is decided by a signature rather than by the branches — most sharply in code generic in E, where the fold's type has to be declared. It also stops a drifting branch from silently widening the outgoing type, reports the mismatch on the offending branch, and gives branch returns a contextual type (so object literals need no annotation). A branch may still return the injected defect helper's marker; the defect channel is not part of the declared output. Callable before any arm has produced an output, and only once (mirroring ts-pattern's up-front pin): once there is an inferred output for the pin to contradict — or the builder is already pinned — this is typed as a non-callable diagnostic. In practice that means calling it directly after match(…); the gate is about output rather than position, so an earlier arm whose handler returns never (it always throws) contributes nothing and does not close it — sound, since a never branch can contradict no declared type. A no-op at runtime. Type Param R the declared output type of every branch.packages/core/src/matcher.ts:245

Methods ​

run() ​
ts
run(): PinnedOut<Declared, O>;

Defined in: packages/core/src/matcher.ts:266

Execute the match (the combinators call this; it runs .exhaustive()). A value with no matching arm throws NonExhaustiveError — unreachable for well-typed callers.

Returns ​

PinnedOut<Declared, O>

with() ​
Call Signature ​
ts
with<O2>(pattern, handler): Matcher<E, never, O | O2, Declared>;

Defined in: packages/core/src/matcher.ts:200

The catch-all arm: .with(P._, handler) — the wildcard escape hatch, not the way to handle a concrete error union (name those cases; @unthrown/oxlint's no-catch-all-pattern, in its recommended preset, flags the wildcard).

It is a state transition, not a computation — it returns Matcher<E, never, …> with the remaining cases literally never, so the builder is provably exhaustive even when E is an unresolved type parameter (a lazily-deferred Exclude<E, unknown> would not resolve there). That is what makes it irreplaceable for a helper generic in E: it can terminate a match no arm list could (issue #145) — one of the two sanctioned uses (see P).

Type Parameters ​
Type Parameter
O2
Parameters ​
ParameterType
patternUniversalPattern
handler(value) => BranchReturn<Declared, O2>
Returns ​

Matcher<E, never, O | O2, Declared>

Call Signature ​
ts
with<Pts, O2>(...args): Matcher<E, Exclude<Remaining, MatchedOf<Pts[number]>>, O | O2, Declared>;

Defined in: packages/core/src/matcher.ts:211

Add an arm: one or more patterns sharing a single handler (grouped patterns — matcher.with(P.tag("A"), P.tag("B"), handler)). The handler receives the input narrowed to what the patterns match (computed against Remaining, so cases already handled by earlier arms are excluded); the matched cases are subtracted from Remaining.

Type Parameters ​
Type Parameter
Pts extends readonly [unknown, unknown]
O2
Parameters ​
ParameterType
...args[...patterns: { [I in string | number | symbol]: NoEmptyPattern<Pts[I]> }[], (value) => BranchReturn<Declared, O2>]
Returns ​

Matcher<E, Exclude<Remaining, MatchedOf<Pts[number]>>, O | O2, Declared>


NotThenable ​

ts
type NotThenable<R> = [Extract<R, PromiseLike<unknown>>] extends [never] ? unknown : "unthrown: combinator callbacks are synchronous — lift async work with fromPromise and compose with flatMap";

Defined in: packages/core/src/types.ts:56

Compile-time rejection of a thenable callback result — the type-level enforcement of "combinator callbacks are synchronous" (see the AsyncResult remarks).

Type Parameters ​

Type ParameterDescription
Rthe callback's inferred return type.

Remarks ​

Resolves to unknown (a no-op in an intersection) for any non-thenable R, and to an explanatory string-literal type when R is a PromiseLike — so an async callback fails to compile with the explanation in the error. Without this, async () => … would be assignable to () => void, and its rejection would escape the pipeline as an unhandled rejection instead of a Defect. Lift async work with fromPromise and compose it with flatMap.

Spelled with Extract, not [R] extends [PromiseLike<…>], so the ban also fires when only SOME arms of a union return are thenable — a sometimes-async callback (flag ? 1 : work()) is still an unawaited effect whose rejection the pipeline never sees. The tuple-wrapped form is false for a partial union and let exactly that through. This is the same reasoning fromPromise's async-qualify guard already used.


OkOf ​

ts
type OkOf<R> = R extends object ? T : never;

Defined in: packages/core/src/types.ts:1068

Extract the success type T from a Result type — derive one type from another instead of restating it (e.g. the payload a function returns).

Type Parameters ​

Type ParameterDescription
Rthe Result type to inspect.

Example ​

ts
type R = Result<User, NotFound>;
type U = OkOf<R>; // User
type E = ErrOf<R>; // NotFound

PatternMatcher ​

ts
type PatternMatcher<M> = object;

Defined in: packages/core/src/matcher.ts:50

A P.* pattern: a runtime predicate plus the phantom type M it matches. The phantom is declaration-only (never present at runtime); it drives the type-level narrowing (Extract) and exhaustiveness (Exclude).

Type Parameters ​

Type ParameterDescription
Mthe type this pattern matches.

Properties ​

PropertyModifierTypeDefined in
[MATCHES]?readonlyMpackages/core/src/matcher.ts:52
[PATTERN_BRAND]readonly(value) => booleanpackages/core/src/matcher.ts:51

Settle ​

ts
type Settle<T, E> = (result) => void;

Defined in: packages/core/src/interop.ts:308

The settler a fromExecutor executor receives. Settles the pending AsyncResult once — later calls are no-ops, exactly as resolve is on a Promise.

Type Parameters ​

Type ParameterDescription
Tthe success type.
Ethe modeled error type.

Parameters ​

ParameterType
resultResult<T, E> | Defect

Returns ​

void


TaggedErrorConstructor ​

ts
type TaggedErrorConstructor<Tag> = <A>(args) => TaggedErrorInstance<Tag, A>;

Defined in: packages/core/src/tagged.ts:39

The class constructor returned by TaggedError. Generic in its payload: apply it with an instantiation expression at the extends site.

Type Parameters ​

Type ParameterDescription
Tag extends stringthe string literal discriminant.

Parameters ​

ParameterType
argskeyof A extends never ? void : A & object

Returns ​

TaggedErrorInstance<Tag, A>

Remarks ​

When the payload is empty, the constructor takes no arguments (the keyof A extends never ? void : A trick); otherwise it takes the payload. The name, message, and stack keys are all rejected (?: never) because all three are reserved: name is the display label, message is the human string owned by Error, and stack is Error's trace. Set the message the standard way — override message = "…" (or a constructor override) on the subclass — never as a free-form per-call payload field. The reservations are enforced at the call site, mirroring how TaggedErrorInstance excludes all three. (cause is deliberately not reserved: Error.cause is unknown, so a typed payload cause is a legitimate structured field.)


TaggedErrorInstance ​

ts
type TaggedErrorInstance<Tag, A> = Error & Readonly<Omit<A, "name" | "message" | "stack">> & object;

Defined in: packages/core/src/tagged.ts:16

The instance shape produced by a TaggedError class: an Error plus a _tag discriminant and the (readonly) payload fields.

Type Declaration ​

NameTypeDefined in
_tagTagpackages/core/src/tagged.ts:17

Type Parameters ​

Type ParameterDescription
Tag extends stringthe string literal discriminant.
A extends Propsthe payload object type.

UniversalPattern ​

ts
type UniversalPattern = PatternMatcher<unknown> & object;

Defined in: packages/core/src/matcher.ts:64

The statically-known universal pattern — the type of P._ only. The phantom UNIVERSAL marker is required, so no other PatternMatcher<unknown> (e.g. a P.when guard that happens to be universal) is assignable: the catch-all .with overload must only fire for a pattern the type system KNOWS covers everything.

Type Declaration ​

NameTypeDefined in
[UNIVERSAL]truepackages/core/src/matcher.ts:65

Methods ​

AsyncResultMethods ​

ts
type AsyncResultMethods<T, E> = object;

Defined in: packages/core/src/types.ts:810

The async method surface every AsyncResult carries — the combinators (map, flatMap, mapErrCases, match, get, …) with their asynchronous signatures, documented one per entry below. The async mirror of ResultMethods: each entry links its synchronous counterpart and states only the async delta.

Remarks ​

Like ResultMethods, this type exists to document the surface — not to be authored against; you obtain it by holding an AsyncResult. Its combinator callbacks are synchronous (a raw Promise may never enter — see the AsyncResult remarks); async work re-enters via fromPromise and composes with flatMap. Systematic differences from the sync surface: the binds return an AsyncResult (and additionally accept one), and the eliminators return a Promise.

Extended by ​

Type Parameters ​

Type ParameterDescription
Tthe success value type.
Ethe modeled error type.

Methods ​

as() ​
ts
as<U>(value): AsyncResult<U, E>;

Defined in: packages/core/src/types.ts:879

Asynchronous as: replaces the value with value.

Type Parameters ​
Type Parameter
U
Parameters ​
ParameterType
valueU
Returns ​

AsyncResult<U, E>

bind() ​
ts
bind<K, U, E2>(name, f): AsyncResult<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E | E2>;

Defined in: packages/core/src/types.ts:863

Asynchronous bind (do-notation). f may return a Result or an AsyncResult; its value is bound under name in the accumulating scope.

Type Parameters ​
Type Parameter
K extends string
U
E2
Parameters ​
ParameterType
nameK
f(scope) => | Result<U, E2> | Awaitable<Result<U, E2>> & ReturnAnAsyncResultNotAPromise
Returns ​

AsyncResult<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E | E2>

discard() ​
ts
discard(): AsyncResult<void, E>;

Defined in: packages/core/src/types.ts:881

Asynchronous discard: drops the value, collapsing the success type to void.

Returns ​

AsyncResult<void, E>

ensure() ​
Call Signature ​
ts
ensure<U, E2>(predicate, onFail): AsyncResult<U, E | E2>;

Defined in: packages/core/src/types.ts:889

Asynchronous ensure: validate the success value — and, with a type-guard predicate (this overload), refine it — failing into the modeled channel with Err(onFail(value)). Both callbacks are synchronous (an async onFail is rejected at compile time, NotThenable); a throw in either becomes a Defect.

Type Parameters ​
Type Parameter
U
E2
Parameters ​
ParameterType
predicate(value) => value is U
onFail(value) => E2 & NotThenable<E2>
Returns ​

AsyncResult<U, E | E2>

Call Signature ​
ts
ensure<E2>(predicate, onFail): AsyncResult<T, E | E2>;

Defined in: packages/core/src/types.ts:894

Boolean form of the asynchronous ensure — validates without refining, keeping T.

Type Parameters ​
Type Parameter
E2
Parameters ​
ParameterType
predicate(value) => boolean
onFail(value) => E2 & NotThenable<E2>
Returns ​

AsyncResult<T, E | E2>

flatMap() ​
ts
flatMap<U, E2>(f): AsyncResult<U, E | E2>;

Defined in: packages/core/src/types.ts:830

Asynchronous flatMap. Unlike the sync form, f may return a Result or an AsyncResult (never a raw Promise); a throw becomes a Defect.

Type Parameters ​
Type Parameter
U
E2
Parameters ​
ParameterType
f(value) => | Result<U, E2> | Awaitable<Result<U, E2>> & ReturnAnAsyncResultNotAPromise
Returns ​

AsyncResult<U, E | E2>

Remarks ​

The async branch of f's return type is spelled Awaitable<Result<U, E2>> & { flatMap: unknown } rather than AsyncResult<U, E2>: this is what you get by returning an AsyncResult (it satisfies both), but inference runs through the Awaitable then-channel so U/E2 stay precise instead of collapsing to unknown, while the { flatMap: unknown } marker still rejects a bare Promise (it has no flatMap). Just return a Result or an AsyncResult.

flatMapErrCases() ​
ts
flatMapErrCases<M>(f): AsyncResult<
  | T
  | OkOf<MatchOut<M>>
  | AsyncOkOf<MatchOut<M>>, 
  | ErrOf<MatchOut<M>>
  | AsyncErrOf<MatchOut<M>>>;

Defined in: packages/core/src/types.ts:915

Asynchronous flatMapErrCases — the same exhaustive ErrMatcher form. Unlike the sync form, a branch may return a Result or an AsyncResult.

Type Parameters ​
Type Parameter
M extends ExhaustiveMatch< | Result<unknown, unknown> | Defect | Awaitable<Result<unknown, unknown>> & ReturnAnAsyncResultNotAPromise>
Parameters ​
ParameterType
f(matcher, defect) => M
Returns ​

AsyncResult< | T | OkOf<MatchOut<M>> | AsyncOkOf<MatchOut<M>>, | ErrOf<MatchOut<M>> | AsyncErrOf<MatchOut<M>>>

flatTap() ​
ts
flatTap<E2>(f): AsyncResult<T, E | E2>;

Defined in: packages/core/src/types.ts:851

Asynchronous flatTap — a failable tap that keeps the original value. f may return a Result or an AsyncResult; its Ok value is discarded, an Err/Defect short-circuits, and a throw becomes a Defect.

Type Parameters ​
Type Parameter
E2
Parameters ​
ParameterType
f(value) => | Result<unknown, E2> | Awaitable<Result<unknown, E2>> & ReturnAnAsyncResultNotAPromise
Returns ​

AsyncResult<T, E | E2>

flatTapErrCases() ​
ts
flatTapErrCases<E2>(f): AsyncResult<T, E | E2>;

Defined in: packages/core/src/types.ts:968

Asynchronous flatTapErrCases — the error-channel mirror of flatTap. f may return a Result or an AsyncResult; its Ok value is discarded, an Err/Defect from f threads through, and if f throws — or a branch returns the injected defect(cause) marker, the expression-position form of a throw — the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it.

Type Parameters ​
Type Parameter
E2
Parameters ​
ParameterType
f(matcher, defect) => ExhaustiveMatch< | Result<unknown, E2> | Awaitable<Result<unknown, E2>> & ReturnAnAsyncResultNotAPromise>
Returns ​

AsyncResult<T, E | E2>

get() ​
ts
get(this): Promise<T>;

Defined in: packages/core/src/types.ts:1017

Asynchronous get. Compiles only when the error channel is empty (this: AsyncResult<T, never>); the returned promise rejects on a Defect (rethrowing its cause).

Parameters ​
ParameterType
this[E] extends [never] ? AsyncResult<T, never> : "unthrown: get() needs an empty error channel (E = never) — handle the Err first with recoverErrCases / match / flatMapErrCases, or use getOr / getOrElse / getOrNull / getOrUndefined"
Returns ​

Promise<T>

getErr() ​
ts
getErr(this): Promise<E>;

Defined in: packages/core/src/types.ts:1027

Asynchronous getErr. Compiles only when the success channel is empty (this: AsyncResult<never, E>); the returned promise rejects on a Defect (rethrowing its cause).

Parameters ​
ParameterType
this[T] extends [never] ? AsyncResult<never, E> : "unthrown: getErr() needs an empty success channel (T = never) — narrow with isErr() first, or fold with match"
Returns ​

Promise<E>

getOr() ​
ts
getOr<U>(fallback): Promise<T | U>;

Defined in: packages/core/src/types.ts:1033

Asynchronous getOr.

Type Parameters ​
Type Parameter
U
Parameters ​
ParameterType
fallbackU
Returns ​

Promise<T | U>

getOrElse() ​
ts
getOrElse<U>(f): Promise<T | U>;

Defined in: packages/core/src/types.ts:1035

Asynchronous getOrElse.

Type Parameters ​
Type Parameter
U
Parameters ​
ParameterType
f(error) => U
Returns ​

Promise<T | U>

getOrNull() ​
ts
getOrNull(): Promise<T | null>;

Defined in: packages/core/src/types.ts:1037

Asynchronous getOrNull.

Returns ​

Promise<T | null>

getOrThrow() ​
ts
getOrThrow(this): Promise<T>;

Defined in: packages/core/src/types.ts:1046

Asynchronous getOrThrow — the returned promise rejects with the modeled error on Err (or the original cause on a Defect), rather than throwing synchronously. Gated the same way: it compiles only when the error channel is non-empty (E is not never).

Parameters ​
ParameterType
this[E] extends [never] ? "unthrown: getOrThrow is unnecessary here — the Err channel is empty (E = never), so there is nothing to throw. Use get() instead." : AsyncResult<T, E>
Returns ​

Promise<T>

getOrUndefined() ​
ts
getOrUndefined(): Promise<T | undefined>;

Defined in: packages/core/src/types.ts:1039

Asynchronous getOrUndefined.

Returns ​

Promise<T | undefined>

let() ​
ts
let<K, U>(name, f): AsyncResult<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E>;

Defined in: packages/core/src/types.ts:874

Asynchronous let (do-notation). f returns a plain value, bound under name. An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type Parameter
K extends string
U
Parameters ​
ParameterType
nameK
f(scope) => U & NotThenable<U>
Returns ​

AsyncResult<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E>

map() ​
ts
map<U>(f): AsyncResult<U, E>;

Defined in: packages/core/src/types.ts:816

Asynchronous map: transforms the success value with f. f is synchronous; a throw becomes a Defect. An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type Parameter
U
Parameters ​
ParameterType
f(value) => U & NotThenable<U>
Returns ​

AsyncResult<U, E>

mapErrCases() ​
ts
mapErrCases<M>(f, ..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCases): AsyncResult<T, Exclude<MatchOut<M>, Defect>>;

Defined in: packages/core/src/types.ts:904

Asynchronous mapErrCases — the same exhaustive ErrMatcher form; the combinator calls .exhaustive(). Branches are synchronous — an async branch is a compile error, as on the sync surface.

Type Parameters ​
Type Parameter
M extends ExhaustiveMatch<unknown>
Parameters ​
ParameterType
f(matcher, defect) => M
..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCasesSyncBranches<MatchOut<M>, E>
Returns ​

AsyncResult<T, Exclude<MatchOut<M>, Defect>>

match() ​
ts
match<ROk, RDefect, M>(cases): Promise<ROk | RDefect | MatchOut<M>>;

Defined in: packages/core/src/types.ts:1007

Asynchronous match. Handlers are synchronous (the errCases handler returns an exhaustive ErrMatcher builder, no defect helper); resolves to a Promise of the folded value.

Type Parameters ​
Type Parameter
ROk
RDefect
M extends ExhaustiveMatch<unknown>
Parameters ​
ParameterType
cases{ defect: (cause) => RDefect; errCases: (matcher) => M; ok: (value) => ROk; }
cases.defect(cause) => RDefect
cases.errCases(matcher) => M
cases.ok(value) => ROk
Returns ​

Promise<ROk | RDefect | MatchOut<M>>

recoverDefect() ​
ts
recoverDefect<U, E2>(f): AsyncResult<T | U, E | E2>;

Defined in: packages/core/src/types.ts:981

Asynchronous recoverDefect. f may return a Result or an AsyncResult.

Type Parameters ​
Type Parameter
U
E2
Parameters ​
ParameterType
f(cause) => | Result<U, E2> | AsyncResult<U, E2>
Returns ​

AsyncResult<T | U, E | E2>

recoverErrCases() ​
ts
recoverErrCases<M>(f, ..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCases): AsyncResult<T | Exclude<MatchOut<M>, Defect>, never>;

Defined in: packages/core/src/types.ts:933

Asynchronous recoverErrCases — the same exhaustive ErrMatcher form. Branches are synchronous; a throw becomes a Defect.

Type Parameters ​
Type Parameter
M extends ExhaustiveMatch<unknown>
Parameters ​
ParameterType
f(matcher, defect) => M
..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCasesSyncBranches<MatchOut<M>, T | E>
Returns ​

AsyncResult<T | Exclude<MatchOut<M>, Defect>, never>

tap() ​
ts
tap<R>(f): AsyncResult<T, E>;

Defined in: packages/core/src/types.ts:844

Asynchronous tap. f is synchronous; a throw becomes a Defect. An async callback is rejected at compile time (NotThenable) — and so is a returned AsyncResult (it is awaitable). Beware the near-miss: calling an AsyncResult-returning effect inside the callback without returning it compiles and leaves the effect floating — fire-and-forget, never awaited, its Err/Defect unobserved. If the effect returns a Result/AsyncResult, use flatTap.

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterType
f(value) => R & NotThenable<R>
Returns ​

AsyncResult<T, E>

tapDefect() ​
ts
tapDefect<R>(f): AsyncResult<T, E>;

Defined in: packages/core/src/types.ts:990

Asynchronous tapDefect. If f throws, the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterType
f(cause) => R & NotThenable<R>
Returns ​

AsyncResult<T, E>

tapErrCases() ​
ts
tapErrCases<R>(f): AsyncResult<T, E>;

Defined in: packages/core/src/types.ts:952

Asynchronous tapErrCases. f is synchronous; if it throws — or a branch returns the injected defect(cause) marker, the expression-position form of a throw — the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async branch is rejected at compile time (NotThenable on the builder output) — other branch results are discarded, so a rejected Promise would float unobserved. The tap fire-and-forget caveat applies here too — a failable effect belongs in flatTapErrCases.

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterType
f(matcher, defect) => ExhaustiveMatch<R & NotThenable<R>>
Returns ​

AsyncResult<T, E>

tapFailure() ​
ts
tapFailure<R>(f): AsyncResult<T, E>;

Defined in: packages/core/src/types.ts:1000

Asynchronous tapFailure — the cross-channel observer. f receives the narrowed failure variant (FailureView); if it throws, the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterType
f(failure) => R & NotThenable<R>
Returns ​

AsyncResult<T, E>


ResultMethods ​

ts
type ResultMethods<T, E> = object;

Defined in: packages/core/src/types.ts:181

The fluent method surface every Result variant carries — the combinators (map, flatMap, mapErrCases, match, get, …), documented one per entry below. Factored out so the three variants (OkView, ErrView, DefectView) can each intersect it; AsyncResult mirrors this surface with async signatures.

Remarks ​

This type exists to document the surface and to power narrowing — not to be authored against. You obtain it by holding a Result (or AsyncResult), never by implementing your own Result-like; treat it as read-only reference.

Extended by ​

Type Parameters ​

Type ParameterDescription
Tthe success value type.
Ethe modeled error type.

Methods ​

as() ​
ts
as<U>(value): Result<U, E>;

Defined in: packages/core/src/types.ts:288

Replace the success value with a constant value.

Runs only on Ok; Err and Defect pass through.

Type Parameters ​
Type ParameterDescription
Uthe replacement value type.
Parameters ​
ParameterType
valueU
Returns ​

Result<U, E>

bind() ​
ts
bind<K, U, E2>(name, f): Result<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E | E2>;

Defined in: packages/core/src/types.ts:261

Do-notation: run f for a Result and bind its value under name in an accumulating object scope.

Type Parameters ​
Type ParameterDescription
K extends stringthe key the bound value is stored under.
Uthe bound value type.
E2the error type f may introduce.
Parameters ​
ParameterTypeDescription
nameKthe scope key.
f(scope) => Result<U, E2>produces a Result from the accumulated scope.
Returns ​

Result<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E | E2>

Remarks ​

Begin a chain with Do (an empty object scope) and grow it step by step. f receives the scope accumulated so far and returns a Result; on Ok the value is added as { ...scope, [name]: value }, on Err/Defect the chain short-circuits. Errors union (E | E2). A throw becomes a Defect — as does calling bind on a non-object or non-plain scope (e.g. Ok(5).bind, or a class instance whose getters the merge would drop), which is misuse: the scope is always a plain object inside a real Do() chain. (let is the pure-value counterpart.)

discard() ​
ts
discard(): Result<void, E>;

Defined in: packages/core/src/types.ts:297

Drop the success value, collapsing the success type to void.

The named form of map(() => undefined). Runs only on Ok (the value is replaced with undefined); Err and Defect pass through. Unlike as(undefined) — which produces Result<undefined, E> — the success type is void: the value's story ends here.

Returns ​

Result<void, E>

ensure() ​
Call Signature ​
ts
ensure<U, E2>(predicate, onFail): Result<U, E | E2>;

Defined in: packages/core/src/types.ts:332

Validate the success value — keep the Ok when predicate holds, otherwise fail into the modeled channel with Err(onFail(value)).

Type Parameters ​
Type ParameterDescription
Uthe refined success type (type-guard form).
E2the error type onFail produces.
Parameters ​
ParameterTypeDescription
predicate(value) => value is Uthe check; a type guard refines T to U.
onFail(value) => E2 & NotThenable<E2>maps the failing value to the modeled error.
Returns ​

Result<U, E | E2>

Remarks ​

The named form of flatMap((v) => (p(v) ? Ok(v) : Err(e))). With a type-guard predicate ((v): v is U) the success type is refined to U on the way through (this overload). Runs only on Ok — a passing value flows through as the same Ok; Err and Defect pass through untouched. A throw in predicate or onFail becomes a Defect.

Both callbacks are synchronous: an async onFail is rejected at compile time (NotThenable), and an async predicate does not type-check either — its Promise<boolean> is not a boolean (and, being truthy, would have silently always passed).

Example ​
ts
// boolean form: gate a value
Ok(-1).ensure((n) => n > 0, (n) => `negative: ${n}`); // Err("negative: -1")

// type-guard form: refine the success type
declare const r: Result<string | number, "e">;
const s = r.ensure(
  (v): v is string => typeof v === "string",
  () => "not_a_string" as const,
); // Result<string, "e" | "not_a_string">
Call Signature ​
ts
ensure<E2>(predicate, onFail): Result<T, E | E2>;

Defined in: packages/core/src/types.ts:340

Boolean form of ensure — validates without refining, keeping the success type T.

Type Parameters ​
Type Parameter
E2
Parameters ​
ParameterType
predicate(value) => boolean
onFail(value) => E2 & NotThenable<E2>
Returns ​

Result<T, E | E2>

flatMap() ​
ts
flatMap<U, E2>(f): Result<U, E | E2>;

Defined in: packages/core/src/types.ts:204

Sequence a dependent, Result-returning step (monadic bind).

Runs f only on Ok; Err and Defect pass through. The error channels combine, widening to E | E2. If f throws, the throw becomes a Defect.

Type Parameters ​
Type ParameterDescription
Uthe success type of the next step.
E2the error type the next step may introduce.
Parameters ​
ParameterTypeDescription
f(value) => Result<U, E2>produces the next Result from the current success value.
Returns ​

Result<U, E | E2>

flatMapErrCases() ​
ts
flatMapErrCases<M>(f): Result<T | OkOf<MatchOut<M>>, ErrOf<MatchOut<M>>>;

Defined in: packages/core/src/types.ts:397

Sequence from an Err by producing another Result — the error-channel mirror of flatMap, matching the error exhaustively (ErrMatcher; the combinator calls .exhaustive()).

Each branch returns a Result; the outgoing channels are the unions of the branch-returned Results' channels. A branch may return defect(cause). Runs only on Err; Ok and Defect pass through.

Type Parameters ​
Type ParameterDescription
M extends ExhaustiveMatch<Result<unknown, unknown> | Defect>the exhaustive builder the callback returns.
Parameters ​
ParameterTypeDescription
f(matcher, defect) => Mbuilds the match; each branch produces a fallback Result.
Returns ​

Result<T | OkOf<MatchOut<M>>, ErrOf<MatchOut<M>>>

flatTap() ​
ts
flatTap<E2>(f): Result<T, E | E2>;

Defined in: packages/core/src/types.ts:240

Run a failable side effect on the success value, keeping the original value but threading the effect's error.

Type Parameters ​
Type ParameterDescription
E2the error type the effect may introduce.
Parameters ​
ParameterTypeDescription
f(value) => Result<unknown, E2>the failable side effect; its Ok value is ignored.
Returns ​

Result<T, E | E2>

Remarks ​

This is to tap what flatMap is to map: f returns a Result, but its success value is discarded — on success the original value flows through (Result<T, E | E2>), while an Err (or Defect) from f short-circuits. Runs only on Ok; Err and Defect pass through. If f throws, the throw becomes a Defect. Use it for a validation or write whose result matters but whose value you don't need.

flatTapErrCases() ​
ts
flatTapErrCases<E2>(f): Result<T, E | E2>;

Defined in: packages/core/src/types.ts:478

Run a failable side effect on the error, keeping the original error but threading the effect's own error — matched exhaustively (ErrMatcher).

Type Parameters ​
Type Parameter
E2
Parameters ​
ParameterTypeDescription
f(matcher, defect) => ExhaustiveMatch<Result<unknown, E2>>builds the match; each branch is a failable effect (its Ok is ignored).
Returns ​

Result<T, E | E2>

Remarks ​

The error-channel mirror of flatTap: each branch returns a Result whose success value is discarded — on the effect's Ok the original Err flows through, while an Err/Defect from a branch short-circuits and threads its error. Note the asymmetry with a throw: a branch that returns a Defect-state Result replaces the original Err (Defect-dominance, the short-circuit rule — it is not aggregated), whereas a branch that throws produces a Defect aggregating [thrown, original failure] (observing a failure by throwing never destroys it). A branch returning the injected defect(cause) marker — reachable under a returnType pin — follows the throw rule, since it is the lint-clean, expression-position form of one.

get() ​
ts
get(this): T;

Defined in: packages/core/src/types.ts:583

Extract the success value.

Parameters ​
ParameterType
this[E] extends [never] ? Result<T, never> : "unthrown: get() needs an empty error channel (E = never) — handle the Err first with recoverErrCases / match / flatMapErrCases, or use getOr / getOrElse / getOrNull / getOrUndefined"
Returns ​

T

the Ok value.

Remarks ​

Compiles only when the error channel is empty (E = never) — eliminate modeled errors first (match / recoverErrCases / flatMapErrCases), or reach for the getOr / getOrElse / getOrNull / getOrUndefined family (which recover an Err). The gate is a this type that becomes an explanatory string when E is not never, so the compile error names the fix.

E = never empties only the modeled error channel — a Defect can still be present, and get() rethrows its original cause (it panics); Result<T, never> does not mean get() cannot throw.

getErr() ​
ts
getErr(this): E;

Defined in: packages/core/src/types.ts:601

Extract the modeled error.

Parameters ​
ParameterType
this[T] extends [never] ? Result<never, E> : "unthrown: getErr() needs an empty success channel (T = never) — narrow with isErr() first, or fold with match"
Returns ​

E

the Err value.

Remarks ​

Compiles only when the success channel is empty (T = never) — eliminate the success case first. T = never is rarely the case in practice (a Result you hold usually still has a success type), so to inspect an error prefer an isErr() guard or, in tests, @unthrown/vitest's toBeErrWith. A Defect still rethrows its original cause (a defect is a bug, not an absent value), so this does not mean getErr() can't throw.

getOr() ​
ts
getOr<U>(fallback): T | U;

Defined in: packages/core/src/types.ts:614

The success value, or fallback on Err.

Type Parameters ​
Type ParameterDescription
Uthe fallback type (may differ from T; the return widens to `T
Parameters ​
ParameterTypeDescription
fallbackUreturned when the result is an Err (may be a different type; the return widens to `T
Returns ​

T | U

Throws ​

Re-throws on a Defect — a Defect is a bug, not an absent value, so it is never silently replaced.

getOrElse() ​
ts
getOrElse<U>(f): T | U;

Defined in: packages/core/src/types.ts:622

The success value, or f(error) on Err.

Type Parameters ​
Type ParameterDescription
Uthe fallback type (may differ from T; the return widens to `T
Parameters ​
ParameterTypeDescription
f(error) => Ulazily computes the fallback from the error (may return a different type; the return widens to `T
Returns ​

T | U

Throws ​

Re-throws on a Defect.

getOrNull() ​
ts
getOrNull(): T | null;

Defined in: packages/core/src/types.ts:628

The success value, or null on Err.

Returns ​

T | null

Throws ​

Re-throws on a Defect.

getOrThrow() ​
ts
getOrThrow(this): T;

Defined in: packages/core/src/types.ts:666

The success value, or throw the modeled error on Err.

Parameters ​
ParameterType
this[E] extends [never] ? "unthrown: getOrThrow is unnecessary here — the Err channel is empty (E = never), so there is nothing to throw. Use get() instead." : Result<T, E>
Returns ​

T

the Ok value.

Remarks ​

A deliberate escape hatch off the errors-as-values model — it throws the Err value as-is at the call site, so a caller of the enclosing function sees a throw rather than a channel. Its home is tests and scripts, where "this Result had better be Ok" is the assertion and a throw is the correct failure mode.

In production code, fold the error channel instead: recoverErrCases empties E, so get compiles and a case routed to the injected defect(...) panics with its original cause — with every case still named. match and flatMapErrCases are the other two ways to keep the error a value. @unthrown/oxlint's opt-in no-get-or-throw rule enforces this, exempting test files through an oxlint overrides entry.

Type-gated as the complement of get: it compiles only when the error channel is non-empty (E is not never) — there must be a modeled error for it to throw. On a Result<T, never> there is nothing to throw, so getOrThrow does not compile; use get() (which gates the other way). Together they partition extraction by the error channel's state, with no overlap.

Throws ​

the modeled error on Err; re-throws the original cause on a Defect (a panic, like the rest of the getOr… family).

getOrUndefined() ​
ts
getOrUndefined(): T | undefined;

Defined in: packages/core/src/types.ts:634

The success value, or undefined on Err.

Returns ​

T | undefined

Throws ​

Re-throws on a Defect.

isDefect() ​
ts
isDefect(): this is DefectView<T, E>;

Defined in: packages/core/src/types.ts:677

Whether this result is a Defect — narrows this to its DefectView on true.

Returns ​

this is DefectView<T, E>

isErr() ​
ts
isErr(): this is ErrView<E, T>;

Defined in: packages/core/src/types.ts:675

Whether this result is Err — narrows this to its ErrView on true.

Returns ​

this is ErrView<E, T>

isOk() ​
ts
isOk(): this is OkView<T, E>;

Defined in: packages/core/src/types.ts:673

Whether this result is Ok — narrows this to its OkView on true.

Returns ​

this is OkView<T, E>

let() ​
ts
let<K, U>(name, f): Result<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E>;

Defined in: packages/core/src/types.ts:280

Do-notation: run f for a plain value and bind it under name in the accumulating object scope. The pure-value counterpart of bind.

Type Parameters ​
Type ParameterDescription
K extends stringthe key the value is stored under.
Uthe value type.
Parameters ​
ParameterTypeDescription
nameKthe scope key.
f(scope) => U & NotThenable<U>computes a value from the accumulated scope.
Returns ​

Result<{ [K in string | number | symbol]: (Omit<T, K> & { readonly [P in string]: U })[K] }, E>

Remarks ​

f receives the scope and returns a value (not a Result); it is added as { ...scope, [name]: value }. Runs only on Ok; Err/Defect pass through. A throw becomes a Defect. An async callback is rejected at compile time (NotThenable).

map() ​
ts
map<U>(f): Result<U, E>;

Defined in: packages/core/src/types.ts:193

Transform the success value with f.

Runs f only on Ok; Err and Defect pass through untouched. If f throws, the thrown value is captured as a Defect.

An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type ParameterDescription
Uthe mapped success type.
Parameters ​
ParameterTypeDescription
f(value) => U & NotThenable<U>maps the current success value to a new one.
Returns ​

Result<U, E>

mapErrCases() ​
ts
mapErrCases<M>(f, ..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCases): Result<T, Exclude<MatchOut<M>, Defect>>;

Defined in: packages/core/src/types.ts:379

Transform the modeled error by matching it exhaustively.

Type Parameters ​
Type ParameterDescription
M extends ExhaustiveMatch<unknown>the exhaustive builder the callback returns.
Parameters ​
ParameterTypeDescription
f(matcher, defect) => Mbuilds the match over the error (returns the un-terminated builder).
..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCasesSyncBranches<MatchOut<M>, E>compile-time only; never pass it. Empty for synchronous branches; an async branch demands this impossible argument, so the call fails to compile (its name is the fix).
Returns ​

Result<T, Exclude<MatchOut<M>, Defect>>

Remarks ​

The callback receives match(error) (an ErrMatcher) and the injected defect helper. Chain .with(pattern, handler) and return the un-terminated builder — mapErrCases calls .exhaustive() itself, so a missing case is a compile error at the call site (there is no .exhaustive() to forget, and no way to slip in .otherwise()). The outgoing error type is the union of the branch returns with the Defect arm subtracted (Exclude<O, Defect>) — a branch returning defect(cause) converts that case to a Defect and drops it from E. Runs only on Err; Ok and Defect pass through. A branch that throws also becomes a Defect. Branches are synchronous: an async branch is a compile error (its Promise would land in E un-triaged), and a thenable slipped past the types becomes a Defect.

Name every case. Match on anything the matcher supports — _tag, code, structural shape, guards — and group the cases that share a handler with .with(a, b, handler). .with(P._, …) is the wildcard escape hatch, not the default: it makes any match exhaustive, so it also absorbs every case E grows later. Two uses are sanctioned — a helper generic in E, where no arm list can prove exhaustiveness against an unresolved type parameter, and an E that is a single type rather than a union of cases (see P for both). @unthrown/oxlint's no-catch-all-pattern (in its recommended preset) flags the rest.

match() ​
ts
match<ROk, RDefect, M>(cases): ROk | RDefect | MatchOut<M>;

Defined in: packages/core/src/types.ts:562

Exhaustively fold all three runtime states into a single value.

Type Parameters ​
Type ParameterDescription
ROkthe ok handler return type.
RDefectthe defect handler return type.
M extends ExhaustiveMatch<unknown>the exhaustive builder the errCases handler returns.
Parameters ​
ParameterTypeDescription
cases{ defect: (cause) => RDefect; errCases: (matcher) => M; ok: (value) => ROk; }the ok/defect handlers plus the errCases matcher builder.
cases.defect(cause) => RDefect-
cases.errCases(matcher) => M-
cases.ok(value) => ROk-
Returns ​

ROk | RDefect | MatchOut<M>

Remarks ​

Exactly one handler runs. Together with the throw-to-Defect guarantee, this is typically the single place a pipeline is handled at the edge — mapping Ok/Err/Defect to (for example) 2xx / 4xx / 5xx with no try/catch.

The errCases handler does not take a single blanket callback: it receives match(error) (an ErrMatcher) and matches the error exhaustively, exactly like the error combinators — which is why the key carries the same …Cases suffix. Chain .with(pattern, handler) and return the un-terminated builder — match calls .exhaustive() itself, so a missing case is a compile error at the call site (no .exhaustive() to forget). Folding at the edge names every case too — .with(P._, …) is the wildcard escape hatch, not the default. Unlike the combinators the branches receive no defect helper — match is total elimination to a value, with no Defect output channel; the defect case handles a Result that already carries one. (A Result is also a discriminated union — for richer whole-Result matching, match(result).with(…).)

recoverDefect() ​
ts
recoverDefect<U, E2>(f): Result<T | U, E | E2>;

Defined in: packages/core/src/types.ts:498

Recover from a Defect — the only combinator that can touch one.

Type Parameters ​
Type ParameterDescription
Ua success type the recovery may produce.
E2an error type the recovery may produce.
Parameters ​
ParameterTypeDescription
f(cause) => Result<U, E2>maps the Defect's unknown cause to a recovering Result.
Returns ​

Result<T | U, E | E2>

Remarks ​

Runs f only when a Defect is present, re-entering the modeled world by returning a Result (an Ok or a fresh Err). Ok and Err pass through. Recovering a Defect should be rare: usually you let it bubble to the edge. If f throws, the throw becomes a new Defect.

recoverErrCases() ​
ts
recoverErrCases<M>(f, ..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCases): Result<T | Exclude<MatchOut<M>, Defect>, never>;

Defined in: packages/core/src/types.ts:421

Recover from an Err by producing a success value, emptying the error channel — matching the error exhaustively (ErrMatcher). Pairs with recoverDefect.

Type Parameters ​
Type ParameterDescription
M extends ExhaustiveMatch<unknown>the exhaustive builder the callback returns.
Parameters ​
ParameterTypeDescription
f(matcher, defect) => Mbuilds the match; each branch produces a success value.
..._asyncBranchBanned_liftWithFromPromiseThenFlatMapErrCasesSyncBranches<MatchOut<M>, T | E>compile-time only; never pass it. Empty for synchronous branches; an async branch demands this impossible argument, so the call fails to compile (its name is the fix).
Returns ​

Result<T | Exclude<MatchOut<M>, Defect>, never>

Remarks ​

The result type is Result<T | U, never>, but never describes only the error channel — a Defect can still be present at runtime. A branch may return defect(cause) (which stays a Defect, not a recovery). Runs only on Err; Ok and Defect pass through. Branches are synchronous: an async branch is a compile error, and a thenable slipped past the types becomes a Defect.

tap() ​
ts
tap<R>(f): Result<T, E>;

Defined in: packages/core/src/types.ts:223

Run a side effect on the success value and pass the Result through unchanged.

Runs only on Ok. If f throws, the throw becomes a Defect. An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterTypeDescription
f(value) => R & NotThenable<R>the side effect (its return value is ignored).
Returns ​

Result<T, E>

Remarks ​

f's return value is ignored — a Result returned by the effect compiles but is discarded, Err and all. If the effect can fail, sequence it instead of tapping it: a Result-returning effect goes in flatTap; an AsyncResult-returning effect cannot be sequenced from the sync surface — lift the chain with toAsync and use the async flatTap (which accepts both).

tapDefect() ​
ts
tapDefect<R>(f): Result<T, E>;

Defined in: packages/core/src/types.ts:508

Run a side effect on a present Defect's cause (e.g. logging) and pass the Defect through unchanged. If f throws, the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async callback is rejected at compile time (NotThenable).

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterTypeDescription
f(cause) => R & NotThenable<R>the side effect over the unknown cause.
Returns ​

Result<T, E>

tapErrCases() ​
ts
tapErrCases<R>(f): Result<T, E>;

Defined in: packages/core/src/types.ts:450

Run a side effect on the error — matched exhaustively (ErrMatcher) — and pass the Result through unchanged.

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterTypeDescription
f(matcher, defect) => ExhaustiveMatch<R & NotThenable<R>>builds the match; branch returns are ignored, bar defect(cause).
Returns ​

Result<T, E>

Remarks ​

The callback builds a match whose branches run side effects; their return values are ignored and the original Err flows through. Exhaustive like the transformers, and like them it wants every case named — .with(P._, …) remains the wildcard escape hatch. If a branch throws, the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async branch is rejected at compile time (NotThenable on the builder output): because the branch results are discarded, a returned Promise would float unobserved and its rejection would vanish. The one branch return that is not discarded is the injected defect(cause) marker: it is the lint-clean, expression-position form of a throw, so it follows the throw rule above (an AggregateError of [the branch's cause, original failure]), never a silent no-op. A failable Result-returning effect belongs in flatTapErrCases.

tapFailure() ​
ts
tapFailure<R>(f): Result<T, E>;

Defined in: packages/core/src/types.ts:534

Run a side effect on any failure — Err or Defect — and pass the Result through unchanged. The one cross-channel observer, for the shared "it went KO" concern (logging, metrics, rollback) that would otherwise be duplicated across tapErrCases and tapDefect.

Type Parameters ​
Type Parameter
R
Parameters ​
ParameterTypeDescription
f(failure) => R & NotThenable<R>the side effect over the failure variant (its return value is ignored).
Returns ​

Result<T, E>

Remarks ​

f receives the narrowed failure variant (FailureView), not a payload — the payload union E | unknown would collapse to unknown and lose E's typing. Branch on failure.tag to reach the typed payload ("Err" → failure.error: E, "Defect" → failure.cause: unknown), or treat it opaquely for a shared logger. Runs on Err and Defect; Ok passes through. It observes without consuming: the failure flows on unchanged — to also recover, use recoverErrCases / recoverDefect (deliberately separate acts) or match at the edge. If f throws, the result is a Defect whose cause is an AggregateError of [thrown, original failure] — observing a failure never destroys it. An async callback is rejected at compile time (NotThenable).

toAsync() ​
ts
toAsync(): AsyncResult<T, E>;

Defined in: packages/core/src/types.ts:680

Lift this synchronous Result into an AsyncResult.

Returns ​

AsyncResult<T, E>

Constructors ​

P ​

ts
const P: Readonly<{
  _: UniversalPattern;
  instanceOf: <C>(cls) => PatternMatcher<InstanceType<C>>;
  tag: <Tag>(value) => object;
  when: <G>(guard) => PatternMatcher<G>;
}>;

Defined in: packages/core/src/matcher.ts:542

The pattern namespace (unthrown's own; the former ts-pattern P):

  • P._ — the universal catch-all, and an escape hatch rather than the default: matching the error channel means naming its cases, so reach for this only where they cannot be named. Matches anything, and (because its phantom type is unknown) makes the builder provably exhaustive even when the matched input is an unresolved type parameter. Two situations are legitimate: a helper generic in E, where no arm list can prove exhaustiveness against an unresolved type parameter; and an E that is a single type, not a union of cases (a validator's issues array, say), where one arm is the enumeration. @unthrown/oxlint's no-catch-all-pattern (in its recommended preset) flags every other use; keep the deliberate ones behind a targeted oxlint-disable saying which of the two it is.
  • P.tag<const Tag extends string>(value: Tag): { _tag: Tag } — the { _tag: t } object pattern, matching any value whose _tag equals t (a TaggedError, or any _tag-discriminated member) and narrowing the branch's parameter to that variant, payload included. The workhorse of the error channel: matcher.with(P.tag("NotFound"), (e) => …). It composes like any other pattern — in a grouped arm (.with(P.tag("A"), P.tag("B"), handler)).
  • P.instanceOf(Cls) — an instanceof check, narrowing to the class instance type (for union members that are not tagged, e.g. a third-party error class). Exhaustiveness here is structural, the check is not: two classes with the same shape (class A extends Error {}, class B extends Error {}) are one type to the compiler, so a match naming only A compiles as exhaustive while a B fails instanceof A at runtime and becomes a Defect. Give each class a distinguishing field (a readonly kind = "A" literal) or use TaggedError, and the missing arm is a compile error again.
  • P.when(guard) — an arbitrary type-guard predicate. Also the way to match a primitive shape (P.when((v): v is string => typeof v === "string")), and grouping patterns under one handler is what a .with(a, b, handler) arm already does.

Example ​

ts
import { P, TaggedError, type Result } from "unthrown";

class NotFound extends TaggedError("NotFound")<{ id: string }> {}
class Conflict extends TaggedError("Conflict") {}
class VendorTimeout extends Error {
  readonly afterMs = 30_000;
}

declare const r: Result<string, NotFound | Conflict | VendorTimeout | "rate_limited">;
const status = r.match({
  ok: () => 200,
  errCases: (matcher) =>
    matcher
      .with(P.tag("NotFound"), () => 404) // a TaggedError, narrowed with its payload
      .with(P.tag("Conflict"), () => 409)
      .with(P.instanceOf(VendorTimeout), (e) => (e.afterMs > 10_000 ? 504 : 503))
      .with(
        P.when((v): v is "rate_limited" => v === "rate_limited"),
        () => 429,
      ),
  defect: () => 500,
});

Err() ​

ts
function Err<E>(error): Result<never, E>;

Defined in: packages/core/src/constructors.ts:61

Construct a failed Result carrying a modeled error.

Type Parameters ​

Type ParameterDescription
Ethe modeled error type.

Parameters ​

ParameterTypeDescription
errorEthe domain error to wrap.

Returns ​

Result<never, E>

Example ​

ts
import { Err } from "unthrown";

Err("not_found").map((n) => n + 1); // => Err("not_found") (map skipped)
Err("not_found").getErr(); // => "not_found"

ErrAsync() ​

ts
function ErrAsync<E>(error): AsyncResult<never, E>;

Defined in: packages/core/src/constructors.ts:133

Construct a failed AsyncResult carrying a modeled error — the pre-lifted form of Err, sparing you Err(error).toAsync().

Type Parameters ​

Type ParameterDescription
Ethe modeled error type.

Parameters ​

ParameterTypeDescription
errorEthe domain error to wrap.

Returns ​

AsyncResult<never, E>

Remarks ​

The error-channel mirror of OkAsync; see it for the naming and the AsyncResult.Err companion alias.

Example ​

ts
import { ErrAsync } from "unthrown";

ErrAsync("not_found"); // AsyncResult<never, string>

match() ​

ts
function match<E>(value): Matcher<E, E, never>;

Defined in: packages/core/src/matcher.ts:464

Begin a match over value. Chain .with(pattern, …patterns, handler) arms; terminate with .exhaustive() — or return the un-terminated builder to an unthrown error combinator / match({ errCases }), which runs it for you.

Type Parameters ​

Type Parameter
E

Parameters ​

ParameterType
valueE

Returns ​

Matcher<E, E, never>

Remarks ​

This is unthrown's own matcher (the former ts-pattern re-export): the same call-site shape, with exhaustiveness computed by plain Exclude over the builder's Remaining parameter. Name every case of the input union; the P._ catch-all is the escape hatch, and is provably exhaustive even over an unresolved generic input — one of the two cases it is irreplaceable for (see P).

Example ​

ts
import { match, type Result } from "unthrown";

// Matching a whole Result natively — every variant named, `.exhaustive()` last:
declare const r: Result<number, "odd" | "negative">;
const label = match(r)
  .with({ tag: "Ok" }, (ok) => `got ${ok.value}`)
  .with({ tag: "Err" }, (err) => `failed: ${err.error}`)
  .with({ tag: "Defect" }, () => "bug")
  .exhaustive();

// Inside a combinator, return the un-terminated builder — it runs `.exhaustive()`:
const reason = r.mapErrCases((matcher) =>
  matcher.with("odd", () => "not even" as const).with("negative", () => "below zero" as const),
); // Result<number, "not even" | "below zero">

Ok() ​

Call Signature ​

ts
function Ok(): Result<void, never>;

Defined in: packages/core/src/constructors.ts:20

Construct a successful void Result — Result<void, never> — sparing you Ok(undefined) and typing the success channel void, not undefined.

Returns ​

Result<void, never>

Example ​
ts
import { Ok } from "unthrown";

Ok(); // => a void success: Result<void, never>

Call Signature ​

ts
function Ok<T>(value): Result<T, never>;

Defined in: packages/core/src/constructors.ts:37

Construct a successful Result.

Type Parameters ​
Type ParameterDescription
Tthe success value type.
Parameters ​
ParameterTypeDescription
valueTthe success value to wrap.
Returns ​

Result<T, never>

Example ​
ts
import { Ok } from "unthrown";

Ok(2).map((n) => n + 1); // => Ok(3)
Ok(42).get(); // => 42

OkAsync() ​

Call Signature ​

ts
function OkAsync(): AsyncResult<void, never>;

Defined in: packages/core/src/constructors.ts:79

Construct a successful void AsyncResult — AsyncResult<void, never> — the pre-lifted form of the no-arg Ok, sparing you Ok(undefined).toAsync().

Returns ​

AsyncResult<void, never>

Example ​
ts
import { OkAsync } from "unthrown";

OkAsync(); // => a void success: AsyncResult<void, never>

Call Signature ​

ts
function OkAsync<T>(value): AsyncResult<T, never>;

Defined in: packages/core/src/constructors.ts:106

Construct a successful AsyncResult from a pure value — the pre-lifted form of Ok, sparing you Ok(value).toAsync().

Type Parameters ​
Type ParameterDescription
Tthe success value type.
Parameters ​
ParameterTypeDescription
valueTthe success value to wrap.
Returns ​

AsyncResult<T, never>

Remarks ​

Reach for this on the synchronous/early branch of an AsyncResult-returning function, so both branches share one return type without a trailing .toAsync(). Named with the Async suffix the async free functions carry (allAsync, allFromDictAsync); the AsyncResult companion aliases it as AsyncResult.Ok (the namespace already says "async", so the suffix drops).

Example ​
ts
import { OkAsync, type AsyncResult } from "unthrown";

function loadItems(ids: string[]): AsyncResult<Item[], never> {
  if (ids.length === 0) return OkAsync([]); // no more Ok([]).toAsync()
  return itemRepository.load(ids);
}

Interop ​

fromExecutor() ​

ts
function fromExecutor<T, E>(executor): AsyncResult<T, E>;

Defined in: packages/core/src/interop.ts:351

Build an AsyncResult from a callback-style API — this library's answer to new Promise((resolve, reject) => …).

Type Parameters ​

Type ParameterDefault typeDescription
Tneverthe success type.
Eneverthe modeled error type.

Parameters ​

ParameterTypeDescription
executor(settle, defect) => voidruns immediately; receives the settler and the defect helper.

Returns ​

AsyncResult<T, E>

Remarks ​

The settler takes a Result, not a value-or-reason pair: the caller names the variant, so no unknown can enter E and there is no qualify to pass. For a failure that is not modeled, settle the injected defect helper's marker — the same injection qualify receives, and the only way to reach the defect channel from inside an asynchronous callback (a throw there runs in its own turn, long after the executor body returned).

T and E cannot be inferred from the body, since settle is a parameter. Supply them explicitly, or let them flow from an annotated target. Absent either, both default to never (Thesis #3: no path may produce unknown in E) — so an unannotated call is a compile error at the settle(...) call site, not a silently-unknown channel.

An executor that never settles yields an AsyncResult that never resolves — the one hazard fromPromise does not have, and identical to new Promise.

Example ​

ts
import { fromExecutor, Err, Ok } from "unthrown";

const listen = (port: number) =>
  fromExecutor<Server, PortInUse>((settle, defect) => {
    server.once("error", (cause) =>
      isAddrInUse(cause) ? settle(Err(new PortInUse(port))) : settle(defect(cause)),
    );
    server.listen(port, () => settle(Ok(server)));
  });

fromNullable() ​

ts
function fromNullable<T, E>(value, onAbsent): Result<NonNullable<T>, E>;

Defined in: packages/core/src/interop.ts:51

Bridge a nullable value into a Result: absence becomes a modeledErr. The sanctioned alternative to an Option type.

Type Parameters ​

Type ParameterDescription
Tthe (nullable) value type.
Ethe error produced when the value is absent.

Parameters ​

ParameterTypeDescription
valueT | null | undefinedthe possibly-absent value.
onAbsent() => Elazily produces the error for the absent case.

Returns ​

Result<NonNullable<T>, E>

Remarks ​

null and undefined map to Err(onAbsent()); any other value (including falsy ones like 0, "", false) maps to Ok.

Example ​

ts
import { fromNullable } from "unthrown";

const map = new Map([["a", 1]]);
fromNullable(map.get("a"), () => "absent").getOr(0); // => 1
fromNullable(map.get("z"), () => "absent"); // => Err("absent")
fromNullable(0, () => "absent").getOr(-1); // => 0 (falsy but present)

fromPromise() ​

ts
function fromPromise<T, R>(
   promise, 
   qualify, 
   ..._guard
): AsyncResult<T, Exclude<R, Defect>>;

Defined in: packages/core/src/interop.ts:227

Wrap a Promise (or a thunk producing one) as an AsyncResult, forcing every rejection to be triaged.

Type Parameters ​

Type ParameterDescription
Tthe resolved value type.
Rqualify's return type; the modeled error E is Exclude<R, Defect> (its Defect arm, if any, is subtracted).

Parameters ​

ParameterTypeDescription
promisePromise<T> | (() => Promise<T>)the promise, or a thunk returning one.
qualify(cause, defect) => Rtriages a rejection cause into a modeled E, or marks it unmodeled by returning defect(cause) (the helper passed as its second arg).
..._guard[Extract<R, PromiseLike<unknown>>] extends [never] ? [] : ["unthrown: qualify must be synchronous — its Promise would land in E un-triaged"]compile-time only; never pass it. The phantom rest-tuple that enforces "qualify is synchronous": an async qualify makes this demand an impossible extra argument (whose type spells out the error), while a synchronous one leaves it empty. Encoded here — not on qualify's return type — so T's inference from promise is undisturbed.

Returns ​

AsyncResult<T, Exclude<R, Defect>>

Remarks ​

qualify must map each rejection cause into a modeled error E or a Defect (via the injected defect helper, its second argument). The returned AsyncResult's internal promise never rejects; await-ing it always yields a Result. A throw inside qualify is itself a Defect. qualify is synchronous: an async qualify is rejected at compile time (NotThenable), and a thenable slipped past the types at runtime becomes a Defect (never an Err(Promise)), its orphaned rejection silenced.

The modeled error type is Exclude<R, Defect> — the Defect arm of qualify's return is subtracted from E, never inferred into it. So a qualify that returns only defect(cause) yields E = never; when every rejection is a Defect, prefer fromSafePromise.

Example ​

ts
import { fromPromise } from "unthrown";

// A rejection with a NotFoundError becomes a modeled `Err`; anything else a Defect.
const user = await fromPromise(fetchUser(id), (cause, defect) =>
  cause instanceof NotFoundError ? ("not_found" as const) : defect(cause),
);

if (user.isOk()) user.value; // => the fetched user
// when fetchUser rejects with NotFoundError: user is Err("not_found")

fromSafePromise() ​

ts
function fromSafePromise<T>(promise): AsyncResult<T, never>;

Defined in: packages/core/src/interop.ts:284

Wrap a Promise asserted not to fail in any modeled way: any rejection becomes a Defect.

Type Parameters ​

Type ParameterDescription
Tthe resolved value type.

Parameters ​

ParameterTypeDescription
promisePromise<T> | (() => Promise<T>)the promise, or a thunk returning one.

Returns ​

AsyncResult<T, never>

Remarks ​

Use this only when a rejection genuinely indicates a bug rather than an anticipated outcome — the error channel is never, so there is nothing to triage. (await-ing still yields a Result; it never throws.) The synchronous counterpart is fromSafeThrowable.

Example ​

ts
import { fromSafePromise } from "unthrown";

(await fromSafePromise(Promise.resolve(3))).get(); // => 3
// a rejection becomes a Defect (never a modeled Err):
await fromSafePromise(Promise.reject(new Error("boom"))); // => Defect(Error("boom"))

fromSafeThrowable() ​

ts
function fromSafeThrowable<A, T>(fn): (...args) => Result<T, never>;

Defined in: packages/core/src/interop.ts:167

Wrap a throwing synchronous function asserted not to fail in any modeled way: any throw becomes a Defect.

Type Parameters ​

Type ParameterDescription
A extends unknown[]the wrapped function's argument tuple.
Tthe wrapped function's return type.

Parameters ​

ParameterTypeDescription
fn(...args) => Tthe throwing function to wrap.

Returns ​

a function with the same arguments returning Result<T, never>.

(...args) => Result<T, never>

Remarks ​

The synchronous counterpart of fromSafePromise. Use it only when a throw genuinely indicates a bug rather than an anticipated outcome — the error channel is never, so there is nothing to triage; there is no qualify. When some throws are anticipated, reach for fromThrowable and triage them.

fn is synchronous: an async fn becomes a Defect (never Ok(<Promise>)), with its orphaned rejection silenced rather than left to float. Reach for fromSafePromise to wrap async work.

Example ​

ts
import { fromSafeThrowable } from "unthrown";

// A decode failure here is a bug (the row came from our own schema), so
// every throw is a defect — no throwaway `(cause, defect) => defect(cause)`.
const decode = fromSafeThrowable((row: Row) => userSchema.parse(row));

decode(row); // => Result<User, never> — a throw becomes a Defect

fromThrowable() ​

ts
function fromThrowable<A, T, R>(fn, qualify): (...args) => Result<T, Exclude<R, Defect>>;

Defined in: packages/core/src/interop.ts:108

Wrap a throwing synchronous function so it returns a Result instead of throwing.

Type Parameters ​

Type ParameterDescription
A extends unknown[]the wrapped function's argument tuple.
Tthe wrapped function's return type.
Rqualify's return type; the modeled error E is Exclude<R, Defect> (its Defect arm, if any, is subtracted).

Parameters ​

ParameterTypeDescription
fn(...args) => Tthe throwing function to wrap.
qualify(cause, defect) => R & NotThenable<R>triages a thrown cause into a modeled E, or marks it unmodeled by returning defect(cause) (the helper passed as its second arg).

Returns ​

a function with the same arguments returning Result<T, E>.

(...args) => Result<T, Exclude<R, Defect>>

Remarks ​

qualify must triage every thrown cause into a modeled error E or a Defect (via the injected defect helper, its second argument) — there is no path that leaves unknown in E. A throw inside qualify itself is treated as a Defect. qualify is synchronous: an async qualify is rejected at compile time (NotThenable) — its Promise would land in E un-triaged — and a thenable slipped past the types at runtime becomes a Defect (never an Err(Promise)), its orphaned rejection silenced.

fn is synchronous too. An async fn rejects after this boundary has already returned, so its rejection could never reach qualify: it becomes a Defect (never Ok(<Promise>)) and the orphaned rejection is silenced rather than left to float. Reach for fromPromise to wrap async work.

The modeled error type is Exclude<R, Defect> — the Defect arm of qualify's return is subtracted from E, never inferred into it. So a qualify that returns only defect(cause) yields E = never (a Defect is out-of-band and must not pollute the error channel); reach for fromSafeThrowable when every throw is a Defect.

Example ​

ts
import { fromThrowable } from "unthrown";

// Model the parse failure as an `Err`, everything unexpected as a `Defect`.
const parse = fromThrowable(
  (text: string) => JSON.parse(text) as unknown,
  (cause, defect) =>
    cause instanceof SyntaxError ? ("invalid_json" as const) : defect(cause),
);

parse('{"ok":true}').getOr(null); // => { ok: true }
parse("nope"); // => Err("invalid_json")

Do-notation ​

Do() ​

ts
function Do(): Result<{
}, never>;

Defined in: packages/core/src/do.ts:48

Start a do-notation chain with an empty object scope, grown step by step with bind (for Result-returning steps) and let (for pure values).

Returns ​

Result<{ }, never>

Remarks ​

Capitalised because do is a reserved word. Each step receives the scope accumulated so far; the error types union across binds, and a throw in any step becomes a Defect. To go asynchronous, lift the chain with toAsync() (then a bind may return an AsyncResult).

Examples ​

ts
import { Do, Ok } from "unthrown";

const result = Do()
  .bind("user", () => findUser(id)) // Result<User, NotFound>
  .bind("org", ({ user }) => findOrg(user.orgId)) // Result<Org, NotFound>
  .let("label", ({ user, org }) => `${user.name} @ ${org.name}`)
  .map(({ user, org, label }) => render(user, org, label));
// Result<View, NotFound>
ts
import { Do, Ok, Err } from "unthrown";

// Ok path — the scope accumulates:
Do()
  .bind("a", () => Ok(2))
  .let("b", ({ a }) => a * 10)
  .map(({ a, b }) => a + b); // => Ok(22)

// Err path — the first Err short-circuits the rest:
Do()
  .bind("a", () => Err("boom"))
  .let("b", ({ a }) => a); // => Err("boom")

DoAsync() ​

ts
function DoAsync(): AsyncResult<{
}, never>;

Defined in: packages/core/src/do.ts:76

Start an asynchronous do-notation chain with an empty object scope — the pre-lifted form of Do, sparing you Do().toAsync().

Returns ​

AsyncResult<{ }, never>

Remarks ​

From here a bind may return a Result or an AsyncResult; the scope accumulates exactly as in a sync Do chain, and a throw in any step becomes a Defect. Named with the Async suffix the async free functions carry (OkAsync, allAsync); the AsyncResult companion aliases it as AsyncResult.Do (the namespace already says "async", so the suffix drops).

Example ​

ts
import { DoAsync, Ok } from "unthrown";

const result = await DoAsync()
  .bind("user", () => findUser(id)) // AsyncResult<User, NotFound>
  .bind("plan", ({ user }) => Ok(user.plan)) // a sync Result is accepted too
  .let("label", ({ user, plan }) => `${user.name} on ${plan}`);
// Result<{ user: User; plan: Plan; label: string }, NotFound>

Guards ​

isDefect() ​

ts
function isDefect<T, E>(r): r is DefectView<T, E>;

Defined in: packages/core/src/constructors.ts:204

Type guard: narrow a Result to its Defect variant, exposing .cause.

Type Parameters ​

Type Parameter
T
E

Parameters ​

ParameterType
rResult<T, E>

Returns ​

r is DefectView<T, E>

true when r is a Defect.

Remarks ​

A Defect has no public constructor — it only arises at a boundary (e.g. a callback throwing inside a combinator). This guard is how you detect one.

Example ​

ts
import { isDefect, Ok } from "unthrown";

// A throw inside a combinator is captured as a Defect:
const r = Ok(1).map(() => {
  throw new Error("boom");
});
isDefect(r); // => true
isDefect(Ok(1)); // => false

if (isDefect(r)) r.cause; // unknown, narrowed

isErr() ​

ts
function isErr<T, E>(r): r is ErrView<E, T>;

Defined in: packages/core/src/constructors.ts:176

Type guard: narrow a Result to its Err variant, exposing .error.

Type Parameters ​

Type Parameter
T
E

Parameters ​

ParameterType
rResult<T, E>

Returns ​

r is ErrView<E, T>

true when r is Err.

Example ​

ts
import { isErr, Ok, Err, type Result } from "unthrown";

isErr(Err("boom")); // => true
isErr(Ok(1)); // => false

declare const r: Result<number, string>;
if (isErr(r)) r.error; // string, narrowed

isOk() ​

ts
function isOk<T, E>(r): r is OkView<T, E>;

Defined in: packages/core/src/constructors.ts:155

Type guard: narrow a Result to its Ok variant, exposing .value.

Type Parameters ​

Type Parameter
T
E

Parameters ​

ParameterType
rResult<T, E>

Returns ​

r is OkView<T, E>

true when r is Ok.

Example ​

ts
import { isOk, Ok, Err, type Result } from "unthrown";

isOk(Ok(1)); // => true
isOk(Err("boom")); // => false

declare const r: Result<number, string>;
if (isOk(r)) r.value; // number, narrowed

isResult() ​

ts
function isResult(x): x is Result<unknown, unknown>;

Defined in: packages/core/src/core.ts:504

Type guard: is x a Result (any of Ok / Err / Defect)?

Parameters ​

ParameterType
xunknown

Returns ​

x is Result<unknown, unknown>

true when x is a Result produced by this library.

Remarks ​

Unlike isOk / isErr / isDefect, which narrow a value already known to be a Result, this narrows from unknown — useful at an untyped boundary. It checks the value carries the Result prototype (instanceof first, falling back to the Symbol.for("unthrown.Result") brand the prototype carries — so a Result built by another copy of unthrown, e.g. the CJS and ESM builds loaded side by side, is still recognised). A look-alike plain object ({ tag: "Ok" }) carries neither and is not matched; nor is a forgery built on the real prototype whose tag or payload is a getter (both must be own data properties). An AsyncResult is not a Result and returns false.

Example ​

ts
import { isResult, Ok, P } from "unthrown";

isResult(Ok(1)); // => true
isResult({ tag: "Ok" }); // => false (look-alike, wrong prototype)
isResult(Ok(1).toAsync()); // => false (an AsyncResult is not a Result)

const x: unknown = Ok(1);
if (isResult(x))
  // `E` is `unknown` here — an untyped boundary has no cases to enumerate,
  // so the `P._` escape hatch is the only arm that can terminate the match:
  // oxlint-disable-next-line unthrown/no-catch-all-pattern -- untyped boundary: `E` is `unknown`
  x.match({
    ok: () => 1,
    errCases: (m) => m.with(P._, () => 0),
    defect: () => -1,
  });

Tagged errors ​

TaggedError() ​

ts
function TaggedError<Tag>(tag, options?): TaggedErrorConstructor<Tag>;

Defined in: packages/core/src/tagged.ts:110

Build a base class for a tagged error — a class extending Error with a _tag string discriminant, in the style of Effect's Data.TaggedError.

Type Parameters ​

Type ParameterDescription
Tag extends stringthe string literal discriminant.

Parameters ​

ParameterTypeDescription
tagTagthe discriminant value; also the default error name.
options?{ name?: string; }optional overrides. options.name sets Error.name independently of tag (defaults to tag).
options.name?string-

Returns ​

TaggedErrorConstructor<Tag>

Remarks ​

Extend the returned class to declare a concrete error. Supply the payload with an instantiation expression; omit it for a payload-less error. The message is not a payload field — it is the human string owned by Error, not structured data, so it is reserved. Define it once per subclass the standard way, override message = "…" (it may interpolate the payload via this, which the base populates before the subclass field initialiser runs); a payload message is rejected at compile time, so contextual detail lives in typed fields, never baked into per-call prose. The _tag always reflects tag and cannot be overridden by the payload. name is likewise reserved — it is the display label (set it with options.name); a payload name is rejected at compile time (and excluded from the instance type), so it can't shadow Error.name. stack is reserved the same way — it is Error's trace, and even an untyped payload stack cannot clobber the real one. cause is deliberately not reserved: Error.cause is typed unknown, so a payload cause (e.g. a wrapped driver error) is a legitimate, narrowing structured field.

The matching half of the convention is P.tag(t) — the pattern constructor on the P namespace, which builds the { _tag: t } pattern this factory's _tag is selected by (there is no standalone tag export).

_tag is the discriminant matched by P.tag in the error combinators (result.mapErrCases((matcher) => matcher.with(P.tag("NotFound"), …))) and in match's errCases handler; Error.name is the human-facing label in stack traces and logs. By default they coincide, but they can be decoupled with options.name — so a tag can be namespaced for collision-safety ("@my-lib/RetryableError") without that slash-prefixed string leaking into Error.name:

ts
class RetryableError extends TaggedError("@my-lib/RetryableError", {
  name: "RetryableError",
}) {
  override message = "operation failed; safe to retry";
}

const e = new RetryableError();
e._tag;    // "@my-lib/RetryableError" — namespaced discriminant
e.name;    // "RetryableError"          — clean display name
e.message; // "operation failed; safe to retry" — the standard Error.message

Example ​

ts
class NotFound extends TaggedError("NotFound") {}
class HttpError extends TaggedError("HttpError")<{ status: number }> {}

new NotFound()._tag; // => "NotFound"
new HttpError({ status: 500 }).status; // => 500

Aggregate ​

all() ​

ts
function all<Rs>(results): Result<AllOk<Rs, { [K in string | number | symbol]: OkOf<Rs[K]> }>, ErrOf<Rs[number]>>;

Defined in: packages/core/src/interop.ts:729

Collect a tuple/array of Results into a single Result of all their success values.

Type Parameters ​

Type Parameter
Rs extends readonly Result<unknown, unknown>[]

Parameters ​

ParameterType
resultsreadonly [Rs]

Returns ​

Result<AllOk<Rs, { [K in string | number | symbol]: OkOf<Rs[K]> }>, ErrOf<Rs[number]>>

Remarks ​

Short-circuits on the first Err (later entries are not inspected for their error); any Defect present dominates, winning even over an earlier Err. A fixed tuple keeps its positional types — all([Ok(1), Ok("a")]) is Result<[number, string], …> — while a dynamic array Result<T, E>[] collapses to Result<T[], E> with no cast. For a record keyed by name, use allFromDict. To report every Err instead of only the first, use validateAll.

Example ​

ts
import { all, Ok, Err } from "unthrown";

all([Ok(1), Ok("a"), Ok(true)]).get(); // => [1, "a", true] (typed [number, string, boolean])
all([Ok(1), Err("e"), Ok(3)]); // => Err("e") (short-circuits on the first Err)

allAsync() ​

ts
function allAsync<Rs>(results): AsyncResult<AllOk<Rs, { [K in string | number | symbol]: AsyncOkOf<Rs[K]> }>, AsyncErrOf<Rs[number]>>;

Defined in: packages/core/src/interop.ts:793

The asynchronous counterpart of all: combine a tuple/array of AsyncResults into one AsyncResult of all their success values.

Type Parameters ​

Type Parameter
Rs extends readonly AsyncResult<unknown, unknown>[]

Parameters ​

ParameterType
resultsreadonly [Rs]

Returns ​

AsyncResult<AllOk<Rs, { [K in string | number | symbol]: AsyncOkOf<Rs[K]> }>, AsyncErrOf<Rs[number]>>

Remarks ​

The inputs are resolved concurrently (order preserved); the resolved Results are then folded with the same rules as all — first Err short-circuits, any Defect dominates. As ever, the returned AsyncResult's internal promise never rejects. For a record, use allFromDictAsync; to report every Err, use validateAllAsync.

Example ​

ts
import { allAsync, fromSafePromise } from "unthrown";

const both = allAsync([
  fromSafePromise(Promise.resolve(1)),
  fromSafePromise(Promise.resolve(2)),
]);
(await both).get(); // => [1, 2]

allFromDict() ​

ts
function allFromDict<R>(results): Result<{ [K in string | number | symbol]: OkOf<R[K]> }, ErrOf<R[keyof R]>>;

Defined in: packages/core/src/interop.ts:760

Collect a record of Results into a single Result of a record of their success values — allFromDict({ a: Result<A, E>, b: Result<B, E> }) is Result<{ a: A; b: B }, E>. The named counterpart of all, for parallel work you'd rather not tuple.

Type Parameters ​

Type Parameter
R extends ResultRecord

Parameters ​

ParameterType
resultsR

Returns ​

Result<{ [K in string | number | symbol]: OkOf<R[K]> }, ErrOf<R[keyof R]>>

Remarks ​

Same folding rules as all: first Err short-circuits, any Defect dominates. This is not error accumulation — for that, reach for validateAllFromDict, which accumulates every Err and folds them into one modeled error.

Example ​

ts
import { allFromDict, Ok, Err } from "unthrown";

allFromDict({ id: Ok(1), name: Ok("ada") }).get(); // => { id: 1, name: "ada" }
allFromDict({ id: Ok(1), name: Err("missing") }); // => Err("missing")

allFromDictAsync() ​

ts
function allFromDictAsync<R>(results): AsyncResult<{ [K in string | number | symbol]: AsyncOkOf<R[K]> }, AsyncErrOf<R[keyof R]>>;

Defined in: packages/core/src/interop.ts:828

The asynchronous counterpart of allFromDict: combine a record of AsyncResults into one AsyncResult of a record of their values.

Type Parameters ​

Type Parameter
R extends AsyncResultRecord

Parameters ​

ParameterType
resultsR

Returns ​

AsyncResult<{ [K in string | number | symbol]: AsyncOkOf<R[K]> }, AsyncErrOf<R[keyof R]>>

Remarks ​

Resolved concurrently (order preserved), folded with the all rules, and the internal promise never rejects. To report every Err, use validateAllFromDictAsync.

Example ​

ts
import { allFromDictAsync, fromSafePromise } from "unthrown";

const both = allFromDictAsync({
  a: fromSafePromise(Promise.resolve(1)),
  b: fromSafePromise(Promise.resolve("x")),
});
(await both).get(); // => { a: 1, b: "x" }

validateAll() ​

ts
function validateAll<Rs, E2>(results, merge): Result<AllOk<Rs, { [K in string | number | symbol]: OkOf<Rs[K]> }>, E2>;

Defined in: packages/core/src/interop.ts:894

Collect a tuple/array of Results, accumulating every Err and merging them into a single modeled error — the accumulating counterpart of all.

Type Parameters ​

Type ParameterDescription
Rs extends readonly Result<unknown, unknown>[]the tuple/array of input Result types.
E2the merged error type.

Parameters ​

ParameterTypeDescription
resultsreadonly [Rs]the results to collect.
merge(errors) => E2 & NotThenable<E2>folds the collected errors into one modeled error.

Returns ​

Result<AllOk<Rs, { [K in string | number | symbol]: OkOf<Rs[K]> }>, E2>

Remarks ​

Same success channel as all: a fixed tuple keeps its positional types, a dynamic array collapses to Result<T[], E2>. The difference is the error channel — instead of the first Err winning, every Err is collected in input order and handed to merge, whose return becomes the modeled error.

merge receives a non-empty list, so it is total: it is called only when at least one Err was collected. It is not called when every element is Ok, nor when a Defect is present.

Any Defect still dominates — it wins over the accumulated errors, which are discarded and never reach merge. A defect means something in this batch failed in a way nobody modeled, so the violations computed alongside it are not trustworthy. An out-of-contract non-Result element becomes a TypeError-caused Defect the same way, and a throw inside merge becomes a Defect too.

merge must be synchronous — an async one is a compile error (NotThenable), since a Promise in E is an unqualified rejection.

For schema-shaped input (a request body, a form), reach for @unthrown/standard-schema's fromSchema instead — a validator already hands you every issue as the modeled error. validateAll is for independent checks you wrote yourself. For a record keyed by name, use validateAllFromDict.

Example ​

ts
import { validateAll, Ok, Err } from "unthrown";

// every Err is collected, not just the first
validateAll([Ok(1), Err("stock"), Err("credit")], (errors) => errors.join(" and "));
// => Err("stock and credit")

// all-Ok keeps the positional tuple; `merge` never runs
validateAll([Ok(1), Ok("a")], (errors) => errors.join());
// => Ok([1, "a"]) typed Result<[number, string], string>

validateAllAsync() ​

ts
function validateAllAsync<Rs, E2>(results, merge): AsyncResult<AllOk<Rs, { [K in string | number | symbol]: AsyncOkOf<Rs[K]> }>, E2>;

Defined in: packages/core/src/interop.ts:979

The asynchronous counterpart of validateAll: collect a tuple/array of AsyncResults, accumulating every Err into one merged error.

Type Parameters ​

Type ParameterDescription
Rs extends readonly AsyncResult<unknown, unknown>[]the tuple/array of input AsyncResult types.
E2the merged error type.

Parameters ​

ParameterTypeDescription
resultsreadonly [Rs]the async results to collect.
merge(errors) => E2 & NotThenable<E2>folds the collected errors into one modeled error.

Returns ​

AsyncResult<AllOk<Rs, { [K in string | number | symbol]: AsyncOkOf<Rs[K]> }>, E2>

Remarks ​

Every validateAll rule holds, with the inputs resolved concurrently (order preserved) — as with allAsync, no work is short-circuited either way; the fail-fast/accumulating split is purely which errors get reported. The internal promise never rejects: an out-of-contract rejecting thenable becomes a dominating Defect. merge stays synchronous here too — this is exactly where its rejection would land unqualified in E. For a record, use validateAllFromDictAsync.

Example ​

ts
import { validateAllAsync, OkAsync, ErrAsync } from "unthrown";

const checked = validateAllAsync(
  [OkAsync(1), ErrAsync("stock"), ErrAsync("credit")],
  (errors) => errors.join(" and "),
);
// (await checked) => Err("stock and credit")

validateAllFromDict() ​

ts
function validateAllFromDict<R, E2>(results, merge): Result<{ [K in string | number | symbol]: OkOf<R[K]> }, E2>;

Defined in: packages/core/src/interop.ts:939

Collect a record of Results, accumulating every Err — the accumulating counterpart of allFromDict, and the named counterpart of validateAll.

Type Parameters ​

Type ParameterDescription
R extends ResultRecordthe record of input Result types.
E2the merged error type.

Parameters ​

ParameterTypeDescription
resultsRthe results to collect, keyed by name.
merge(entries) => E2 & NotThenable<E2>folds the collected [key, error] entries into one error.

Returns ​

Result<{ [K in string | number | symbol]: OkOf<R[K]> }, E2>

Remarks ​

merge receives a non-empty list of [key, error] entries, correlated per key: { a: Result<A, E1>; b: Result<B, E2> } yields ["a", E1] | ["b", E2], so a switch on the key narrows the error and an impossible pairing does not typecheck. That is what keeps two checks sharing one error type distinguishable. Entries come in key order — Object.keys order, then enumerable symbol keys (a symbol key is folded like any other).

Every other rule matches validateAll: any Defect dominates and discards the accumulated errors, a throw in merge becomes a Defect, and merge must be synchronous.

Example ​

ts
import { validateAllFromDict, Ok, Err } from "unthrown";

validateAllFromDict(
  { vatRate: Err("out of range"), currency: Ok("EUR"), dueDate: Err("past") },
  (entries) => entries.map(([key, error]) => `${key}: ${error}`).join("; "),
);
// => Err("vatRate: out of range; dueDate: past")

validateAllFromDictAsync() ​

ts
function validateAllFromDictAsync<R, E2>(results, merge): AsyncResult<{ [K in string | number | symbol]: AsyncOkOf<R[K]> }, E2>;

Defined in: packages/core/src/interop.ts:1016

The asynchronous counterpart of validateAllFromDict: collect a record of AsyncResults, accumulating every Err into one merged error.

Type Parameters ​

Type ParameterDescription
R extends AsyncResultRecordthe record of input AsyncResult types.
E2the merged error type.

Parameters ​

ParameterTypeDescription
resultsRthe async results to collect, keyed by name.
merge(entries) => E2 & NotThenable<E2>folds the collected [key, error] entries into one error.

Returns ​

AsyncResult<{ [K in string | number | symbol]: AsyncOkOf<R[K]> }, E2>

Remarks ​

The validateAllFromDict rules, over inputs resolved concurrently as in validateAllAsync.

Example ​

ts
import { validateAllFromDictAsync, OkAsync, ErrAsync } from "unthrown";

const checked = validateAllFromDictAsync(
  { stock: ErrAsync("none left"), credit: OkAsync(500) },
  (entries) => entries.map(([key, error]) => `${key}: ${error}`).join("; "),
);
// (await checked) => Err("stock: none left")

Errors ​

GetError ​

Defined in: packages/core/src/core.ts:64

Thrown by a Result's get / getErr when the assertion is wrong on a modeled result — get() on an Err, or getErr() on an Ok.

Remarks ​

The offending value is exposed two ways: the typed GetError.error property for programmatic access, and the standard Error.cause for the runtime and devtools to chain — when E is an Error (e.g. a TaggedError) its original stack is printed under "caused by".

A Defect is never wrapped in a GetError: its original cause is re-thrown (with its original stack) instead.

get() and getErr() are type-gated (this: Result<T, never> / Result<never, E>), so the wrong-variant branch that throws this is unreachable through well-typed code — it remains only as a defensive guard against unsound runtime misuse (e.g. an as cast past the gate).

Extends ​

  • Error

Type Parameters ​

Type ParameterDefault typeDescription
Eunknownthe type of the GetError.error it carries.

Constructors ​

Constructor ​
ts
new GetError<E>(error): GetError<E>;

Defined in: packages/core/src/core.ts:70

Parameters ​
ParameterType
errorE
Returns ​

GetError<E>

Overrides ​
ts
Error.constructor

Properties ​

PropertyModifierTypeDescriptionInherited fromDefined in
cause?publicunknown-Error.causenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24
errorreadonlyEThe offending value: the Err error for get(), or the Ok value for getErr().-packages/core/src/core.ts:69
messagepublicstring-Error.messagenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1075
namepublicstring-Error.namenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074
stack?publicstring-Error.stacknode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076
stackTraceLimitstaticnumberThe Error.stackTraceLimit property specifies the number of stack frames collected by a stack trace (whether generated by new Error().stack or Error.captureStackTrace(obj)). The default value is 10 but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames.Error.stackTraceLimitnode_modules/.pnpm/@types+node@26.5.1/node_modules/@types/node/globals.d.ts:67

Methods ​

captureStackTrace() ​
ts
static captureStackTrace(targetObject, constructorOpt?): void;

Defined in: node_modules/.pnpm/@types+node@26.5.1/node_modules/@types/node/globals.d.ts:51

Creates a .stack property on targetObject, which when accessed returns a string representing the location in the code at which Error.captureStackTrace() was called.

js
const myObject = {};
Error.captureStackTrace(myObject);
myObject.stack;  // Similar to `new Error().stack`

The first line of the trace will be prefixed with ${myObject.name}: ${myObject.message}.

The optional constructorOpt argument accepts a function. If given, all frames above constructorOpt, including constructorOpt, will be omitted from the generated stack trace.

The constructorOpt argument is useful for hiding implementation details of error generation from the user. For instance:

js
function a() {
  b();
}

function b() {
  c();
}

function c() {
  // Create an error without stack trace to avoid calculating the stack trace twice.
  const { stackTraceLimit } = Error;
  Error.stackTraceLimit = 0;
  const error = new Error();
  Error.stackTraceLimit = stackTraceLimit;

  // Capture the stack trace above function b
  Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace
  throw error;
}

a();
Parameters ​
ParameterType
targetObjectobject
constructorOpt?Function
Returns ​

void

Inherited from ​
ts
Error.captureStackTrace
prepareStackTrace() ​
ts
static prepareStackTrace(err, stackTraces): any;

Defined in: node_modules/.pnpm/@types+node@26.5.1/node_modules/@types/node/globals.d.ts:55

Parameters ​
ParameterType
errError
stackTracesCallSite[]
Returns ​

any

See ​

https://v8.dev/docs/stack-trace-api#customizing-stack-traces

Inherited from ​
ts
Error.prepareStackTrace

NonExhaustiveError ​

Defined in: packages/core/src/matcher.ts:296

Thrown by .run() / .exhaustive() when no arm matched the value. For well-typed callers the match is exhaustive by construction, so this is only reachable by a value that slipped past the types (a widened cast, a raw-JS caller); inside the error combinators the throw-to-defect net converts it to a Defect, and at the match edge it surfaces (a genuinely unmodeled value is a bug).

Example ​

ts
import { match, NonExhaustiveError } from "unthrown";

// A value typed "a" | "b" that is really "c" (a cast, a raw-JS caller):
const rogue = "c" as "a" | "b";
try {
  match(rogue)
    .with("a", () => 1)
    .with("b", () => 2)
    .exhaustive();
} catch (error) {
  error instanceof NonExhaustiveError; // => true
  (error as NonExhaustiveError).input; // => "c"
}

Extends ​

  • Error

Constructors ​

Constructor ​
ts
new NonExhaustiveError(input): NonExhaustiveError;

Defined in: packages/core/src/matcher.ts:299

Parameters ​
ParameterType
inputunknown
Returns ​

NonExhaustiveError

Overrides ​
ts
Error.constructor

Properties ​

PropertyModifierTypeDescriptionInherited fromDefined in
cause?publicunknown-Error.causenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24
inputreadonlyunknownThe value no arm matched.-packages/core/src/matcher.ts:298
messagepublicstring-Error.messagenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1075
namepublicstring-Error.namenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074
stack?publicstring-Error.stacknode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076
stackTraceLimitstaticnumberThe Error.stackTraceLimit property specifies the number of stack frames collected by a stack trace (whether generated by new Error().stack or Error.captureStackTrace(obj)). The default value is 10 but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames.Error.stackTraceLimitnode_modules/.pnpm/@types+node@26.5.1/node_modules/@types/node/globals.d.ts:67

Methods ​

captureStackTrace() ​
ts
static captureStackTrace(targetObject, constructorOpt?): void;

Defined in: node_modules/.pnpm/@types+node@26.5.1/node_modules/@types/node/globals.d.ts:51

Creates a .stack property on targetObject, which when accessed returns a string representing the location in the code at which Error.captureStackTrace() was called.

js
const myObject = {};
Error.captureStackTrace(myObject);
myObject.stack;  // Similar to `new Error().stack`

The first line of the trace will be prefixed with ${myObject.name}: ${myObject.message}.

The optional constructorOpt argument accepts a function. If given, all frames above constructorOpt, including constructorOpt, will be omitted from the generated stack trace.

The constructorOpt argument is useful for hiding implementation details of error generation from the user. For instance:

js
function a() {
  b();
}

function b() {
  c();
}

function c() {
  // Create an error without stack trace to avoid calculating the stack trace twice.
  const { stackTraceLimit } = Error;
  Error.stackTraceLimit = 0;
  const error = new Error();
  Error.stackTraceLimit = stackTraceLimit;

  // Capture the stack trace above function b
  Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace
  throw error;
}

a();
Parameters ​
ParameterType
targetObjectobject
constructorOpt?Function
Returns ​

void

Inherited from ​
ts
Error.captureStackTrace
prepareStackTrace() ​
ts
static prepareStackTrace(err, stackTraces): any;

Defined in: node_modules/.pnpm/@types+node@26.5.1/node_modules/@types/node/globals.d.ts:55

Parameters ​
ParameterType
errError
stackTracesCallSite[]
Returns ​

any

See ​

https://v8.dev/docs/stack-trace-api#customizing-stack-traces

Inherited from ​
ts
Error.prepareStackTrace

Released under the MIT License.