unthrown 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -16,13 +16,37 @@ type Prettify<T> = { [K in keyof T]: T[K] } & {};
16
16
  */
17
17
  type Bound<T, K extends string, U> = Prettify<Omit<T, K> & { readonly [P in K]: U }>;
18
18
  /**
19
- * The method surface every {@link Result} variant carries. Factored out so the
20
- * three variants ({@link OkView}, {@link ErrView}, {@link DefectView}) can each
21
- * intersect it. Not part of the public API on its own.
19
+ * Compile-time rejection of a thenable callback result — the type-level
20
+ * enforcement of "combinator callbacks are synchronous" (see the
21
+ * {@link AsyncResult} remarks).
22
+ *
23
+ * @remarks
24
+ * Resolves to `unknown` (a no-op in an intersection) for any non-thenable `R`,
25
+ * and to an explanatory string-literal type when `R` is a `PromiseLike` — so an
26
+ * `async` callback fails to compile with the explanation in the error. Without
27
+ * this, `async () => …` would be assignable to `() => void`, and its rejection
28
+ * would escape the pipeline as an unhandled rejection instead of a `Defect`.
29
+ * Lift async work with {@link fromPromise} and compose it with `flatMap`.
30
+ *
31
+ * @typeParam R - the callback's inferred return type.
32
+ * @category Types
33
+ */
34
+ type NotThenable<R> = [R] extends [PromiseLike<unknown>] ? "unthrown: combinator callbacks are synchronous — lift async work with fromPromise and compose with flatMap" : unknown;
35
+ /**
36
+ * The fluent method surface every {@link Result} variant carries — the
37
+ * combinators (`map`, `flatMap`, `mapErr`, `match`, `unwrap`, …), documented one
38
+ * per entry below. Factored out so the three variants ({@link OkView},
39
+ * {@link ErrView}, {@link DefectView}) can each intersect it; {@link AsyncResult}
40
+ * mirrors this surface with async signatures.
41
+ *
42
+ * @remarks
43
+ * This type exists to **document** the surface and to power narrowing — not to be
44
+ * authored against. You obtain it by holding a `Result` (or `AsyncResult`), never
45
+ * by implementing your own `Result`-like; treat it as read-only reference.
22
46
  *
23
47
  * @typeParam T - the success value type.
24
48
  * @typeParam E - the modeled error type.
25
- * @internal
49
+ * @category Methods
26
50
  */
27
51
  type ResultMethods<T, E> = {
28
52
  /**
@@ -31,10 +55,12 @@ type ResultMethods<T, E> = {
31
55
  * Runs `f` only on `Ok`; `Err` and `Defect` pass through untouched. If `f`
32
56
  * throws, the thrown value is captured as a `Defect`.
33
57
  *
58
+ * An async callback is rejected at compile time ({@link NotThenable}).
59
+ *
34
60
  * @typeParam U - the mapped success type.
35
61
  * @param f - maps the current success value to a new one.
36
62
  */
37
- map<U>(f: (value: T) => U): Result$1<U, E>;
63
+ map<U>(f: (value: T) => U & NotThenable<U>): Result$1<U, E>;
38
64
  /**
39
65
  * Sequence a dependent, `Result`-returning step (monadic bind).
40
66
  *
@@ -50,11 +76,12 @@ type ResultMethods<T, E> = {
50
76
  * Run a side effect on the success value and pass the `Result` through
51
77
  * unchanged.
52
78
  *
53
- * Runs only on `Ok`. If `f` throws, the throw becomes a `Defect`.
79
+ * Runs only on `Ok`. If `f` throws, the throw becomes a `Defect`. An async
80
+ * callback is rejected at compile time ({@link NotThenable}).
54
81
  *
55
82
  * @param f - the side effect (its return value is ignored).
56
83
  */
57
- tap(f: (value: T) => void): Result$1<T, E>;
84
+ tap<R>(f: (value: T) => R & NotThenable<R>): Result$1<T, E>;
58
85
  /**
59
86
  * Run a **failable** side effect on the success value, keeping the original
60
87
  * value but threading the effect's error.
@@ -99,14 +126,15 @@ type ResultMethods<T, E> = {
99
126
  * @remarks
100
127
  * `f` receives the scope and returns a value (not a `Result`); it is added as
101
128
  * `{ ...scope, [name]: value }`. Runs only on `Ok`; `Err`/`Defect` pass
102
- * through. A throw becomes a `Defect`.
129
+ * through. A throw becomes a `Defect`. An async callback is rejected at
130
+ * compile time ({@link NotThenable}).
103
131
  *
104
132
  * @typeParam K - the key the value is stored under.
105
133
  * @typeParam U - the value type.
106
134
  * @param name - the scope key.
107
135
  * @param f - computes a value from the accumulated scope.
108
136
  */
109
- let<K extends string, U>(name: K, f: (scope: T) => U): Result$1<Bound<T, K, U>, E>;
137
+ let<K extends string, U>(name: K, f: (scope: T) => U & NotThenable<U>): Result$1<Bound<T, K, U>, E>;
110
138
  /**
111
139
  * Replace the success value with a constant `value`.
112
140
  *
@@ -119,12 +147,13 @@ type ResultMethods<T, E> = {
119
147
  * Transform the modeled error with `f`.
120
148
  *
121
149
  * Runs `f` only on `Err`; `Ok` passes through and a `Defect` is **never**
122
- * touched. If `f` throws, the throw becomes a `Defect`.
150
+ * touched. If `f` throws, the throw becomes a `Defect`. An async callback is
151
+ * rejected at compile time ({@link NotThenable}).
123
152
  *
124
153
  * @typeParam E2 - the mapped error type.
125
154
  * @param f - maps the current error to a new one.
126
155
  */
127
- mapErr<E2>(f: (error: E) => E2): Result$1<T, E2>;
156
+ mapErr<E2>(f: (error: E) => E2 & NotThenable<E2>): Result$1<T, E2>;
128
157
  /**
129
158
  * Recover from an `Err` by producing another `Result`.
130
159
  *
@@ -144,20 +173,24 @@ type ResultMethods<T, E> = {
144
173
  * The result type is `Result<T | U, never>`, but `never` describes only the
145
174
  * **error** channel — a `Defect` can still be present at runtime, so do not
146
175
  * read `never` as "total". Runs `f` only on `Err`; `Ok` and `Defect` pass
147
- * through. If `f` throws, the throw becomes a `Defect`.
176
+ * through. If `f` throws, the throw becomes a `Defect`. An async callback is
177
+ * rejected at compile time ({@link NotThenable}).
148
178
  *
149
179
  * @typeParam U - the recovered success type.
150
180
  * @param f - produces a success value from the current error.
151
181
  */
152
- recover<U>(f: (error: E) => U): Result$1<T | U, never>;
182
+ recover<U>(f: (error: E) => U & NotThenable<U>): Result$1<T | U, never>;
153
183
  /**
154
184
  * Run a side effect on the error and pass the `Result` through unchanged.
155
185
  *
156
- * Runs only on `Err`. If `f` throws, the throw becomes a `Defect`.
186
+ * Runs only on `Err`. If `f` throws, the result is a `Defect` whose cause is
187
+ * an `AggregateError` of `[thrown, original failure]` — observing a failure
188
+ * never destroys it. An async callback is rejected at compile time
189
+ * ({@link NotThenable}).
157
190
  *
158
191
  * @param f - the side effect (its return value is ignored).
159
192
  */
160
- tapErr(f: (error: E) => void): Result$1<T, E>;
193
+ tapErr<R>(f: (error: E) => R & NotThenable<R>): Result$1<T, E>;
161
194
  /**
162
195
  * Run a **failable** side effect on the error, keeping the original error but
163
196
  * threading the effect's own error.
@@ -167,9 +200,10 @@ type ResultMethods<T, E> = {
167
200
  * returns a `Result`, but its **success value is discarded** — on the effect's
168
201
  * `Ok` the original `Err` flows through unchanged, while an `Err` (or `Defect`)
169
202
  * from `f` short-circuits and threads its error (`Result<T, E | E2>`). Runs only
170
- * on `Err`; `Ok` and `Defect` pass through. If `f` throws, the throw becomes a
171
- * `Defect`. Use it for a failable effect _during_ error handling (e.g. writing
172
- * the error to an audit log that may itself fail).
203
+ * on `Err`; `Ok` and `Defect` pass through. If `f` throws, the result is a
204
+ * `Defect` whose cause is an `AggregateError` of `[thrown, original failure]` —
205
+ * observing a failure never destroys it. Use it for a failable effect _during_
206
+ * error handling (e.g. writing the error to an audit log that may itself fail).
173
207
  *
174
208
  * @typeParam E2 - the error type the effect may introduce.
175
209
  * @param f - the failable side effect; its `Ok` value is ignored.
@@ -191,11 +225,14 @@ type ResultMethods<T, E> = {
191
225
  recoverDefect<U, E2>(f: (cause: unknown) => Result$1<U, E2>): Result$1<T | U, E | E2>;
192
226
  /**
193
227
  * Run a side effect on a present `Defect`'s cause (e.g. logging) and pass the
194
- * `Defect` through unchanged.
228
+ * `Defect` through unchanged. If `f` throws, the result is a `Defect` whose
229
+ * cause is an `AggregateError` of `[thrown, original failure]` — observing a
230
+ * failure never destroys it. An async callback is rejected at compile time
231
+ * ({@link NotThenable}).
195
232
  *
196
233
  * @param f - the side effect over the unknown cause.
197
234
  */
198
- tapDefect(f: (cause: unknown) => void): Result$1<T, E>;
235
+ tapDefect<R>(f: (cause: unknown) => R & NotThenable<R>): Result$1<T, E>;
199
236
  /**
200
237
  * Exhaustively fold all three runtime states into a single value of type `R`.
201
238
  *
@@ -234,18 +271,20 @@ type ResultMethods<T, E> = {
234
271
  /**
235
272
  * The success value, or `fallback` on `Err`.
236
273
  *
237
- * @param fallback - returned when the result is an `Err`.
274
+ * @typeParam U - the fallback type (may differ from `T`; the return widens to `T | U`).
275
+ * @param fallback - returned when the result is an `Err` (may be a different type; the return widens to `T | U`).
238
276
  * @throws Re-throws on a `Defect` — a Defect is a bug, not an absent value, so
239
277
  * it is never silently replaced.
240
278
  */
241
- unwrapOr(fallback: T): T;
279
+ unwrapOr<U>(fallback: U): T | U;
242
280
  /**
243
281
  * The success value, or `f(error)` on `Err`.
244
282
  *
245
- * @param f - lazily computes the fallback from the error.
283
+ * @typeParam U - the fallback type (may differ from `T`; the return widens to `T | U`).
284
+ * @param f - lazily computes the fallback from the error (may return a different type; the return widens to `T | U`).
246
285
  * @throws Re-throws on a `Defect`.
247
286
  */
248
- unwrapOrElse(f: (error: E) => T): T;
287
+ unwrapOrElse<U>(f: (error: E) => U): T | U;
249
288
  /**
250
289
  * The success value, or `null` on `Err`.
251
290
  *
@@ -263,17 +302,58 @@ type ResultMethods<T, E> = {
263
302
  isDefect(): this is DefectView<T, E>; /** Lift this synchronous `Result` into an {@link AsyncResult}. */
264
303
  toAsync(): AsyncResult$1<T, E>;
265
304
  };
