unthrown 4.2.0 → 5.0.0-beta.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/README.md +5 -4
- package/dist/index.cjs +168 -129
- package/dist/index.d.cts +269 -279
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +269 -279
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +155 -128
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -4
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
import { P, match, match as match$1 } from "ts-pattern";
|
|
2
|
+
//#region src/defect.d.ts
|
|
3
|
+
declare const DEFECT: unique symbol;
|
|
4
|
+
/**
|
|
5
|
+
* The opaque marker a `qualify` function returns to triage a cause as
|
|
6
|
+
* **unexpected**.
|
|
7
|
+
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* `qualify` (passed to {@link fromPromise} / {@link fromThrowable}) returns
|
|
10
|
+
* `E | Defect`: either a modeled domain error, or a `Defect` produced by the
|
|
11
|
+
* injected `defect` helper to say "this failure is not modeled". A `Defect` is
|
|
12
|
+
* opaque — it carries the original cause for the boundary to convert into the
|
|
13
|
+
* third runtime state of a `Result`. It is **not** a public value; the only way
|
|
14
|
+
* to mint one is the `defect` helper the boundary passes to `qualify`.
|
|
15
|
+
*
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
type Defect = {
|
|
19
|
+
readonly [DEFECT]: true;
|
|
20
|
+
readonly cause: unknown;
|
|
21
|
+
};
|
|
22
|
+
//#endregion
|
|
1
23
|
//#region src/types.d.ts
|
|
2
24
|
/**
|
|
3
25
|
* Flatten an intersection into a single object literal so accumulated `bind` /
|
|
@@ -32,6 +54,49 @@ type Bound<T, K extends string, U> = Prettify<Omit<T, K> & { readonly [P in K]:
|
|
|
32
54
|
* @category Types
|
|
33
55
|
*/
|
|
34
56
|
type NotThenable<R> = [R] extends [PromiseLike<unknown>] ? "unthrown: combinator callbacks are synchronous — lift async work with fromPromise and compose with flatMap" : unknown;
|
|
57
|
+
/**
|
|
58
|
+
* The ts-pattern match builder over an error union `E`, as produced by
|
|
59
|
+
* `match(error)`. This is what an error combinator's callback receives — chain
|
|
60
|
+
* `.with(pattern, handler)` on it; the combinator itself calls `.exhaustive()`,
|
|
61
|
+
* so the callback returns the **un-terminated** builder.
|
|
62
|
+
*
|
|
63
|
+
* @remarks
|
|
64
|
+
* Named via `ReturnType<typeof match<E>>` so the internal ts-pattern `Match`
|
|
65
|
+
* type (not part of ts-pattern's public exports) never has to be imported.
|
|
66
|
+
*
|
|
67
|
+
* @typeParam E - the error union being matched.
|
|
68
|
+
* @category Types
|
|
69
|
+
*/
|
|
70
|
+
type ErrMatcher<E> = ReturnType<typeof match$1<E>>;
|
|
71
|
+
/**
|
|
72
|
+
* The shape an error-combinator callback must return: an **exhaustive**
|
|
73
|
+
* ts-pattern builder. `exhaustive` is required to be *callable* — on a builder
|
|
74
|
+
* that hasn't covered every case ts-pattern types it as a `NonExhaustiveError`
|
|
75
|
+
* (not a function), so a non-exhaustive chain fails to satisfy this and errors
|
|
76
|
+
* at the call site. `run` carries the output type.
|
|
77
|
+
*
|
|
78
|
+
* @typeParam O - the union of the branch return types (the builder's output).
|
|
79
|
+
* @internal
|
|
80
|
+
*/
|
|
81
|
+
type ExhaustiveMatch<O> = {
|
|
82
|
+
exhaustive: (...args: never[]) => unknown;
|
|
83
|
+
run: () => O;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* The output of an `ExhaustiveMatch` — the union of its branch returns.
|
|
87
|
+
*
|
|
88
|
+
* @internal
|
|
89
|
+
*/
|
|
90
|
+
type MatchOut<M> = M extends ExhaustiveMatch<infer O> ? O : never;
|
|
91
|
+
/**
|
|
92
|
+
* The outgoing modeled-error type a transforming match produces: the builder's
|
|
93
|
+
* output with the `Defect` arm **subtracted** (`Exclude<O, Defect>`, the same
|
|
94
|
+
* inference as the boundary `qualify`, Thesis #3). A branch that returns
|
|
95
|
+
* `defect(cause)` therefore contributes nothing to the modeled channel.
|
|
96
|
+
*
|
|
97
|
+
* @internal
|
|
98
|
+
*/
|
|
99
|
+
type MatchErrOut<M> = Exclude<MatchOut<M>, Defect>;
|
|
35
100
|
/**
|
|
36
101
|
* The fluent method surface every {@link Result} variant carries — the
|
|
37
102
|
* combinators (`map`, `flatMap`, `mapErr`, `match`, `get`, …), documented one
|
|
@@ -48,7 +113,7 @@ type NotThenable<R> = [R] extends [PromiseLike<unknown>] ? "unthrown: combinator
|
|
|
48
113
|
* @typeParam E - the modeled error type.
|
|
49
114
|
* @category Methods
|
|
50
115
|
*/
|
|
51
|
-
type ResultMethods<T, E> = {
|
|
116
|
+
type ResultMethods<out T, out E> = {
|
|
52
117
|
/**
|
|
53
118
|
* Transform the success value with `f`.
|
|
54
119
|
*
|
|
@@ -162,103 +227,90 @@ type ResultMethods<T, E> = {
|
|
|
162
227
|
*/
|
|
163
228
|
discard(): Result$1<void, E>;
|
|
164
229
|
/**
|
|
165
|
-
* Transform the modeled error with
|
|
166
|
-
*
|
|
167
|
-
* Runs `f` only on `Err`; `Ok` passes through and a `Defect` is **never**
|
|
168
|
-
* touched. If `f` throws, the throw becomes a `Defect`. An async callback is
|
|
169
|
-
* rejected at compile time ({@link NotThenable}).
|
|
230
|
+
* Transform the modeled error by **matching it exhaustively** with ts-pattern.
|
|
170
231
|
*
|
|
171
|
-
* @
|
|
172
|
-
*
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
*
|
|
177
|
-
*
|
|
232
|
+
* @remarks
|
|
233
|
+
* The callback receives `match(error)` (an {@link ErrMatcher}) and the
|
|
234
|
+
* injected `defect` helper. Chain `.with(pattern, handler)` and **return the
|
|
235
|
+
* un-terminated builder** — `mapErr` calls `.exhaustive()` itself, so a
|
|
236
|
+
* missing case is a compile error at the call site (there is no `.exhaustive()`
|
|
237
|
+
* to forget, and no way to slip in `.otherwise()`). The outgoing error type is
|
|
238
|
+
* the union of the branch returns with the `Defect` arm subtracted
|
|
239
|
+
* (`Exclude<O, Defect>`) — a branch returning `defect(cause)` converts that case
|
|
240
|
+
* to a `Defect` and drops it from `E`. Runs only on `Err`; `Ok` and `Defect`
|
|
241
|
+
* pass through. A branch that throws also becomes a `Defect`.
|
|
178
242
|
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
243
|
+
* `.with(P._, …)` is the deliberate uniform/catch-all (it makes the match
|
|
244
|
+
* exhaustive). Match on anything ts-pattern supports — `_tag`, `code`,
|
|
245
|
+
* structural shape, guards, or grouped patterns `.with(a, b, handler)`.
|
|
181
246
|
*
|
|
182
|
-
* @typeParam
|
|
183
|
-
* @
|
|
184
|
-
* @param f - produces a fallback `Result` from the current error.
|
|
247
|
+
* @typeParam M - the exhaustive builder the callback returns.
|
|
248
|
+
* @param f - builds the match over the error (returns the un-terminated builder).
|
|
185
249
|
*/
|
|
186
|
-
|
|
250
|
+
mapErr<M extends ExhaustiveMatch<unknown>>(f: (matcher: ErrMatcher<E>, defect: (cause: unknown) => Defect) => M): Result$1<T, MatchErrOut<M>>;
|
|
187
251
|
/**
|
|
188
|
-
* Sequence from an `Err` by producing another `Result
|
|
252
|
+
* Sequence from an `Err` by producing another `Result` — the error-channel
|
|
253
|
+
* mirror of {@link ResultMethods.flatMap | flatMap}, **matching the error
|
|
254
|
+
* exhaustively** ({@link ErrMatcher}; the combinator calls `.exhaustive()`).
|
|
189
255
|
*
|
|
190
|
-
*
|
|
191
|
-
* `
|
|
192
|
-
*
|
|
256
|
+
* Each branch returns a `Result`; the outgoing channels are the unions of the
|
|
257
|
+
* branch-returned `Result`s' channels. A branch may return `defect(cause)`.
|
|
258
|
+
* Runs only on `Err`; `Ok` and `Defect` pass through.
|
|
193
259
|
*
|
|
194
|
-
* @typeParam
|
|
195
|
-
* @
|
|
196
|
-
* @param f - produces a fallback `Result` from the current error.
|
|
260
|
+
* @typeParam M - the exhaustive builder the callback returns.
|
|
261
|
+
* @param f - builds the match; each branch produces a fallback `Result`.
|
|
197
262
|
*/
|
|
198
|
-
|
|
263
|
+
flatMapErr<M extends ExhaustiveMatch<Result$1<unknown, unknown> | Defect>>(f: (matcher: ErrMatcher<E>, defect: (cause: unknown) => Defect) => M): Result$1<T | OkOf<MatchOut<M>>, ErrOf<MatchOut<M>>>;
|
|
199
264
|
/**
|
|
200
265
|
* Recover from an `Err` by producing a success value, emptying the error
|
|
201
|
-
* channel
|
|
266
|
+
* channel — **matching the error exhaustively** ({@link ErrMatcher}). Pairs
|
|
267
|
+
* with {@link ResultMethods.recoverDefect | recoverDefect}.
|
|
202
268
|
*
|
|
203
269
|
* @remarks
|
|
204
270
|
* The result type is `Result<T | U, never>`, but `never` describes only the
|
|
205
|
-
* **error** channel — a `Defect` can still be present at runtime
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
* rejected at compile time ({@link NotThenable}).
|
|
209
|
-
*
|
|
210
|
-
* @typeParam U - the recovered success type.
|
|
211
|
-
* @param f - produces a success value from the current error.
|
|
212
|
-
*/
|
|
213
|
-
recoverErr<U>(f: (error: E) => U & NotThenable<U>): Result$1<T | U, never>;
|
|
214
|
-
/**
|
|
215
|
-
* Recover from an `Err` by producing a success value.
|
|
216
|
-
*
|
|
217
|
-
* @deprecated Renamed to {@link ResultMethods.recoverErr | recoverErr} — it now
|
|
218
|
-
* pairs with {@link ResultMethods.recoverDefect | recoverDefect} and follows the
|
|
219
|
-
* `…Err` convention. This alias will be removed in a future major.
|
|
271
|
+
* **error** channel — a `Defect` can still be present at runtime. A branch may
|
|
272
|
+
* return `defect(cause)` (which stays a `Defect`, not a recovery). Runs only on
|
|
273
|
+
* `Err`; `Ok` and `Defect` pass through.
|
|
220
274
|
*
|
|
221
|
-
* @typeParam
|
|
222
|
-
* @param f - produces a success value
|
|
275
|
+
* @typeParam M - the exhaustive builder the callback returns.
|
|
276
|
+
* @param f - builds the match; each branch produces a success value.
|
|
223
277
|
*/
|
|
224
|
-
|
|
278
|
+
recoverErr<M extends ExhaustiveMatch<unknown>>(f: (matcher: ErrMatcher<E>, defect: (cause: unknown) => Defect) => M): Result$1<T | MatchErrOut<M>, never>;
|
|
225
279
|
/**
|
|
226
|
-
* Run a side effect on the error
|
|
227
|
-
*
|
|
228
|
-
* Runs only on `Err`. If `f` throws, the result is a `Defect` whose cause is
|
|
229
|
-
* an `AggregateError` of `[thrown, original failure]` — observing a failure
|
|
230
|
-
* never destroys it. An async callback is rejected at compile time
|
|
231
|
-
* ({@link NotThenable}).
|
|
280
|
+
* Run a side effect on the error — **matched exhaustively** ({@link ErrMatcher})
|
|
281
|
+
* — and pass the `Result` through unchanged.
|
|
232
282
|
*
|
|
233
283
|
* @remarks
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
284
|
+
* The callback builds a match whose branches run side effects; their return
|
|
285
|
+
* values are ignored and the original `Err` flows through. Exhaustive like the
|
|
286
|
+
* transformers (use `.with(P._, …)` for a catch-all). If a branch throws, the
|
|
287
|
+
* result is a `Defect` whose cause is an `AggregateError` of `[thrown, original
|
|
288
|
+
* failure]` — observing a failure never destroys it. A failable
|
|
289
|
+
* `Result`-returning effect belongs in
|
|
290
|
+
* {@link ResultMethods.flatTapErr | flatTapErr}.
|
|
240
291
|
*
|
|
241
|
-
* @param f - the
|
|
292
|
+
* @param f - builds the match; branch returns are ignored.
|
|
242
293
|
*/
|
|
243
|
-
tapErr
|
|
294
|
+
tapErr(f: (matcher: ErrMatcher<E>, defect: (cause: unknown) => Defect) => ExhaustiveMatch<unknown>): Result$1<T, E>;
|
|
244
295
|
/**
|
|
245
296
|
* Run a **failable** side effect on the error, keeping the original error but
|
|
246
|
-
* threading the effect's own error
|
|
297
|
+
* threading the effect's own error — **matched exhaustively**
|
|
298
|
+
* ({@link ErrMatcher}).
|
|
247
299
|
*
|
|
248
300
|
* @remarks
|
|
249
|
-
* The error-channel mirror of {@link ResultMethods.flatTap | flatTap}:
|
|
250
|
-
* returns a `Result
|
|
251
|
-
* `Ok` the original `Err` flows through
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
301
|
+
* The error-channel mirror of {@link ResultMethods.flatTap | flatTap}: each
|
|
302
|
+
* branch returns a `Result` whose **success value is discarded** — on the
|
|
303
|
+
* effect's `Ok` the original `Err` flows through, while an `Err`/`Defect` from a
|
|
304
|
+
* branch short-circuits and threads its error. Note the asymmetry with a
|
|
305
|
+
* *throw*: a branch that **returns** a `Defect` **replaces** the original `Err`
|
|
306
|
+
* (Defect-dominance, the short-circuit rule — it is not aggregated), whereas a
|
|
307
|
+
* branch that **throws** produces a `Defect` aggregating `[thrown, original
|
|
308
|
+
* failure]` (observing a failure by throwing never destroys it).
|
|
257
309
|
*
|
|
258
|
-
* @typeParam
|
|
259
|
-
* @param f - the failable
|
|
310
|
+
* @typeParam M - the exhaustive builder the callback returns.
|
|
311
|
+
* @param f - builds the match; each branch is a failable effect (its `Ok` is ignored).
|
|
260
312
|
*/
|
|
261
|
-
flatTapErr<E2>(f: (
|
|
313
|
+
flatTapErr<E2>(f: (matcher: ErrMatcher<E>, defect: (cause: unknown) => Defect) => ExhaustiveMatch<Result$1<unknown, E2>>): Result$1<T, E | E2>;
|
|
262
314
|
/**
|
|
263
315
|
* Recover from a `Defect` — the **only** combinator that can touch one.
|
|
264
316
|
*
|
|
@@ -284,23 +336,59 @@ type ResultMethods<T, E> = {
|
|
|
284
336
|
*/
|
|
285
337
|
tapDefect<R>(f: (cause: unknown) => R & NotThenable<R>): Result$1<T, E>;
|
|
286
338
|
/**
|
|
287
|
-
*
|
|
339
|
+
* Run a side effect on **any failure** — `Err` or `Defect` — and pass the
|
|
340
|
+
* `Result` through unchanged. The one cross-channel observer, for the shared
|
|
341
|
+
* "it went KO" concern (logging, metrics, rollback) that would otherwise be
|
|
342
|
+
* duplicated across {@link ResultMethods.tapErr | tapErr} and
|
|
343
|
+
* {@link ResultMethods.tapDefect | tapDefect}.
|
|
344
|
+
*
|
|
345
|
+
* @remarks
|
|
346
|
+
* `f` receives the narrowed **failure variant** ({@link FailureView}), not a
|
|
347
|
+
* payload — the payload union `E | unknown` would collapse to `unknown` and
|
|
348
|
+
* lose `E`'s typing. Branch on `failure.tag` to reach the typed payload
|
|
349
|
+
* (`"Err"` → `failure.error: E`, `"Defect"` → `failure.cause: unknown`), or
|
|
350
|
+
* treat it opaquely for a shared logger. Runs on `Err` and `Defect`; `Ok`
|
|
351
|
+
* passes through. It **observes without consuming**: the failure flows on
|
|
352
|
+
* unchanged — to also recover, use
|
|
353
|
+
* {@link ResultMethods.recoverErr | recoverErr} /
|
|
354
|
+
* {@link ResultMethods.recoverDefect | recoverDefect} (deliberately separate
|
|
355
|
+
* acts) or {@link ResultMethods.match | match} at the edge. If `f` throws, the
|
|
356
|
+
* result is a `Defect` whose cause is an `AggregateError` of `[thrown,
|
|
357
|
+
* original failure]` — observing a failure never destroys it. An async
|
|
358
|
+
* callback is rejected at compile time ({@link NotThenable}).
|
|
359
|
+
*
|
|
360
|
+
* @param f - the side effect over the failure variant (its return value is ignored).
|
|
361
|
+
*/
|
|
362
|
+
tapFailure<R>(f: (failure: FailureView<E, T>) => R & NotThenable<R>): Result$1<T, E>;
|
|
363
|
+
/**
|
|
364
|
+
* Exhaustively fold all three runtime states into a single value.
|
|
288
365
|
*
|
|
289
366
|
* @remarks
|
|
290
367
|
* Exactly one handler runs. Together with the throw-to-Defect guarantee, this
|
|
291
368
|
* is typically the single place a pipeline is handled at the edge — mapping
|
|
292
369
|
* `Ok`/`Err`/`Defect` to (for example) 2xx / 4xx / 5xx with no `try`/`catch`.
|
|
293
|
-
* (For richer matching, a `Result` is also a discriminated union — branch on
|
|
294
|
-
* its `tag` property, e.g. with `ts-pattern`.)
|
|
295
370
|
*
|
|
296
|
-
*
|
|
297
|
-
* @
|
|
371
|
+
* The `err` handler does not take a single blanket callback: it receives
|
|
372
|
+
* `match(error)` (an {@link ErrMatcher}) and **matches the error exhaustively**,
|
|
373
|
+
* exactly like the error combinators. Chain `.with(pattern, handler)` and
|
|
374
|
+
* **return the un-terminated builder** — `match` calls `.exhaustive()` itself,
|
|
375
|
+
* so a missing case is a compile error at the call site (no `.exhaustive()` to
|
|
376
|
+
* forget). Use `.with(P._, …)` for a uniform catch-all. Unlike the combinators
|
|
377
|
+
* the branches receive **no `defect` helper** — `match` is total elimination
|
|
378
|
+
* to a value, with no `Defect` output channel; the `defect` case handles a
|
|
379
|
+
* `Result` that already carries one. (A `Result` is also a discriminated
|
|
380
|
+
* union — for richer whole-`Result` matching, `match(result).with(…)`.)
|
|
381
|
+
*
|
|
382
|
+
* @typeParam ROk - the `ok` handler return type.
|
|
383
|
+
* @typeParam RDefect - the `defect` handler return type.
|
|
384
|
+
* @typeParam M - the exhaustive builder the `err` handler returns.
|
|
385
|
+
* @param cases - the `ok`/`defect` handlers plus the `err` matcher builder.
|
|
298
386
|
*/
|
|
299
|
-
match<
|
|
300
|
-
ok: (value: T) =>
|
|
301
|
-
err: (
|
|
302
|
-
defect: (cause: unknown) =>
|
|
303
|
-
}):
|
|
387
|
+
match<ROk, RDefect, M extends ExhaustiveMatch<unknown>>(cases: {
|
|
388
|
+
ok: (value: T) => ROk;
|
|
389
|
+
err: (matcher: ErrMatcher<E>) => M;
|
|
390
|
+
defect: (cause: unknown) => RDefect;
|
|
391
|
+
}): ROk | RDefect | MatchOut<M>;
|
|
304
392
|
/**
|
|
305
393
|
* Extract the success value.
|
|
306
394
|
*
|
|
@@ -318,15 +406,6 @@ type ResultMethods<T, E> = {
|
|
|
318
406
|
* @returns the `Ok` value.
|
|
319
407
|
*/
|
|
320
408
|
get(this: Result$1<T, never>): T;
|
|
321
|
-
/**
|
|
322
|
-
* Extract the success value.
|
|
323
|
-
*
|
|
324
|
-
* @deprecated Renamed to {@link ResultMethods.get | get}, unifying the extractor
|
|
325
|
-
* family under `get…`. This alias will be removed in a future major.
|
|
326
|
-
*
|
|
327
|
-
* @returns the `Ok` value.
|
|
328
|
-
*/
|
|
329
|
-
unwrap(this: Result$1<T, never>): T;
|
|
330
409
|
/**
|
|
331
410
|
* Extract the modeled error.
|
|
332
411
|
*
|
|
@@ -341,15 +420,6 @@ type ResultMethods<T, E> = {
|
|
|
341
420
|
* @returns the `Err` value.
|
|
342
421
|
*/
|
|
343
422
|
getErr(this: Result$1<never, E>): E;
|
|
344
|
-
/**
|
|
345
|
-
* Extract the modeled error.
|
|
346
|
-
*
|
|
347
|
-
* @deprecated Renamed to {@link ResultMethods.getErr | getErr}, unifying the
|
|
348
|
-
* extractor family under `get…`. This alias will be removed in a future major.
|
|
349
|
-
*
|
|
350
|
-
* @returns the `Err` value.
|
|
351
|
-
*/
|
|
352
|
-
unwrapErr(this: Result$1<never, E>): E;
|
|
353
423
|
/**
|
|
354
424
|
* The success value, or `fallback` on `Err`.
|
|
355
425
|
*
|
|
@@ -359,17 +429,6 @@ type ResultMethods<T, E> = {
|
|
|
359
429
|
* it is never silently replaced.
|
|
360
430
|
*/
|
|
361
431
|
getOr<U>(fallback: U): T | U;
|
|
362
|
-
/**
|
|
363
|
-
* The success value, or `fallback` on `Err`.
|
|
364
|
-
*
|
|
365
|
-
* @deprecated Renamed to {@link ResultMethods.getOr | getOr}, unifying the
|
|
366
|
-
* extractor family under `get…`. This alias will be removed in a future major.
|
|
367
|
-
*
|
|
368
|
-
* @typeParam U - the fallback type (may differ from `T`; the return widens to `T | U`).
|
|
369
|
-
* @param fallback - returned when the result is an `Err`.
|
|
370
|
-
* @throws Re-throws on a `Defect`.
|
|
371
|
-
*/
|
|
372
|
-
unwrapOr<U>(fallback: U): T | U;
|
|
373
432
|
/**
|
|
374
433
|
* The success value, or `f(error)` on `Err`.
|
|
375
434
|
*
|
|
@@ -378,17 +437,6 @@ type ResultMethods<T, E> = {
|
|
|
378
437
|
* @throws Re-throws on a `Defect`.
|
|
379
438
|
*/
|
|
380
439
|
getOrElse<U>(f: (error: E) => U): T | U;
|
|
381
|
-
/**
|
|
382
|
-
* The success value, or `f(error)` on `Err`.
|
|
383
|
-
*
|
|
384
|
-
* @deprecated Renamed to {@link ResultMethods.getOrElse | getOrElse}, unifying
|
|
385
|
-
* the extractor family under `get…`. This alias will be removed in a future major.
|
|
386
|
-
*
|
|
387
|
-
* @typeParam U - the fallback type (may differ from `T`; the return widens to `T | U`).
|
|
388
|
-
* @param f - lazily computes the fallback from the error.
|
|
389
|
-
* @throws Re-throws on a `Defect`.
|
|
390
|
-
*/
|
|
391
|
-
unwrapOrElse<U>(f: (error: E) => U): T | U;
|
|
392
440
|
/**
|
|
393
441
|
* The success value, or `null` on `Err`.
|
|
394
442
|
*
|
|
@@ -405,20 +453,26 @@ type ResultMethods<T, E> = {
|
|
|
405
453
|
* The success value, or **throw** the modeled error on `Err`.
|
|
406
454
|
*
|
|
407
455
|
* @remarks
|
|
408
|
-
* A deliberate escape hatch off the errors-as-values model
|
|
409
|
-
*
|
|
410
|
-
*
|
|
411
|
-
*
|
|
412
|
-
*
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
*
|
|
456
|
+
* A deliberate escape hatch off the errors-as-values model — it **throws the
|
|
457
|
+
* `Err` value as-is** at the call site. Its purpose is to move a literal
|
|
458
|
+
* `throw` behind a method, so a `no-throw` lint rule can ban raw throws while
|
|
459
|
+
* this one sanctioned extraction remains — _not_ to replace principled
|
|
460
|
+
* handling. When you can keep the error a value, prefer
|
|
461
|
+
* {@link ResultMethods.match | match} / {@link ResultMethods.recoverErr | recoverErr} /
|
|
462
|
+
* {@link ResultMethods.flatMapErr | flatMapErr}.
|
|
463
|
+
*
|
|
464
|
+
* Type-gated as the **complement** of {@link ResultMethods.get | get}: it
|
|
465
|
+
* compiles only when the error channel is **non-empty** (`E` is not `never`) —
|
|
466
|
+
* there must be a modeled error for it to throw. On a `Result<T, never>` there
|
|
467
|
+
* is nothing to throw, so `getOrThrow` does not compile; use `get()` (which
|
|
468
|
+
* gates the other way). Together they partition extraction by the error
|
|
469
|
+
* channel's state, with no overlap.
|
|
416
470
|
*
|
|
417
471
|
* @returns the `Ok` value.
|
|
418
472
|
* @throws the modeled `error` on `Err`; re-throws the original `cause` on a
|
|
419
473
|
* `Defect` (a panic, like the rest of the `getOr…` family).
|
|
420
474
|
*/
|
|
421
|
-
getOrThrow(): T;
|
|
475
|
+
getOrThrow(this: [E] extends [never] ? never : Result$1<T, E>): T;
|
|
422
476
|
/** Whether this result is `Ok` — narrows `this` to its {@link OkView} on `true`. */
|
|
423
477
|
isOk(): this is OkView<T, E>;
|
|
424
478
|
/** Whether this result is `Err` — narrows `this` to its {@link ErrView} on `true`. */
|
|
@@ -484,6 +538,30 @@ type DefectView<T = never, E = never> = ResultMethods<T, E> & {
|
|
|
484
538
|
readonly tag: "Defect";
|
|
485
539
|
readonly cause: unknown;
|
|
486
540
|
};
|
|
541
|
+
/**
|
|
542
|
+
* A failure variant of a {@link Result}: an {@link ErrView} **or** a
|
|
543
|
+
* {@link DefectView}. This is what a `tapFailure` callback receives — the
|
|
544
|
+
* discriminated variant rather than a payload, because the payload union
|
|
545
|
+
* `E | unknown` would collapse to `unknown` and lose `E`'s typing. Branch on
|
|
546
|
+
* `tag` to narrow (`"Err"` → `.error: E`, `"Defect"` → `.cause: unknown`).
|
|
547
|
+
*
|
|
548
|
+
* @remarks
|
|
549
|
+
* Like {@link ErrView}, the error type comes **first** (`FailureView<E, T>`) —
|
|
550
|
+
* the error is the payload you are usually here for, and a shared observer can
|
|
551
|
+
* spell just `FailureView<MyError>`.
|
|
552
|
+
*
|
|
553
|
+
* @example
|
|
554
|
+
* ```ts
|
|
555
|
+
* const logKo = (f: FailureView<ApiError>) =>
|
|
556
|
+
* f.tag === "Err" ? logger.warn(f.error) : logger.error(f.cause);
|
|
557
|
+
* result.tapFailure(logKo);
|
|
558
|
+
* ```
|
|
559
|
+
*
|
|
560
|
+
* @typeParam E - the modeled error type.
|
|
561
|
+
* @typeParam T - the success value type (phantom here; a failure carries none).
|
|
562
|
+
* @category Types
|
|
563
|
+
*/
|
|
564
|
+
type FailureView<E, T = never> = ErrView<E, T> | DefectView<T, E>;
|
|
487
565
|
/**
|
|
488
566
|
* The core type of the library: a computation that has either succeeded with a
|
|
489
567
|
* value of type `T` or failed with a *modeled* error of type `E`.
|
|
@@ -540,7 +618,7 @@ type Result$1<T, E> = OkView<T, E> | ErrView<E, T> | DefectView<T, E>;
|
|
|
540
618
|
*
|
|
541
619
|
* @category Types
|
|
542
620
|
*/
|
|
543
|
-
type Awaitable<T> = {
|
|
621
|
+
type Awaitable<out T> = {
|
|
544
622
|
then<R = T>(onfulfilled?: ((value: T) => R | PromiseLike<R>) | null): PromiseLike<R>;
|
|
545
623
|
};
|
|
546
624
|
/**
|
|
@@ -563,7 +641,7 @@ type Awaitable<T> = {
|
|
|
563
641
|
* @typeParam E - the modeled error type.
|
|
564
642
|
* @category Methods
|
|
565
643
|
*/
|
|
566
|
-
type AsyncResultMethods<T, E> = {
|
|
644
|
+
type AsyncResultMethods<out T, out E> = {
|
|
567
645
|
/**
|
|
568
646
|
* Asynchronous {@link ResultMethods.map | map}: transforms the success value
|
|
569
647
|
* with `f`. `f` is synchronous; a throw becomes a `Defect`. An async callback
|
|
@@ -611,32 +689,22 @@ type AsyncResultMethods<T, E> = {
|
|
|
611
689
|
/** Asynchronous {@link ResultMethods.discard | discard}: drops the value, collapsing the success type to `void`. */
|
|
612
690
|
discard(): AsyncResult$1<void, E>;
|
|
613
691
|
/**
|
|
614
|
-
* Asynchronous {@link ResultMethods.mapErr | mapErr}
|
|
615
|
-
*
|
|
616
|
-
* ({@link NotThenable}).
|
|
617
|
-
*/
|
|
618
|
-
mapErr<E2>(f: (error: E) => E2 & NotThenable<E2>): AsyncResult$1<T, E2>;
|
|
619
|
-
/**
|
|
620
|
-
* Asynchronous {@link ResultMethods.flatMapErr | flatMapErr}. `f` may return a
|
|
621
|
-
* `Result` or an `AsyncResult`.
|
|
692
|
+
* Asynchronous {@link ResultMethods.mapErr | mapErr} — the same exhaustive
|
|
693
|
+
* {@link ErrMatcher} form; the combinator calls `.exhaustive()`.
|
|
622
694
|
*/
|
|
623
|
-
|
|
695
|
+
mapErr<M extends ExhaustiveMatch<unknown>>(f: (matcher: ErrMatcher<E>, defect: (cause: unknown) => Defect) => M): AsyncResult$1<T, MatchErrOut<M>>;
|
|
624
696
|
/**
|
|
625
|
-
*
|
|
626
|
-
*
|
|
697
|
+
* Asynchronous {@link ResultMethods.flatMapErr | flatMapErr} — the same
|
|
698
|
+
* exhaustive {@link ErrMatcher} form. Unlike the sync form, a branch may
|
|
699
|
+
* return a `Result` **or** an `AsyncResult`.
|
|
627
700
|
*/
|
|
628
|
-
|
|
701
|
+
flatMapErr<M extends ExhaustiveMatch<Result$1<unknown, unknown> | AsyncResult$1<unknown, unknown> | Defect>>(f: (matcher: ErrMatcher<E>, defect: (cause: unknown) => Defect) => M): AsyncResult$1<T | OkOf<MatchOut<M>> | AsyncOkOf<MatchOut<M>>, ErrOf<MatchOut<M>> | AsyncErrOf<MatchOut<M>>>;
|
|
629
702
|
/**
|
|
630
|
-
* Asynchronous {@link ResultMethods.recoverErr | recoverErr}
|
|
631
|
-
*
|
|
632
|
-
*
|
|
633
|
-
*/
|
|
634
|
-
recoverErr<U>(f: (error: E) => U & NotThenable<U>): AsyncResult$1<T | U, never>;
|
|
635
|
-
/**
|
|
636
|
-
* @deprecated Renamed to {@link AsyncResultMethods.recoverErr | recoverErr}.
|
|
637
|
-
* This alias will be removed in a future major.
|
|
703
|
+
* Asynchronous {@link ResultMethods.recoverErr | recoverErr} — the same
|
|
704
|
+
* exhaustive {@link ErrMatcher} form. Branches are synchronous; a throw
|
|
705
|
+
* becomes a `Defect`.
|
|
638
706
|
*/
|
|
639
|
-
|
|
707
|
+
recoverErr<M extends ExhaustiveMatch<unknown>>(f: (matcher: ErrMatcher<E>, defect: (cause: unknown) => Defect) => M): AsyncResult$1<T | MatchErrOut<M>, never>;
|
|
640
708
|
/**
|
|
641
709
|
* Asynchronous {@link ResultMethods.tapErr | tapErr}. `f` is synchronous; if it
|
|
642
710
|
* throws, the result is a `Defect` whose cause is an `AggregateError` of
|
|
@@ -646,7 +714,7 @@ type AsyncResultMethods<T, E> = {
|
|
|
646
714
|
* too — a failable effect belongs in
|
|
647
715
|
* {@link AsyncResultMethods.flatTapErr | flatTapErr}.
|
|
648
716
|
*/
|
|
649
|
-
tapErr
|
|
717
|
+
tapErr(f: (matcher: ErrMatcher<E>, defect: (cause: unknown) => Defect) => ExhaustiveMatch<unknown>): AsyncResult$1<T, E>;
|
|
650
718
|
/**
|
|
651
719
|
* Asynchronous {@link ResultMethods.flatTapErr | flatTapErr} — the
|
|
652
720
|
* error-channel mirror of `flatTap`. `f` may return a `Result` **or** an
|
|
@@ -655,7 +723,7 @@ type AsyncResultMethods<T, E> = {
|
|
|
655
723
|
* an `AggregateError` of `[thrown, original failure]` — observing a failure
|
|
656
724
|
* never destroys it.
|
|
657
725
|
*/
|
|
658
|
-
flatTapErr<E2>(f: (
|
|
726
|
+
flatTapErr<E2>(f: (matcher: ErrMatcher<E>, defect: (cause: unknown) => Defect) => ExhaustiveMatch<Result$1<unknown, E2> | AsyncResult$1<unknown, E2>>): AsyncResult$1<T, E | E2>;
|
|
659
727
|
/**
|
|
660
728
|
* Asynchronous {@link ResultMethods.recoverDefect | recoverDefect}. `f` may
|
|
661
729
|
* return a `Result` or an `AsyncResult`.
|
|
@@ -669,50 +737,40 @@ type AsyncResultMethods<T, E> = {
|
|
|
669
737
|
*/
|
|
670
738
|
tapDefect<R>(f: (cause: unknown) => R & NotThenable<R>): AsyncResult$1<T, E>;
|
|
671
739
|
/**
|
|
672
|
-
* Asynchronous {@link ResultMethods.
|
|
673
|
-
*
|
|
740
|
+
* Asynchronous {@link ResultMethods.tapFailure | tapFailure} — the
|
|
741
|
+
* cross-channel observer. `f` receives the narrowed failure variant
|
|
742
|
+
* ({@link FailureView}); if it throws, the result is a `Defect` whose cause
|
|
743
|
+
* is an `AggregateError` of `[thrown, original failure]` — observing a
|
|
744
|
+
* failure never destroys it. An async callback is rejected at compile time
|
|
745
|
+
* ({@link NotThenable}).
|
|
674
746
|
*/
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
747
|
+
tapFailure<R>(f: (failure: FailureView<E, T>) => R & NotThenable<R>): AsyncResult$1<T, E>;
|
|
748
|
+
/**
|
|
749
|
+
* Asynchronous {@link ResultMethods.match | match}. Handlers are synchronous
|
|
750
|
+
* (the `err` handler returns an exhaustive {@link ErrMatcher} builder, no
|
|
751
|
+
* `defect` helper); resolves to a `Promise` of the folded value.
|
|
752
|
+
*/
|
|
753
|
+
match<ROk, RDefect, M extends ExhaustiveMatch<unknown>>(cases: {
|
|
754
|
+
ok: (value: T) => ROk;
|
|
755
|
+
err: (matcher: ErrMatcher<E>) => M;
|
|
756
|
+
defect: (cause: unknown) => RDefect;
|
|
757
|
+
}): Promise<ROk | RDefect | MatchOut<M>>;
|
|
680
758
|
/**
|
|
681
759
|
* Asynchronous {@link ResultMethods.get | get}. Compiles only when the
|
|
682
760
|
* error channel is empty (`this: AsyncResult<T, never>`); the returned promise
|
|
683
761
|
* rejects on a `Defect` (rethrowing its cause).
|
|
684
762
|
*/
|
|
685
763
|
get(this: AsyncResult$1<T, never>): Promise<T>;
|
|
686
|
-
/**
|
|
687
|
-
* @deprecated Renamed to {@link AsyncResultMethods.get | get}. This alias will
|
|
688
|
-
* be removed in a future major.
|
|
689
|
-
*/
|
|
690
|
-
unwrap(this: AsyncResult$1<T, never>): Promise<T>;
|
|
691
764
|
/**
|
|
692
765
|
* Asynchronous {@link ResultMethods.getErr | getErr}. Compiles only when
|
|
693
766
|
* the success channel is empty (`this: AsyncResult<never, E>`); the returned
|
|
694
767
|
* promise rejects on a `Defect` (rethrowing its cause).
|
|
695
768
|
*/
|
|
696
769
|
getErr(this: AsyncResult$1<never, E>): Promise<E>;
|
|
697
|
-
/**
|
|
698
|
-
* @deprecated Renamed to {@link AsyncResultMethods.getErr | getErr}. This alias
|
|
699
|
-
* will be removed in a future major.
|
|
700
|
-
*/
|
|
701
|
-
unwrapErr(this: AsyncResult$1<never, E>): Promise<E>;
|
|
702
770
|
/** Asynchronous {@link ResultMethods.getOr | getOr}. */
|
|
703
771
|
getOr<U>(fallback: U): Promise<T | U>;
|
|
704
|
-
/**
|
|
705
|
-
* @deprecated Renamed to {@link AsyncResultMethods.getOr | getOr}. This alias
|
|
706
|
-
* will be removed in a future major.
|
|
707
|
-
*/
|
|
708
|
-
unwrapOr<U>(fallback: U): Promise<T | U>;
|
|
709
772
|
/** Asynchronous {@link ResultMethods.getOrElse | getOrElse}. */
|
|
710
773
|
getOrElse<U>(f: (error: E) => U): Promise<T | U>;
|
|
711
|
-
/**
|
|
712
|
-
* @deprecated Renamed to {@link AsyncResultMethods.getOrElse | getOrElse}. This
|
|
713
|
-
* alias will be removed in a future major.
|
|
714
|
-
*/
|
|
715
|
-
unwrapOrElse<U>(f: (error: E) => U): Promise<T | U>;
|
|
716
774
|
/** Asynchronous {@link ResultMethods.getOrNull | getOrNull}. */
|
|
717
775
|
getOrNull(): Promise<T | null>;
|
|
718
776
|
/** Asynchronous {@link ResultMethods.getOrUndefined | getOrUndefined}. */
|
|
@@ -720,9 +778,10 @@ type AsyncResultMethods<T, E> = {
|
|
|
720
778
|
/**
|
|
721
779
|
* Asynchronous {@link ResultMethods.getOrThrow | getOrThrow} — the returned
|
|
722
780
|
* promise **rejects** with the modeled error on `Err` (or the original cause
|
|
723
|
-
* on a `Defect`), rather than throwing synchronously.
|
|
781
|
+
* on a `Defect`), rather than throwing synchronously. Gated the same way: it
|
|
782
|
+
* compiles only when the error channel is non-empty (`E` is not `never`).
|
|
724
783
|
*/
|
|
725
|
-
getOrThrow(): Promise<T>;
|
|
784
|
+
getOrThrow(this: [E] extends [never] ? never : AsyncResult$1<T, E>): Promise<T>;
|
|
726
785
|
};
|
|
727
786
|
/**
|
|
728
787
|
* The asynchronous counterpart of {@link Result}: an awaitable wrapper carrying
|
|
@@ -795,7 +854,7 @@ type ErrOf<R> = R extends {
|
|
|
795
854
|
*
|
|
796
855
|
* @category Types
|
|
797
856
|
*/
|
|
798
|
-
type AsyncOkOf<R> = R extends
|
|
857
|
+
type AsyncOkOf<R> = R extends Awaitable<infer Res> ? OkOf<Res> : never;
|
|
799
858
|
/**
|
|
800
859
|
* Extract the error type `E` from an {@link AsyncResult} type — the async
|
|
801
860
|
* counterpart of {@link ErrOf}.
|
|
@@ -809,7 +868,7 @@ type AsyncOkOf<R> = R extends AsyncResult$1<infer T, unknown> ? T : never;
|
|
|
809
868
|
*
|
|
810
869
|
* @category Types
|
|
811
870
|
*/
|
|
812
|
-
type AsyncErrOf<R> = R extends
|
|
871
|
+
type AsyncErrOf<R> = R extends Awaitable<infer Res> ? ErrOf<Res> : never;
|
|
813
872
|
//#endregion
|
|
814
873
|
//#region src/constructors.d.ts
|
|
815
874
|
/**
|
|
@@ -996,12 +1055,12 @@ declare function isDefect<T, E>(r: Result$1<T, E>): r is DefectView<T, E>;
|
|
|
996
1055
|
* `Ok`.
|
|
997
1056
|
*
|
|
998
1057
|
* @remarks
|
|
999
|
-
* The offending value is exposed two ways: the typed {@link
|
|
1058
|
+
* The offending value is exposed two ways: the typed {@link GetError.error}
|
|
1000
1059
|
* property for programmatic access, and the standard `Error.cause` for the
|
|
1001
1060
|
* runtime and devtools to chain — when `E` is an `Error` (e.g. a `TaggedError`)
|
|
1002
1061
|
* its original stack is printed under "caused by".
|
|
1003
1062
|
*
|
|
1004
|
-
* A `Defect` is never wrapped in
|
|
1063
|
+
* A `Defect` is never wrapped in a `GetError`: its original cause is
|
|
1005
1064
|
* re-thrown (with its original stack) instead.
|
|
1006
1065
|
*
|
|
1007
1066
|
* `get()` and `getErr()` are type-gated (`this: Result<T, never>` /
|
|
@@ -1009,11 +1068,11 @@ declare function isDefect<T, E>(r: Result$1<T, E>): r is DefectView<T, E>;
|
|
|
1009
1068
|
* unreachable through well-typed code — it remains only as a defensive guard
|
|
1010
1069
|
* against unsound runtime misuse (e.g. an `as` cast past the gate).
|
|
1011
1070
|
*
|
|
1012
|
-
* @typeParam E - the type of the {@link
|
|
1071
|
+
* @typeParam E - the type of the {@link GetError.error} it carries.
|
|
1013
1072
|
*
|
|
1014
1073
|
* @category Errors
|
|
1015
1074
|
*/
|
|
1016
|
-
declare class
|
|
1075
|
+
declare class GetError<E = unknown> extends Error {
|
|
1017
1076
|
/**
|
|
1018
1077
|
* The offending value: the `Err` error for `get()`, or the `Ok` value for
|
|
1019
1078
|
* `getErr()`.
|
|
@@ -1092,27 +1151,6 @@ declare function isResult(x: unknown): x is Result$1<unknown, unknown>;
|
|
|
1092
1151
|
*/
|
|
1093
1152
|
declare function Do(): Result$1<{}, never>;
|
|
1094
1153
|
//#endregion
|
|
1095
|
-
//#region src/defect.d.ts
|
|
1096
|
-
declare const DEFECT: unique symbol;
|
|
1097
|
-
/**
|
|
1098
|
-
* The opaque marker a `qualify` function returns to triage a cause as
|
|
1099
|
-
* **unexpected**.
|
|
1100
|
-
*
|
|
1101
|
-
* @remarks
|
|
1102
|
-
* `qualify` (passed to {@link fromPromise} / {@link fromThrowable}) returns
|
|
1103
|
-
* `E | Defect`: either a modeled domain error, or a `Defect` produced by the
|
|
1104
|
-
* injected `defect` helper to say "this failure is not modeled". A `Defect` is
|
|
1105
|
-
* opaque — it carries the original cause for the boundary to convert into the
|
|
1106
|
-
* third runtime state of a `Result`. It is **not** a public value; the only way
|
|
1107
|
-
* to mint one is the `defect` helper the boundary passes to `qualify`.
|
|
1108
|
-
*
|
|
1109
|
-
* @internal
|
|
1110
|
-
*/
|
|
1111
|
-
type Defect = {
|
|
1112
|
-
readonly [DEFECT]: true;
|
|
1113
|
-
readonly cause: unknown;
|
|
1114
|
-
};
|
|
1115
|
-
//#endregion
|
|
1116
1154
|
//#region src/interop.d.ts
|
|
1117
1155
|
/**
|
|
1118
1156
|
* Bridge a nullable value into a {@link Result}: absence becomes a **modeled**
|
|
@@ -1547,8 +1585,10 @@ type TaggedErrorConstructor<Tag extends string> = {
|
|
|
1547
1585
|
* rejected at compile time (and excluded from the instance type), so it can't
|
|
1548
1586
|
* shadow `Error.name`.
|
|
1549
1587
|
*
|
|
1550
|
-
* `_tag` is the discriminant
|
|
1551
|
-
*
|
|
1588
|
+
* `_tag` is the discriminant matched by {@link tag} in the error combinators
|
|
1589
|
+
* (`result.mapErr((matcher) => matcher.with(tag("NotFound"), …))`) and in
|
|
1590
|
+
* `match`; `Error.name` is the human-facing label in stack traces and logs. By
|
|
1591
|
+
* default they coincide, but
|
|
1552
1592
|
* they can be **decoupled** with `options.name` — so a tag can be namespaced for
|
|
1553
1593
|
* collision-safety (`"@my-lib/RetryableError"`) without that slash-prefixed
|
|
1554
1594
|
* string leaking into `Error.name`:
|
|
@@ -1586,78 +1626,28 @@ declare function TaggedError<Tag extends string>(tag: Tag, options?: {
|
|
|
1586
1626
|
readonly name?: string;
|
|
1587
1627
|
}): TaggedErrorConstructor<Tag>;
|
|
1588
1628
|
/**
|
|
1589
|
-
*
|
|
1590
|
-
*
|
|
1591
|
-
*
|
|
1592
|
-
*
|
|
1593
|
-
* @typeParam T - the success value type.
|
|
1594
|
-
* @typeParam E - the tagged error union.
|
|
1595
|
-
* @typeParam R - the folded result type.
|
|
1596
|
-
*
|
|
1597
|
-
* @category Types
|
|
1598
|
-
*/
|
|
1599
|
-
type TagHandlers<T, E extends {
|
|
1600
|
-
_tag: string;
|
|
1601
|
-
}, R> = {
|
|
1602
|
-
Ok: (value: T) => R;
|
|
1603
|
-
Defect: (cause: unknown) => R;
|
|
1604
|
-
} & { [K in E["_tag"]]: (error: Extract<E, {
|
|
1605
|
-
_tag: K;
|
|
1606
|
-
}>) => R; };
|
|
1607
|
-
/**
|
|
1608
|
-
* The channel-handler names are reserved: an error tag named `"Ok"` or
|
|
1609
|
-
* `"Defect"` would collide with them inside {@link TagHandlers}, so
|
|
1610
|
-
* {@link matchTags} rejects such unions at the call site.
|
|
1611
|
-
*
|
|
1612
|
-
* @internal
|
|
1613
|
-
*/
|
|
1614
|
-
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)';
|
|
1615
|
-
/**
|
|
1616
|
-
* Exhaustively fold a {@link Result} (or {@link AsyncResult}) whose error type is
|
|
1617
|
-
* a tagged union, dispatching each error to the handler matching its `_tag`.
|
|
1618
|
-
*
|
|
1619
|
-
* @remarks
|
|
1620
|
-
* The `handlers` object must provide `Ok`, `Defect`, and exactly one function
|
|
1621
|
-
* per error tag; each tag's handler receives the narrowed error variant. A
|
|
1622
|
-
* missing tag is a compile error. For an `AsyncResult`, the fold resolves to a
|
|
1623
|
-
* `Promise<R>`. At runtime, an error whose `_tag` has no handler (possible only
|
|
1624
|
-
* outside the typed contract) is routed to the `Defect` handler — an unmodeled
|
|
1625
|
-
* tag is an unmodeled failure. Tags named `"Ok"` or `"Defect"` are rejected at
|
|
1626
|
-
* compile time.
|
|
1629
|
+
* A `ts-pattern` pattern matching any value whose `_tag` equals `value` — a
|
|
1630
|
+
* {@link TaggedError}, or any discriminated member. Equivalent to the object
|
|
1631
|
+
* pattern `{ _tag: value }`, but reads better inside an error-matching
|
|
1632
|
+
* combinator and narrows to the matching variant, payload included.
|
|
1627
1633
|
*
|
|
1628
|
-
* @typeParam
|
|
1629
|
-
* @
|
|
1630
|
-
* @typeParam R - the folded result type.
|
|
1631
|
-
* @param result - the result to fold.
|
|
1632
|
-
* @param handlers - one branch per channel/tag.
|
|
1634
|
+
* @typeParam Tag - the string literal tag to match.
|
|
1635
|
+
* @param value - the `_tag` to match.
|
|
1633
1636
|
*
|
|
1634
1637
|
* @category Tagged errors
|
|
1635
1638
|
*
|
|
1636
1639
|
* @example
|
|
1637
1640
|
* ```ts
|
|
1638
|
-
*
|
|
1639
|
-
*
|
|
1640
|
-
*
|
|
1641
|
-
*
|
|
1642
|
-
*
|
|
1643
|
-
* const fold = (r: Result<number, NotFound | Forbidden>) =>
|
|
1644
|
-
* matchTags(r, {
|
|
1645
|
-
* Ok: (n) => `got ${n}`,
|
|
1646
|
-
* Defect: (cause) => `bug: ${String(cause)}`,
|
|
1647
|
-
* NotFound: () => "404",
|
|
1648
|
-
* Forbidden: (e) => `403 for ${e.user}`,
|
|
1649
|
-
* });
|
|
1650
|
-
*
|
|
1651
|
-
* fold(Ok(1)); // => "got 1"
|
|
1652
|
-
* fold(Err(new Forbidden({ user: "ada" }))); // => "403 for ada"
|
|
1641
|
+
* result.mapErr((matcher) =>
|
|
1642
|
+
* matcher
|
|
1643
|
+
* .with(tag("NotFound"), () => new NotFoundException())
|
|
1644
|
+
* .with(tag("Conflict"), (e) => new ConflictException(e.key)),
|
|
1645
|
+
* );
|
|
1653
1646
|
* ```
|
|
1654
1647
|
*/
|
|
1655
|
-
declare function
|
|
1656
|
-
_tag:
|
|
1657
|
-
}
|
|
1658
|
-
declare function matchTags<T, E extends {
|
|
1659
|
-
_tag: string;
|
|
1660
|
-
}, R>(result: AsyncResult$1<T, E>, handlers: TagHandlers<T, E, R> & ([Extract<E["_tag"], "Ok" | "Defect">] extends [never] ? unknown : ReservedTagError)): Promise<R>;
|
|
1648
|
+
declare function tag<const Tag extends string>(value: Tag): {
|
|
1649
|
+
_tag: Tag;
|
|
1650
|
+
};
|
|
1661
1651
|
//#endregion
|
|
1662
|
-
export { type AsyncErrOf, type AsyncOkOf, AsyncResult, type AsyncResultMethods, type Awaitable, type DefectView, Do, Err, ErrAsync, type ErrOf, type ErrView, type NotThenable, Ok, OkAsync, type OkOf, type OkView, Result, type ResultMethods,
|
|
1652
|
+
export { type AsyncErrOf, type AsyncOkOf, AsyncResult, type AsyncResultMethods, type Awaitable, type DefectView, Do, Err, ErrAsync, type ErrMatcher, type ErrOf, type ErrView, type FailureView, GetError, type NotThenable, Ok, OkAsync, type OkOf, type OkView, P, Result, type ResultMethods, TaggedError, type TaggedErrorConstructor, type TaggedErrorInstance, all, allAsync, allFromDict, allFromDictAsync, fromNullable, fromPromise, fromSafePromise, fromSafeThrowable, fromThrowable, isDefect, isErr, isOk, isResult, match, tag };
|
|
1663
1653
|
//# sourceMappingURL=index.d.cts.map
|