266
- /** The `Ok` variant of a {@link Result}: a success carrying a `value`. */
305
+ /**
306
+ * The `Ok` variant of a {@link Result}: a success carrying a `value`. This is
307
+ * what a successful `isOk` guard narrows to, making `.value` reachable. It also
308
+ * carries the shared fluent surface ({@link ResultMethods}).
309
+ *
310
+ * @example
311
+ * ```ts
312
+ * if (r.isOk()) r.value; // r: OkView<T, E> here — .value is a T
313
+ * ```
314
+ *
315
+ * @category Types
316
+ */
267
317
  type OkView<T, E = never> = ResultMethods<T, E> & {
268
318
  readonly tag: "Ok";
269
319
  readonly value: T;
270
320
  };
271
- /** The `Err` variant of a {@link Result}: a modeled failure carrying an `error`. */
321
+ /**
322
+ * The `Err` variant of a {@link Result}: a modeled failure carrying an `error`.
323
+ * This is what a successful `isErr` guard narrows to, exposing `.error`. It also
324
+ * carries the shared fluent surface ({@link ResultMethods}).
325
+ *
326
+ * @remarks
327
+ * **Note the parameter order: `ErrView<E, T>` puts the error type _first_** — the
328
+ * reverse of the `<T, E>` order used by {@link OkView}, {@link DefectView}, and
329
+ * {@link Result} — because `Result<T, E>` narrows to `ErrView<E, T>` (the error is
330
+ * the payload the guard makes reachable). You rarely write it by hand (a failed
331
+ * `isErr()` narrows to it for you); if you do, mind the flip — `ErrView<MyError,
332
+ * MyValue>`, not `ErrView<MyValue, MyError>`.
333
+ *
334
+ * @example
335
+ * ```ts
336
+ * if (r.isErr()) r.error; // r: ErrView<E, T> here — .error is an E
337
+ * ```
338
+ *
339
+ * @category Types
340
+ */
272
341
  type ErrView<E, T = never> = ResultMethods<T, E> & {
273
342
  readonly tag: "Err";
274
343
  readonly error: E;
275
344
  };
276
- /** The `Defect` variant of a {@link Result}: an unmodeled failure carrying a `cause`. */
345
+ /**
346
+ * The `Defect` variant of a {@link Result}: an unmodeled failure carrying a
347
+ * `cause`. This is what a successful `isDefect` guard narrows to, exposing
348
+ * `.cause`. It also carries the shared fluent surface ({@link ResultMethods}).
349
+ *
350
+ * @example
351
+ * ```ts
352
+ * if (r.isDefect()) r.cause; // r: DefectView<T, E> here — .cause is `unknown`
353
+ * ```
354
+ *
355
+ * @category Types
356
+ */
277
357
  type DefectView<T = never, E = never> = ResultMethods<T, E> & {
278
358
  readonly tag: "Defect";
279
359
  readonly cause: unknown;
@@ -324,107 +404,227 @@ type Result$1<T, E> = OkView<T, E> | ErrView<E, T> | DefectView<T, E>;
324
404
  * An {@link AsyncResult}'s internal promise never rejects, so `await`-ing one
325
405
  * always yields a {@link Result} and never throws — there is no rejection
326
406
  * channel to model, and none is advertised. At runtime it is still a thenable
327
- * (the only way `await` can collapse it); the narrowing simply keeps it from
328
- * being treated as a raw promise (e.g. dropped into `Promise.all`).
407
+ * (the only way `await` can collapse it), and `Promise.all` / `Promise.resolve`
408
+ * will still adopt it — harmlessly, since it settles to a `Result` and never
409
+ * rejects. What the narrowing prevents is treating it as a full promise:
410
+ * `.catch()` / `.finally()` do not type-check, because there is no rejection to
411
+ * handle.
329
412
  *
330
413
  * @typeParam T - the value `await` resolves to.
414
+ *
415
+ * @category Types
331
416
  */
332
417
  type Awaitable<T> = {
333
418
  then<R = T>(onfulfilled?: ((value: T) => R | PromiseLike<R>) | null): PromiseLike<R>;
334
419
  };
335
420
  /**
336
- * The asynchronous counterpart of {@link Result}: an awaitable wrapper with the
337
- * same method surface, collapsing to a `Result<T, E>` when `await`-ed.
421
+ * The async method surface every {@link AsyncResult} carries — the combinators
422
+ * (`map`, `flatMap`, `mapErr`, `match`, `unwrap`, …) with their asynchronous
423
+ * signatures, documented one per entry below. The async mirror of
424
+ * {@link ResultMethods}: each entry links its synchronous counterpart and states
425
+ * only the async delta.
338
426
  *
339
427
  * @remarks
340
- * **Combinator callbacks are synchronous.** A raw `Promise` may never enter an
341
- * `AsyncResult` method — that would be an un-qualified async boundary, and its
342
- * rejection would silently become a `Defect`, skipping the triage that
343
- * {@link fromPromise} forces. To do further async work, re-enter through a
344
- * qualified boundary and compose it: `ar.flatMap((v) => fromPromise(work(v),
345
- * qualify))`. The eliminators (`unwrap`, …) return promises; the binds
346
- * (`flatMap`, `flatTap`, `orElse`, `recoverDefect`) additionally accept an
347
- * `AsyncResult`.
348
- *
349
- * To pattern-match an `AsyncResult`, `await` it first: `match(await ar)`.
428
+ * Like {@link ResultMethods}, this type exists to **document** the surface — not
429
+ * to be authored against; you obtain it by holding an `AsyncResult`. Its
430
+ * combinator callbacks are **synchronous** (a raw `Promise` may never enter — see
431
+ * the {@link AsyncResult} remarks); async work re-enters via {@link fromPromise}
432
+ * and composes with `flatMap`. Systematic differences from the sync surface: the
433
+ * binds return an `AsyncResult` (and additionally accept one), and the
434
+ * eliminators return a `Promise`.
350
435
  *
351
436
  * @typeParam T - the success value type.
352
437
  * @typeParam E - the modeled error type.
438
+ * @category Methods
353
439
  */
354
- type AsyncResult$1<T, E> = Awaitable<Result$1<T, E>> & {
355
- /** Asynchronous `map`. `f` is synchronous; a throw becomes a `Defect`. */map<U>(f: (value: T) => U): AsyncResult$1<U, E>;
440
+ type AsyncResultMethods<T, E> = {
356
441
  /**
357
- * Asynchronous `flatMap`. `f` may return a `Result` **or** an `AsyncResult`
358
- * (never a raw `Promise`); a throw becomes a `Defect`.
442
+ * Asynchronous {@link ResultMethods.map | map}: transforms the success value
443
+ * with `f`. `f` is synchronous; a throw becomes a `Defect`. An async callback
444
+ * is rejected at compile time ({@link NotThenable}).
359
445
  */
360
- flatMap<U, E2>(f: (value: T) => Result$1<U, E2> | AsyncResult$1<U, E2>): AsyncResult$1<U, E | E2>; /** Asynchronous `tap`. `f` is synchronous; a throw becomes a `Defect`. */
361
- tap(f: (value: T) => void): AsyncResult$1<T, E>;
446
+ map<U>(f: (value: T) => U & NotThenable<U>): AsyncResult$1<U, E>;
362
447
  /**
363
- * Asynchronous `flatTap` — a failable tap that keeps the original value. `f`
364
- * may return a `Result` **or** an `AsyncResult`; its `Ok` value is discarded,
365
- * an `Err`/`Defect` short-circuits, and a throw becomes a `Defect`.
448
+ * Asynchronous {@link ResultMethods.flatMap | flatMap}. Unlike the sync form,
449
+ * `f` may return a `Result` **or** an `AsyncResult` (never a raw `Promise`); a
450
+ * throw becomes a `Defect`.
366
451
  */
367
- flatTap<E2>(f: (value: T) => Result$1<unknown, E2> | AsyncResult$1<unknown, E2>): AsyncResult$1<T, E | E2>;
452
+ flatMap<U, E2>(f: (value: T) => Result$1<U, E2> | AsyncResult$1<U, E2>): AsyncResult$1<U, E | E2>;
368
453
  /**
369
- * Asynchronous `bind` (do-notation). `f` may return a `Result` **or** an
370
- * `AsyncResult`; its value is bound under `name` in the accumulating scope.
454
+ * Asynchronous {@link ResultMethods.tap | tap}. `f` is synchronous; a throw
455
+ * becomes a `Defect`. An async callback is rejected at compile time
456
+ * ({@link NotThenable}).
371
457
  */
372
- bind<K extends string, U, E2>(name: K, f: (scope: T) => Result$1<U, E2> | AsyncResult$1<U, E2>): AsyncResult$1<Bound<T, K, U>, E | E2>; /** Asynchronous `let` (do-notation). `f` returns a plain value, bound under `name`. */
373
- let<K extends string, U>(name: K, f: (scope: T) => U): AsyncResult$1<Bound<T, K, U>, E>; /** Asynchronous `as`. */
374
- as<U>(value: U): AsyncResult$1<U, E>; /** Asynchronous `mapErr`. `f` is synchronous; a throw becomes a `Defect`. */
375
- mapErr<E2>(f: (error: E) => E2): AsyncResult$1<T, E2>; /** Asynchronous `orElse`. `f` may return a `Result` or an `AsyncResult`. */
376
- orElse<U, E2>(f: (error: E) => Result$1<U, E2> | AsyncResult$1<U, E2>): AsyncResult$1<T | U, E2>; /** Asynchronous `recover`. `f` is synchronous; a throw becomes a `Defect`. */
377
- recover<U>(f: (error: E) => U): AsyncResult$1<T | U, never>; /** Asynchronous `tapErr`. `f` is synchronous; a throw becomes a `Defect`. */
378
- tapErr(f: (error: E) => void): AsyncResult$1<T, E>;
458
+ tap<R>(f: (value: T) => R & NotThenable<R>): AsyncResult$1<T, E>;
379
459
  /**
380
- * Asynchronous `flatTapErr` — a failable tap on the error that keeps the
381
- * original error. `f` may return a `Result` **or** an `AsyncResult`; its `Ok`
382
- * value is discarded, an `Err`/`Defect` from `f` threads through, and a throw
460
+ * Asynchronous {@link ResultMethods.flatTap | flatTap} — a failable tap that
461
+ * keeps the original value. `f` may return a `Result` **or** an `AsyncResult`;
462
+ * its `Ok` value is discarded, an `Err`/`Defect` short-circuits, and a throw
383
463
  * becomes a `Defect`.
384
464
  */
385
- flatTapErr<E2>(f: (error: E) => Result$1<unknown, E2> | AsyncResult$1<unknown, E2>): AsyncResult$1<T, E | E2>; /** Asynchronous `recoverDefect`. `f` may return a `Result` or an `AsyncResult`. */
386
- recoverDefect<U, E2>(f: (cause: unknown) => Result$1<U, E2> | AsyncResult$1<U, E2>): AsyncResult$1<T | U, E | E2>; /** Asynchronous `tapDefect`. */
387
- tapDefect(f: (cause: unknown) => void): AsyncResult$1<T, E>; /** Asynchronous `match`. Handlers are synchronous; resolves to `R`. */
465
+ flatTap<E2>(f: (value: T) => Result$1<unknown, E2> | AsyncResult$1<unknown, E2>): AsyncResult$1<T, E | E2>;
466
+ /**
467
+ * Asynchronous {@link ResultMethods.bind | bind} (do-notation). `f` may return
468
+ * a `Result` **or** an `AsyncResult`; its value is bound under `name` in the
469
+ * accumulating scope.
470
+ */
471
+ bind<K extends string, U, E2>(name: K, f: (scope: T) => Result$1<U, E2> | AsyncResult$1<U, E2>): AsyncResult$1<Bound<T, K, U>, E | E2>;
472
+ /**
473
+ * Asynchronous {@link ResultMethods.let | let} (do-notation). `f` returns a
474
+ * plain value, bound under `name`. An async callback is rejected at compile
475
+ * time ({@link NotThenable}).
476
+ */
477
+ let<K extends string, U>(name: K, f: (scope: T) => U & NotThenable<U>): AsyncResult$1<Bound<T, K, U>, E>; /** Asynchronous {@link ResultMethods.as | as}: replaces the value with `value`. */
478
+ as<U>(value: U): AsyncResult$1<U, E>;
479
+ /**
480
+ * Asynchronous {@link ResultMethods.mapErr | mapErr}. `f` is synchronous; a
481
+ * throw becomes a `Defect`. An async callback is rejected at compile time
482
+ * ({@link NotThenable}).
483
+ */
484
+ mapErr<E2>(f: (error: E) => E2 & NotThenable<E2>): AsyncResult$1<T, E2>;
485
+ /**
486
+ * Asynchronous {@link ResultMethods.orElse | orElse}. `f` may return a `Result`
487
+ * or an `AsyncResult`.
488
+ */
489
+ orElse<U, E2>(f: (error: E) => Result$1<U, E2> | AsyncResult$1<U, E2>): AsyncResult$1<T | U, E2>;
490
+ /**
491
+ * Asynchronous {@link ResultMethods.recover | recover}. `f` is synchronous; a
492
+ * throw becomes a `Defect`. An async callback is rejected at compile time
493
+ * ({@link NotThenable}).
494
+ */
495
+ recover<U>(f: (error: E) => U & NotThenable<U>): AsyncResult$1<T | U, never>;
496
+ /**
497
+ * Asynchronous {@link ResultMethods.tapErr | tapErr}. `f` is synchronous; if it
498
+ * throws, the result is a `Defect` whose cause is an `AggregateError` of
499
+ * `[thrown, original failure]` — observing a failure never destroys it. An
500
+ * async callback is rejected at compile time ({@link NotThenable}).
501
+ */
502
+ tapErr<R>(f: (error: E) => R & NotThenable<R>): AsyncResult$1<T, E>;
503
+ /**
504
+ * Asynchronous {@link ResultMethods.flatTapErr | flatTapErr} — the
505
+ * error-channel mirror of `flatTap`. `f` may return a `Result` **or** an
506
+ * `AsyncResult`; its `Ok` value is discarded, an `Err`/`Defect` from `f`
507
+ * threads through, and if `f` throws, the result is a `Defect` whose cause is
508
+ * an `AggregateError` of `[thrown, original failure]` — observing a failure
509
+ * never destroys it.
510
+ */
511
+ flatTapErr<E2>(f: (error: E) => Result$1<unknown, E2> | AsyncResult$1<unknown, E2>): AsyncResult$1<T, E | E2>;
512
+ /**
513
+ * Asynchronous {@link ResultMethods.recoverDefect | recoverDefect}. `f` may
514
+ * return a `Result` or an `AsyncResult`.
515
+ */
516
+ recoverDefect<U, E2>(f: (cause: unknown) => Result$1<U, E2> | AsyncResult$1<U, E2>): AsyncResult$1<T | U, E | E2>;
517
+ /**
518
+ * Asynchronous {@link ResultMethods.tapDefect | tapDefect}. If `f` throws, the
519
+ * result is a `Defect` whose cause is an `AggregateError` of `[thrown,
520
+ * original failure]` — observing a failure never destroys it. An async
521
+ * callback is rejected at compile time ({@link NotThenable}).
522
+ */
523
+ tapDefect<R>(f: (cause: unknown) => R & NotThenable<R>): AsyncResult$1<T, E>;
524
+ /**
525
+ * Asynchronous {@link ResultMethods.match | match}. Handlers are synchronous;
526
+ * resolves to a `Promise<R>`.
527
+ */
388
528
  match<R>(cases: {
389
529
  ok: (value: T) => R;
390
530
  err: (error: E) => R;
391
531
  defect: (cause: unknown) => R;
392
- }): Promise<R>; /** Asynchronous `unwrap`. The returned promise rejects on `Err`/`Defect`. */
393
- unwrap(): Promise<T>; /** Asynchronous `unwrapErr`. */
394
- unwrapErr(): Promise<E>; /** Asynchronous `unwrapOr`. */
395
- unwrapOr(fallback: T): Promise<T>; /** Asynchronous `unwrapOrElse`. */
396
- unwrapOrElse(f: (error: E) => T): Promise<T>; /** Asynchronous `getOrNull`. */
397
- getOrNull(): Promise<T | null>; /** Asynchronous `getOrUndefined`. */
532
+ }): Promise<R>;
533
+ /**
534
+ * Asynchronous {@link ResultMethods.unwrap | unwrap}. The returned promise
535
+ * rejects on `Err`/`Defect`.
536
+ */
537
+ unwrap(): Promise<T>; /** Asynchronous {@link ResultMethods.unwrapErr | unwrapErr}. */
538
+ unwrapErr(): Promise<E>; /** Asynchronous {@link ResultMethods.unwrapOr | unwrapOr}. */
539
+ unwrapOr<U>(fallback: U): Promise<T | U>; /** Asynchronous {@link ResultMethods.unwrapOrElse | unwrapOrElse}. */
540
+ unwrapOrElse<U>(f: (error: E) => U): Promise<T | U>; /** Asynchronous {@link ResultMethods.getOrNull | getOrNull}. */
541
+ getOrNull(): Promise<T | null>; /** Asynchronous {@link ResultMethods.getOrUndefined | getOrUndefined}. */
398
542
  getOrUndefined(): Promise<T | undefined>;
399
543
  };
400
544
  /**
401
- * Extract the success type `T` from a `Result`.
545
+ * The asynchronous counterpart of {@link Result}: an awaitable wrapper carrying
546
+ * the {@link AsyncResultMethods} surface, collapsing to a `Result<T, E>` when
547
+ * `await`-ed.
548
+ *
549
+ * @remarks
550
+ * **Combinator callbacks are synchronous.** A raw `Promise` may never enter an
551
+ * `AsyncResult` method — that would be an un-qualified async boundary, and its
552
+ * rejection would silently become a `Defect`, skipping the triage that
553
+ * {@link fromPromise} forces. To do further async work, re-enter through a
554
+ * qualified boundary and compose it: `ar.flatMap((v) => fromPromise(work(v),
555
+ * qualify))`. The eliminators (`unwrap`, …) return promises; the binds
556
+ * (`flatMap`, `flatTap`, `orElse`, `recoverDefect`) additionally accept an
557
+ * `AsyncResult`. Its combinators are documented one per entry on
558
+ * {@link AsyncResultMethods}.
559
+ *
560
+ * To pattern-match an `AsyncResult`, `await` it first: `match(await ar)`.
561
+ *
562
+ * @typeParam T - the success value type.
563
+ * @typeParam E - the modeled error type.
564
+ */
565
+ type AsyncResult$1<T, E> = Awaitable<Result$1<T, E>> & AsyncResultMethods<T, E>;
566
+ /**
567
+ * Extract the success type `T` from a `Result` type — derive one type from
568
+ * another instead of restating it (e.g. the payload a function returns).
402
569
  *
403
570
  * @typeParam R - the `Result` type to inspect.
571
+ *
572
+ * @example
573
+ * ```ts
574
+ * type R = Result<User, NotFound>;
575
+ * type U = OkOf<R>; // User
576
+ * type E = ErrOf<R>; // NotFound
577
+ * ```
578
+ *
579
+ * @category Types
404
580
  */
405
581
  type OkOf<R> = R extends {
406
582
  readonly tag: "Ok";
407
583
  readonly value: infer T;
408
584
  } ? T : never;
409
585
  /**
410
- * Extract the error type `E` from a `Result`.
586
+ * Extract the error type `E` from a `Result` type — the counterpart of
587
+ * {@link OkOf}.
411
588
  *
412
589
  * @typeParam R - the `Result` type to inspect.
590
+ *
591
+ * @example
592
+ * ```ts
593
+ * type E = ErrOf<Result<User, NotFound>>; // NotFound
594
+ * ```
595
+ *
596
+ * @category Types
413
597
  */
414
598
  type ErrOf<R> = R extends {
415
599
  readonly tag: "Err";
416
600
  readonly error: infer E;
417
601
  } ? E : never;
418
602
  /**
419
- * Extract the success type `T` from an {@link AsyncResult}.
603
+ * Extract the success type `T` from an {@link AsyncResult} type — the async
604
+ * counterpart of {@link OkOf}.
420
605
  *
421
606
  * @typeParam R - the `AsyncResult` type to inspect.
607
+ *
608
+ * @example
609
+ * ```ts
610
+ * type T = AsyncOkOf<AsyncResult<User, NotFound>>; // User
611
+ * ```
612
+ *
613
+ * @category Types
422
614
  */
423
615
  type AsyncOkOf<R> = R extends AsyncResult$1<infer T, unknown> ? T : never;
424
616
  /**
425
- * Extract the error type `E` from an {@link AsyncResult}.
617
+ * Extract the error type `E` from an {@link AsyncResult} type — the async
618
+ * counterpart of {@link ErrOf}.
426
619
  *
427
620
  * @typeParam R - the `AsyncResult` type to inspect.
621
+ *
622
+ * @example
623
+ * ```ts
624
+ * type E = AsyncErrOf<AsyncResult<User, NotFound>>; // NotFound
625
+ * ```
626
+ *
627
+ * @category Types
428
628
  */
429
629
  type AsyncErrOf<R> = R extends AsyncResult$1<unknown, infer E> ? E : never;
430
630
  //#endregion
@@ -438,8 +638,12 @@ type AsyncErrOf<R> = R extends AsyncResult$1<unknown, infer E> ? E : never;
438
638
  * @example
439
639
  * ```ts
440
640
  * import { Ok } from "unthrown";
441
- * Ok(42).unwrap(); // 42
641
+ *
642
+ * Ok(2).map((n) => n + 1); // => Ok(3)
643
+ * Ok(42).unwrap(); // => 42
442
644
  * ```
645
+ *
646
+ * @category Constructors
443
647
  */
444
648
  declare function Ok<T>(value: T): Result$1<T, never>;
445
649
  /**
@@ -451,8 +655,12 @@ declare function Ok<T>(value: T): Result$1<T, never>;
451
655
  * @example
452
656
  * ```ts
453
657
  * import { Err } from "unthrown";
454
- * Err("not_found").unwrapErr(); // "not_found"
658
+ *
659
+ * Err("not_found").map((n) => n + 1); // => Err("not_found") (map skipped)
660
+ * Err("not_found").unwrapErr(); // => "not_found"
455
661
  * ```
662
+ *
663
+ * @category Constructors
456
664
  */
457
665
  declare function Err<E>(error: E): Result$1<never, E>;
458
666
  /**
@@ -462,22 +670,61 @@ declare function Err<E>(error: E): Result$1<never, E>;
462
670
  *
463
671
  * @example
464
672
  * ```ts
465
- * import { isOk, type Result } from "unthrown";
673
+ * import { isOk, Ok, Err, type Result } from "unthrown";
674
+ *
675
+ * isOk(Ok(1)); // => true
676
+ * isOk(Err("boom")); // => false
677
+ *
466
678
  * declare const r: Result<number, string>;
467
679
  * if (isOk(r)) r.value; // number, narrowed
468
680
  * ```
681
+ *
682
+ * @category Guards
469
683
  */
470
684
  declare function isOk<T, E>(r: Result$1<T, E>): r is OkView<T, E>;
471
685
  /**
472
686
  * Type guard: narrow a {@link Result} to its `Err` variant, exposing `.error`.
473
687
  *
474
688
  * @returns `true` when `r` is `Err`.
689
+ *
690
+ * @example
691
+ * ```ts
692
+ * import { isErr, Ok, Err, type Result } from "unthrown";
693
+ *
694
+ * isErr(Err("boom")); // => true
695
+ * isErr(Ok(1)); // => false
696
+ *
697
+ * declare const r: Result<number, string>;
698
+ * if (isErr(r)) r.error; // string, narrowed
699
+ * ```
700
+ *
701
+ * @category Guards
475
702
  */
476
703
  declare function isErr<T, E>(r: Result$1<T, E>): r is ErrView<E, T>;
477
704
  /**
478
705
  * Type guard: narrow a {@link Result} to its `Defect` variant, exposing `.cause`.
479
706
  *
707
+ * @remarks
708
+ * A `Defect` has no public constructor — it only arises at a boundary (e.g. a
709
+ * callback throwing inside a combinator). This guard is how you detect one.
710
+ *
480
711
  * @returns `true` when `r` is a `Defect`.
712
+ *
713
+ * @example
714
+ * ```ts
715
+ * import { isDefect, Ok } from "unthrown";
716
+ *
717
+ * // A throw inside a combinator is captured as a Defect:
718
+ * const r = Ok(1).map(() => {
719
+ * throw new Error("boom");
720
+ * });
721
+ * isDefect(r); // => true
722
+ * isDefect(Ok(1)); // => false
723
+ *
724
+ * if (isDefect(r)) r.cause; // unknown, narrowed
725
+ * ```
726
+ *
727
+ * @category Guards
481
728
  */
482
729
  declare function isDefect<T, E>(r: Result$1<T, E>): r is DefectView<T, E>;
483
730
  //#endregion
@@ -497,6 +744,8 @@ declare function isDefect<T, E>(r: Result$1<T, E>): r is DefectView<T, E>;
497
744
  * re-thrown (with its original stack) instead.
498
745
  *
499
746
  * @typeParam E - the type of the {@link UnwrapError.error} it carries.
747
+ *
748
+ * @category Errors
500
749
  */
501
750
  declare class UnwrapError<E = unknown> extends Error {
502
751
  /**
@@ -517,6 +766,20 @@ declare class UnwrapError<E = unknown> extends Error {
517
766
  * is not a `Result` and returns `false`.
518
767
  *
519
768
  * @returns `true` when `x` is a `Result` produced by this library.
769
+ *
770
+ * @example
771
+ * ```ts
772
+ * import { isResult, Ok } from "unthrown";
773
+ *
774
+ * isResult(Ok(1)); // => true
775
+ * isResult({ tag: "Ok" }); // => false (look-alike, wrong prototype)
776
+ * isResult(Ok(1).toAsync()); // => false (an AsyncResult is not a Result)
777
+ *
778
+ * const x: unknown = Ok(1);
779
+ * if (isResult(x)) x.match({ ok: () => 1, err: () => 0, defect: () => -1 });
780
+ * ```
781
+ *
782
+ * @category Guards
520
783
  */
521
784
  declare function isResult(x: unknown): x is Result$1<unknown, unknown>;
522
785
  //#endregion
@@ -542,6 +805,24 @@ declare function isResult(x: unknown): x is Result$1<unknown, unknown>;
542
805
  * .map(({ user, org, label }) => render(user, org, label));
543
806
  * // Result<View, NotFound>
544
807
  * ```
808
+ *
809
+ * @example
810
+ * ```ts
811
+ * import { Do, Ok, Err } from "unthrown";
812
+ *
813
+ * // Ok path — the scope accumulates:
814
+ * Do()
815
+ * .bind("a", () => Ok(2))
816
+ * .let("b", ({ a }) => a * 10)
817
+ * .map(({ a, b }) => a + b); // => Ok(22)
818
+ *
819
+ * // Err path — the first Err short-circuits the rest:
820
+ * Do()
821
+ * .bind("a", () => Err("boom"))
822
+ * .let("b", ({ a }) => a); // => Err("boom")
823
+ * ```
824
+ *
825
+ * @category Do-notation
545
826
  */
546
827
  declare function Do(): Result$1<{}, never>;
547
828
  //#endregion
@@ -580,10 +861,16 @@ type Defect = {
580
861
  * @param value - the possibly-absent value.
581
862
  * @param onAbsent - lazily produces the error for the absent case.
582
863
  *
864
+ * @category Interop
865
+ *
583
866
  * @example
584
867
  * ```ts
585
868
  * import { fromNullable } from "unthrown";
586
- * fromNullable(map.get(key), () => "missing").unwrap();
869
+ *
870
+ * const map = new Map([["a", 1]]);
871
+ * fromNullable(map.get("a"), () => "absent").unwrap(); // => 1
872
+ * fromNullable(map.get("z"), () => "absent"); // => Err("absent")
873
+ * fromNullable(0, () => "absent").unwrap(); // => 0 (falsy but present)
587
874
  * ```
588
875
  */
589
876
  declare function fromNullable<T, E>(value: T | null | undefined, onAbsent: () => E): Result$1<NonNullable<T>, E>;
@@ -612,11 +899,21 @@ declare function fromNullable<T, E>(value: T | null | undefined, onAbsent: () =>
612
899
  * unmodeled by returning `defect(cause)` (the helper passed as its second arg).
613
900
  * @returns a function with the same arguments returning `Result<T, E>`.
614
901
  *
902
+ * @category Interop
903
+ *
615
904
  * @example
616
905
  * ```ts
617
906
  * import { fromThrowable } from "unthrown";
618
- * const parse = fromThrowable(JSON.parse, (cause, defect) => defect(cause));
619
- * parse("{}").unwrap();
907
+ *
908
+ * // Model the parse failure as an `Err`, everything unexpected as a `Defect`.
909
+ * const parse = fromThrowable(
910
+ * (text: string) => JSON.parse(text) as unknown,
911
+ * (cause, defect) =>
912
+ * cause instanceof SyntaxError ? ("invalid_json" as const) : defect(cause),
913
+ * );
914
+ *
915
+ * parse('{"ok":true}').unwrap(); // => { ok: true }
916
+ * parse("nope"); // => Err("invalid_json")
620
917
  * ```
621
918
  */
622
919
  declare function fromThrowable<A extends unknown[], T, R>(fn: (...args: A) => T, qualify: (cause: unknown, defect: (cause: unknown) => Defect) => R): (...args: A) => Result$1<T, Exclude<R, Defect>>;
@@ -642,12 +939,19 @@ declare function fromThrowable<A extends unknown[], T, R>(fn: (...args: A) => T,
642
939
  * @param qualify - triages a rejection `cause` into a modeled `E`, or marks it
643
940
  * unmodeled by returning `defect(cause)` (the helper passed as its second arg).
644
941
  *
942
+ * @category Interop
943
+ *
645
944
  * @example
646
945
  * ```ts
647
946
  * import { fromPromise } from "unthrown";
947
+ *
948
+ * // A rejection with a NotFoundError becomes a modeled `Err`; anything else a Defect.
648
949
  * const user = await fromPromise(fetchUser(id), (cause, defect) =>
649
950
  * cause instanceof NotFoundError ? ("not_found" as const) : defect(cause),
650
951
  * );
952
+ *
953
+ * user.unwrap(); // => the fetched user (on success)
954
+ * // when fetchUser rejects with NotFoundError: => Err("not_found")
651
955
  * ```
652
956
  */
653
957
  declare function fromPromise<T, R>(promise: Promise<T> | (() => Promise<T>), qualify: (cause: unknown, defect: (cause: unknown) => Defect) => R): AsyncResult$1<T, Exclude<R, Defect>>;
@@ -662,6 +966,17 @@ declare function fromPromise<T, R>(promise: Promise<T> | (() => Promise<T>), qua
662
966
  *
663
967
  * @typeParam T - the resolved value type.
664
968
  * @param promise - the promise, or a thunk returning one.
969
+ *
970
+ * @category Interop
971
+ *
972
+ * @example
973
+ * ```ts
974
+ * import { fromSafePromise } from "unthrown";
975
+ *
976
+ * (await fromSafePromise(Promise.resolve(3))).unwrap(); // => 3
977
+ * // a rejection becomes a Defect (never a modeled Err):
978
+ * await fromSafePromise(Promise.reject(new Error("boom"))); // => Defect(Error("boom"))
979
+ * ```
665
980
  */
666
981
  declare function fromSafePromise<T>(promise: Promise<T> | (() => Promise<T>)): AsyncResult$1<T, never>;
667
982
  /**
@@ -698,11 +1013,14 @@ type AsyncResultRecord = Record<string, AsyncResult$1<unknown, unknown>>;
698
1013
  * collapses to `Result<T[], E>` with no cast. For a **record** keyed by name,
699
1014
  * use {@link allFromDict}.
700
1015
  *
1016
+ * @category Aggregate
1017
+ *
701
1018
  * @example
702
1019
  * ```ts
703
- * import { all, Ok } from "unthrown";
704
- * all([Ok(1), Ok("a"), Ok(true)]).unwrap(); // [1, "a", true] (typed [number, string, boolean])
705
- * all([Ok(1), Ok(2)] as Result<number, never>[]).unwrap(); // number[]
1020
+ * import { all, Ok, Err } from "unthrown";
1021
+ *
1022
+ * all([Ok(1), Ok("a"), Ok(true)]).unwrap(); // => [1, "a", true] (typed [number, string, boolean])
1023
+ * all([Ok(1), Err("e"), Ok(3)]); // => Err("e") (short-circuits on the first Err)
706
1024
  * ```
707
1025
  */
708
1026
  declare function all<Rs extends readonly Result$1<unknown, unknown>[]>(results: readonly [...Rs]): Result$1<AllOk<Rs, { [K in keyof Rs]: OkOf<Rs[K]> }>, ErrOf<Rs[number]>>;
@@ -716,10 +1034,14 @@ declare function all<Rs extends readonly Result$1<unknown, unknown>[]>(results:
716
1034
  * Same folding rules as {@link all}: first `Err` short-circuits, any `Defect`
717
1035
  * dominates. This is **not** error accumulation.
718
1036
  *
1037
+ * @category Aggregate
1038
+ *
719
1039
  * @example
720
1040
  * ```ts
721
- * import { allFromDict, Ok } from "unthrown";
722
- * allFromDict({ id: Ok(1), name: Ok("ada") }).unwrap(); // { id: 1, name: "ada" }
1041
+ * import { allFromDict, Ok, Err } from "unthrown";
1042
+ *
1043
+ * allFromDict({ id: Ok(1), name: Ok("ada") }).unwrap(); // => { id: 1, name: "ada" }
1044
+ * allFromDict({ id: Ok(1), name: Err("missing") }); // => Err("missing")
723
1045
  * ```
724
1046
  */
725
1047
  declare function allFromDict<R extends ResultRecord>(results: R): Result$1<{ [K in keyof R]: OkOf<R[K]> }, ErrOf<R[keyof R]>>;
@@ -733,10 +1055,14 @@ declare function allFromDict<R extends ResultRecord>(results: R): Result$1<{ [K
733
1055
  * short-circuits, any `Defect` dominates. As ever, the returned `AsyncResult`'s
734
1056
  * internal promise never rejects. For a **record**, use {@link allFromDictAsync}.
735
1057
  *
1058
+ * @category Aggregate
1059
+ *
736
1060
  * @example
737
1061
  * ```ts
738
1062
  * import { allAsync, fromSafePromise } from "unthrown";
739
- * await allAsync([fromSafePromise(a()), fromSafePromise(b())]);
1063
+ *
1064
+ * const both = allAsync([fromSafePromise(Promise.resolve(1)), fromSafePromise(Promise.resolve(2))]);
1065
+ * (await both).unwrap(); // => [1, 2]
740
1066
  * ```
741
1067
  */
742
1068
  declare function allAsync<Rs extends readonly AsyncResult$1<unknown, unknown>[]>(results: readonly [...Rs]): AsyncResult$1<AllOk<Rs, { [K in keyof Rs]: AsyncOkOf<Rs[K]> }>, AsyncErrOf<Rs[number]>>;
@@ -748,10 +1074,17 @@ declare function allAsync<Rs extends readonly AsyncResult$1<unknown, unknown>[]>
748
1074
  * Resolved concurrently (order preserved), folded with the {@link all} rules,
749
1075
  * and the internal promise never rejects.
750
1076
  *
1077
+ * @category Aggregate
1078
+ *
751
1079
  * @example
752
1080
  * ```ts
753
1081
  * import { allFromDictAsync, fromSafePromise } from "unthrown";
754
- * await allFromDictAsync({ a: fromSafePromise(a()), b: fromSafePromise(b()) });
1082
+ *
1083
+ * const both = allFromDictAsync({
1084
+ * a: fromSafePromise(Promise.resolve(1)),
1085
+ * b: fromSafePromise(Promise.resolve("x")),
1086
+ * });
1087
+ * (await both).unwrap(); // => { a: 1, b: "x" }
755
1088
  * ```
756
1089
  */
757
1090
  declare function allFromDictAsync<R extends AsyncResultRecord>(results: R): AsyncResult$1<{ [K in keyof R]: AsyncOkOf<R[K]> }, AsyncErrOf<R[keyof R]>>;
@@ -774,10 +1107,12 @@ declare function allFromDictAsync<R extends AsyncResultRecord>(results: R): Asyn
774
1107
  * (`AsyncResult.fromPromise`, `AsyncResult.all`, …), grouped by what they
775
1108
  * return — a static lives in exactly one namespace.
776
1109
  *
1110
+ * @category Facade
1111
+ *
777
1112
  * @example
778
1113
  * ```ts
779
1114
  * import { Result } from "unthrown";
780
- * Result.Ok(1).flatMap((n) => Result.Ok(n + 1)).unwrap(); // 2
1115
+ * Result.Ok(1).flatMap((n) => Result.Ok(n + 1)).unwrap(); // => 2
781
1116
  * ```
782
1117
  */
783
1118
  declare const Result: {
@@ -793,6 +1128,20 @@ declare const Result: {
793
1128
  readonly isDefect: typeof isDefect;
794
1129
  readonly isResult: typeof isResult;
795
1130
  };
1131
+ /**
1132
+ * `Result<T, E>` — the core discriminated union. Shares its name with the
1133
+ * {@link Result | companion object} above (the value and type are one name); this
1134
+ * is the type half.
1135
+ *
1136
+ * @remarks
1137
+ * A `Result` is a discriminated union, so TypeDoc can't list its methods on this
1138
+ * alias. Its fluent combinators (`map`, `flatMap`, `match`, `unwrap`, …) are
1139
+ * documented one per entry on {@link ResultMethods} — the shared method surface
1140
+ * every variant carries. For "which one do I reach for?", see the
1141
+ * [Choosing a combinator](/guide/choosing-a-combinator) guide.
1142
+ *
1143
+ * @category Facade
1144
+ */
796
1145
  type Result<T, E> = Result$1<T, E>;
797
1146
  /**
798
1147
  * Companion object grouping the **`AsyncResult`-producing** entry points under
@@ -809,10 +1158,13 @@ type Result<T, E> = Result$1<T, E>;
809
1158
  * {@link Result}, the free functions remain the primary, tree-shakeable API; the
810
1159
  * value `AsyncResult` and the type {@link AsyncResult} share one name.
811
1160
  *
1161
+ * @category Facade
1162
+ *
812
1163
  * @example
813
1164
  * ```ts
814
1165
  * import { AsyncResult } from "unthrown";
815
1166
  * const user = await AsyncResult.fromPromise(fetchUser(id), (c, defect) => defect(c));
1167
+ * user.unwrap(); // => the fetched user (on success)
816
1168
  * ```
817
1169
  */
818
1170
  declare const AsyncResult: {
@@ -821,6 +1173,19 @@ declare const AsyncResult: {
821
1173
  readonly all: typeof allAsync;
822
1174
  readonly allFromDict: typeof allFromDictAsync;
823
1175
  };
1176
+ /**
1177
+ * `AsyncResult<T, E>` — the async counterpart of {@link Result}. Shares its name
1178
+ * with the {@link AsyncResult | companion object} above (value and type are one
1179
+ * name); this is the type half.
1180
+ *
1181
+ * @remarks
1182
+ * `AsyncResult` carries the async fluent surface; its combinators (`map`,
1183
+ * `flatMap`, `match`, `unwrap`, …) are documented one per entry — with their
1184
+ * async signatures — on {@link AsyncResultMethods}. For "which one do I reach
1185
+ * for?", see the [Choosing a combinator](/guide/choosing-a-combinator) guide.
1186
+ *
1187
+ * @category Facade
1188
+ */
824
1189
  type AsyncResult<T, E> = AsyncResult$1<T, E>;
825
1190
  //#endregion
826
1191
  //#region src/tagged.d.ts
@@ -831,8 +1196,10 @@ type Props = Record<string, unknown>;
831
1196
  *
832
1197
  * @typeParam Tag - the string literal discriminant.
833
1198
  * @typeParam A - the payload object type.
1199
+ *
1200
+ * @category Types
834
1201
  */
835
- type TaggedErrorInstance<Tag extends string, A extends Props> = Error & Readonly<A> & {
1202
+ type TaggedErrorInstance<Tag extends string, A extends Props> = Error & Readonly<Omit<A, "name">> & {
836
1203
  readonly _tag: Tag;
837
1204
  };
838
1205
  /**
@@ -841,12 +1208,19 @@ type TaggedErrorInstance<Tag extends string, A extends Props> = Error & Readonly
841
1208
  *
842
1209
  * @remarks
843
1210
  * When the payload is empty, the constructor takes **no** arguments (the
844
- * `keyof A extends never ? void : A` trick); otherwise it takes the payload.
1211
+ * `keyof A extends never ? void : A` trick); otherwise it takes the payload. A
1212
+ * `name` key is **rejected** (`name?: never`) because it is reserved for the
1213
+ * display label — mirroring how {@link TaggedErrorInstance} excludes it — so the
1214
+ * reservation is enforced at the call site, not just ignored at runtime.
845
1215
  *
846
1216
  * @typeParam Tag - the string literal discriminant.
1217
+ *
1218
+ * @category Types
847
1219
  */
848
1220
  type TaggedErrorConstructor<Tag extends string> = {
849
- new <A extends Props = {}>(args: keyof A extends never ? void : A): TaggedErrorInstance<Tag, A>;
1221
+ new <A extends Props = {}>(args: keyof A extends never ? void : A & {
1222
+ readonly name?: never;
1223
+ }): TaggedErrorInstance<Tag, A>;
850
1224
  };
851
1225
  /**
852
1226
  * Build a base class for a tagged error — a class extending `Error` with a
@@ -856,7 +1230,10 @@ type TaggedErrorConstructor<Tag extends string> = {
856
1230
  * Extend the returned class to declare a concrete error. Supply the payload with
857
1231
  * an instantiation expression; omit it for a payload-less error. A `message`
858
1232
  * field in the payload is forwarded to `Error`. The `_tag` always reflects
859
- * `tag` and cannot be overridden by the payload.
1233
+ * `tag` and cannot be overridden by the payload. `name` is likewise reserved —
1234
+ * it is the display label (set it with `options.name`); a payload `name` is
1235
+ * rejected at compile time (and excluded from the instance type), so it can't
1236
+ * shadow `Error.name`.
860
1237
  *
861
1238
  * `_tag` is the discriminant used by {@link matchTags}; `Error.name` is the
862
1239
  * human-facing label in stack traces and logs. By default they coincide, but
@@ -879,13 +1256,15 @@ type TaggedErrorConstructor<Tag extends string> = {
879
1256
  * @param options - optional overrides. `options.name` sets `Error.name`
880
1257
  * independently of `tag` (defaults to `tag`).
881
1258
  *
1259
+ * @category Tagged errors
1260
+ *
882
1261
  * @example
883
1262
  * ```ts
884
1263
  * class NotFound extends TaggedError("NotFound") {}
885
1264
  * class HttpError extends TaggedError("HttpError")<{ status: number }> {}
886
1265
  *
887
- * new NotFound()._tag; // "NotFound"
888
- * new HttpError({ status: 500 }).status; // 500
1266
+ * new NotFound()._tag; // => "NotFound"
1267
+ * new HttpError({ status: 500 }).status; // => 500
889
1268
  * ```
890
1269
  */
891
1270
  declare function TaggedError<Tag extends string>(tag: Tag, options?: {
@@ -899,6 +1278,8 @@ declare function TaggedError<Tag extends string>(tag: Tag, options?: {
899
1278
  * @typeParam T - the success value type.
900
1279
  * @typeParam E - the tagged error union.
901
1280
  * @typeParam R - the folded result type.
1281
+ *
1282
+ * @category Types
902
1283
  */
903
1284
  type TagHandlers<T, E extends {
904
1285
  _tag: string;
@@ -908,6 +1289,14 @@ type TagHandlers<T, E extends {
908
1289
  } & { [K in E["_tag"]]: (error: Extract<E, {
909
1290
  _tag: K;
910
1291
  }>) => R };
1292
+ /**
1293
+ * The channel-handler names are reserved: an error tag named `"Ok"` or
1294
+ * `"Defect"` would collide with them inside {@link TagHandlers}, so
1295
+ * {@link matchTags} rejects such unions at the call site.
1296
+ *
1297
+ * @internal
1298
+ */
1299
+ type ReservedTagError = 'unthrown: error tags "Ok" and "Defect" are reserved by matchTags — rename the colliding tag (TaggedError\'s options.name can keep the display name)';
911
1300
  /**
912
1301
  * Exhaustively fold a {@link Result} (or {@link AsyncResult}) whose error type is
913
1302
  * a tagged union, dispatching each error to the handler matching its `_tag`.
@@ -916,7 +1305,10 @@ type TagHandlers<T, E extends {
916
1305
  * The `handlers` object must provide `Ok`, `Defect`, and exactly one function
917
1306
  * per error tag; each tag's handler receives the narrowed error variant. A
918
1307
  * missing tag is a compile error. For an `AsyncResult`, the fold resolves to a
919
- * `Promise<R>`.
1308
+ * `Promise<R>`. At runtime, an error whose `_tag` has no handler (possible only
1309
+ * outside the typed contract) is routed to the `Defect` handler — an unmodeled
1310
+ * tag is an unmodeled failure. Tags named `"Ok"` or `"Defect"` are rejected at
1311
+ * compile time.
920
1312
  *
921
1313
  * @typeParam T - the success value type.
922
1314
  * @typeParam E - the tagged error union (`E extends { _tag: string }`).
@@ -924,26 +1316,33 @@ type TagHandlers<T, E extends {
924
1316
  * @param result - the result to fold.
925
1317
  * @param handlers - one branch per channel/tag.
926
1318
  *
1319
+ * @category Tagged errors
1320
+ *
927
1321
  * @example
928
1322
  * ```ts
1323
+ * import { Ok, Err, matchTags, TaggedError, type Result } from "unthrown";
1324
+ *
929
1325
  * class NotFound extends TaggedError("NotFound") {}
930
1326
  * class Forbidden extends TaggedError("Forbidden")<{ user: string }> {}
931
1327
  *
932
- * declare const r: Result<number, NotFound | Forbidden>;
933
- * matchTags(r, {
934
- * Ok: (n) => `got ${n}`,
935
- * Defect: (cause) => `bug: ${String(cause)}`,
936
- * NotFound: () => "404",
937
- * Forbidden: (e) => `403 for ${e.user}`,
938
- * });
1328
+ * const fold = (r: Result<number, NotFound | Forbidden>) =>
1329
+ * matchTags(r, {
1330
+ * Ok: (n) => `got ${n}`,
1331
+ * Defect: (cause) => `bug: ${String(cause)}`,
1332
+ * NotFound: () => "404",
1333
+ * Forbidden: (e) => `403 for ${e.user}`,
1334
+ * });
1335
+ *
1336
+ * fold(Ok(1)); // => "got 1"
1337
+ * fold(Err(new Forbidden({ user: "ada" }))); // => "403 for ada"
939
1338
  * ```
940
1339
  */
941
1340
  declare function matchTags<T, E extends {
942
1341
  _tag: string;
943
- }, R>(result: Result$1<T, E>, handlers: TagHandlers<T, E, R>): R;
1342
+ }, R>(result: Result$1<T, E>, handlers: TagHandlers<T, E, R> & ([Extract<E["_tag"], "Ok" | "Defect">] extends [never] ? unknown : ReservedTagError)): R;
944
1343
  declare function matchTags<T, E extends {
945
1344
  _tag: string;
946
- }, R>(result: AsyncResult$1<T, E>, handlers: TagHandlers<T, E, R>): Promise<R>;
1345
+ }, R>(result: AsyncResult$1<T, E>, handlers: TagHandlers<T, E, R> & ([Extract<E["_tag"], "Ok" | "Defect">] extends [never] ? unknown : ReservedTagError)): Promise<R>;
947
1346
  //#endregion
948
- export { type AsyncErrOf, type AsyncOkOf, AsyncResult, type Awaitable, type DefectView, Do, Err, type ErrOf, type ErrView, Ok, type OkOf, type OkView, Result, type TagHandlers, TaggedError, type TaggedErrorConstructor, type TaggedErrorInstance, UnwrapError, all, allAsync, allFromDict, allFromDictAsync, fromNullable, fromPromise, fromSafePromise, fromThrowable, isDefect, isErr, isOk, isResult, matchTags };
1347
+ export { type AsyncErrOf, type AsyncOkOf, AsyncResult, type AsyncResultMethods, type Awaitable, type DefectView, Do, Err, type ErrOf, type ErrView, type NotThenable, Ok, type OkOf, type OkView, Result, type ResultMethods, type TagHandlers, TaggedError, type TaggedErrorConstructor, type TaggedErrorInstance, UnwrapError, all, allAsync, allFromDict, allFromDictAsync, fromNullable, fromPromise, fromSafePromise, fromThrowable, isDefect, isErr, isOk, isResult, matchTags };
949
1348
  //# sourceMappingURL=index.d.cts.map