@jagreehal/workflow 1.0.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.
@@ -0,0 +1,1606 @@
1
+ /**
2
+ * @jagreehal/workflow/core
3
+ *
4
+ * Core Result primitives and run() function.
5
+ * Use this module for minimal bundle size when you don't need the full workflow capabilities
6
+ * (like retries, timeout, or state persistence) provided by `createWorkflow`.
7
+ *
8
+ * This module provides:
9
+ * 1. `Result` types for error handling without try/catch
10
+ * 2. `run()` function for executing steps with standardized error management
11
+ * 3. Utilities for transforming and combining Results
12
+ */
13
+ /**
14
+ * Represents a successful computation or a failed one.
15
+ * Use this type to represent the outcome of an operation that might fail,
16
+ * instead of throwing exceptions.
17
+ *
18
+ * @template T - The type of the success value
19
+ * @template E - The type of the error value (defaults to unknown)
20
+ * @template C - The type of the cause (defaults to unknown)
21
+ */
22
+ type Result<T, E = unknown, C = unknown> = {
23
+ ok: true;
24
+ value: T;
25
+ } | {
26
+ ok: false;
27
+ error: E;
28
+ cause?: C;
29
+ };
30
+ /**
31
+ * A Promise that resolves to a Result.
32
+ * Use this for asynchronous operations that might fail.
33
+ */
34
+ type AsyncResult<T, E = unknown, C = unknown> = Promise<Result<T, E, C>>;
35
+ type UnexpectedStepFailureCause = {
36
+ type: "STEP_FAILURE";
37
+ origin: "result";
38
+ error: unknown;
39
+ cause?: unknown;
40
+ } | {
41
+ type: "STEP_FAILURE";
42
+ origin: "throw";
43
+ error: unknown;
44
+ thrown: unknown;
45
+ };
46
+ type UnexpectedCause = {
47
+ type: "UNCAUGHT_EXCEPTION";
48
+ thrown: unknown;
49
+ } | UnexpectedStepFailureCause;
50
+ type UnexpectedError = {
51
+ type: "UNEXPECTED_ERROR";
52
+ cause: UnexpectedCause;
53
+ };
54
+ type PromiseRejectedError = {
55
+ type: "PROMISE_REJECTED";
56
+ cause: unknown;
57
+ };
58
+ /** Cause type for promise rejections in async batch helpers */
59
+ type PromiseRejectionCause = {
60
+ type: "PROMISE_REJECTION";
61
+ reason: unknown;
62
+ };
63
+ type EmptyInputError = {
64
+ type: "EMPTY_INPUT";
65
+ message: string;
66
+ };
67
+ type MaybeAsyncResult<T, E, C = unknown> = Result<T, E, C> | Promise<Result<T, E, C>>;
68
+ /**
69
+ * Creates a successful Result.
70
+ * Use this when an operation completes successfully.
71
+ *
72
+ * @param value - The success value to wrap
73
+ * @returns A Result object with `{ ok: true, value }`
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * function divide(a: number, b: number): Result<number, string> {
78
+ * if (b === 0) return err("Division by zero");
79
+ * return ok(a / b);
80
+ * }
81
+ * ```
82
+ */
83
+ declare const ok: <T>(value: T) => Result<T, never, never>;
84
+ /**
85
+ * Creates a failed Result.
86
+ * Use this when an operation fails.
87
+ *
88
+ * @param error - The error value describing what went wrong (e.g., error code, object)
89
+ * @param options - Optional context about the failure
90
+ * @param options.cause - The underlying cause of the error (e.g., a caught exception)
91
+ * @returns A Result object with `{ ok: false, error }` (and optional cause)
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * // Simple error
96
+ * const r1 = err("NOT_FOUND");
97
+ *
98
+ * // Error with cause (useful for wrapping exceptions)
99
+ * try {
100
+ * // ... unsafe code
101
+ * } catch (e) {
102
+ * return err("PROCESSING_FAILED", { cause: e });
103
+ * }
104
+ * ```
105
+ */
106
+ declare const err: <E, C = unknown>(error: E, options?: {
107
+ cause?: C;
108
+ }) => Result<never, E, C>;
109
+ /**
110
+ * Checks if a Result is successful.
111
+ * Use this to narrow the type of a Result to the success case.
112
+ *
113
+ * @param r - The Result to check
114
+ * @returns `true` if successful, allowing access to `r.value`
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * const r = someOperation();
119
+ * if (isOk(r)) {
120
+ * console.log(r.value); // Type is T
121
+ * } else {
122
+ * console.error(r.error); // Type is E
123
+ * }
124
+ * ```
125
+ */
126
+ declare const isOk: <T, E, C>(r: Result<T, E, C>) => r is {
127
+ ok: true;
128
+ value: T;
129
+ };
130
+ /**
131
+ * Checks if a Result is a failure.
132
+ * Use this to narrow the type of a Result to the error case.
133
+ *
134
+ * @param r - The Result to check
135
+ * @returns `true` if failed, allowing access to `r.error` and `r.cause`
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * if (isErr(r)) {
140
+ * // Handle error case early
141
+ * return;
142
+ * }
143
+ * // Proceed with success case
144
+ * ```
145
+ */
146
+ declare const isErr: <T, E, C>(r: Result<T, E, C>) => r is {
147
+ ok: false;
148
+ error: E;
149
+ cause?: C;
150
+ };
151
+ /**
152
+ * Checks if an error is an UnexpectedError.
153
+ * Used internally by the framework but exported for advanced custom handling.
154
+ * Indicates an error that wasn't typed/expected in the `run` signature.
155
+ */
156
+ declare const isUnexpectedError: (e: unknown) => e is UnexpectedError;
157
+ type AnyFunction = (...args: never[]) => unknown;
158
+ /**
159
+ * Extract error type from a single function's return type
160
+ */
161
+ type ErrorOf<T extends AnyFunction> = ReturnType<T> extends Result<unknown, infer E, unknown> ? E : ReturnType<T> extends Promise<Result<unknown, infer E, unknown>> ? E : never;
162
+ /**
163
+ * Extract union of error types from multiple functions
164
+ */
165
+ type Errors<T extends AnyFunction[]> = {
166
+ [K in keyof T]: ErrorOf<T[K]>;
167
+ }[number];
168
+ /**
169
+ * Extract value type from Result
170
+ */
171
+ type ExtractValue<T> = T extends {
172
+ ok: true;
173
+ value: infer U;
174
+ } ? U : never;
175
+ /**
176
+ * Extract error type from Result
177
+ */
178
+ type ExtractError<T> = T extends {
179
+ ok: false;
180
+ error: infer E;
181
+ } ? E : never;
182
+ /**
183
+ * Extract cause type from Result
184
+ */
185
+ type ExtractCause<T> = T extends {
186
+ ok: false;
187
+ cause?: infer C;
188
+ } ? C : never;
189
+ /**
190
+ * Extract cause type from a function's return type
191
+ */
192
+ type CauseOf<T extends AnyFunction> = ReturnType<T> extends Result<unknown, unknown, infer C> ? C : ReturnType<T> extends Promise<Result<unknown, unknown, infer C>> ? C : never;
193
+ /**
194
+ * Options for configuring a step within a workflow.
195
+ * Use these to enable tracing, caching, and state persistence.
196
+ */
197
+ type StepOptions = {
198
+ /**
199
+ * Human-readable label for the step.
200
+ * Used in logs, traces, and error messages.
201
+ * Highly recommended for debugging complex workflows.
202
+ */
203
+ name?: string;
204
+ /**
205
+ * Stable identity key for the step.
206
+ * REQUIRED for:
207
+ * 1. Caching: Used as the cache key.
208
+ * 2. Resuming: Used to identify which steps have already completed.
209
+ *
210
+ * Must be unique within the workflow.
211
+ */
212
+ key?: string;
213
+ };
214
+ /**
215
+ * The `step` object passed to the function in `run(async (step) => { ... })`.
216
+ * acts as the bridge between your business logic and the workflow engine.
217
+ *
218
+ * It provides methods to:
219
+ * 1. Execute operations that return `Result` types.
220
+ * 2. safely wrap operations that might throw exceptions (using `step.try`).
221
+ * 3. Assign names and keys to operations for tracing and caching.
222
+ *
223
+ * @template E - The union of all known error types expected in this workflow.
224
+ */
225
+ interface RunStep<E = unknown> {
226
+ /**
227
+ * Execute a Result-returning operation (lazy function form).
228
+ *
229
+ * Use this form when the operation has side effects or is expensive,
230
+ * so it's only executed if the step hasn't been cached/completed yet.
231
+ *
232
+ * @param operation - A function that returns a Result or AsyncResult
233
+ * @param options - Step name or options object
234
+ * @returns The success value (unwrapped)
235
+ * @throws {EarlyExit} If the result is an error (stops execution safely)
236
+ *
237
+ * @example
238
+ * ```typescript
239
+ * const user = await step(() => fetchUser(id), "fetch-user");
240
+ * ```
241
+ */
242
+ <T, StepE extends E, StepC = unknown>(operation: () => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>, options?: StepOptions | string): Promise<T>;
243
+ /**
244
+ * Execute a Result-returning operation (direct value form).
245
+ *
246
+ * Use this form for simple operations or when you already have a Result/Promise.
247
+ * Note: The operation has already started/completed by the time `step` is called.
248
+ *
249
+ * @param result - A Result object or Promise resolving to a Result
250
+ * @param options - Step name or options object
251
+ * @returns The success value (unwrapped)
252
+ * @throws {EarlyExit} If the result is an error (stops execution safely)
253
+ *
254
+ * @example
255
+ * ```typescript
256
+ * const user = await step(existingResult, "check-result");
257
+ * ```
258
+ */
259
+ <T, StepE extends E, StepC = unknown>(result: Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>, options?: StepOptions | string): Promise<T>;
260
+ /**
261
+ * Execute a standard throwing operation safely.
262
+ * Catches exceptions and maps them to a typed error, or wraps them if no mapper is provided.
263
+ *
264
+ * Use this when integrating with libraries that throw exceptions.
265
+ *
266
+ * @param operation - A function that returns a value or Promise (may throw)
267
+ * @param options - Configuration including error mapping
268
+ * @returns The success value
269
+ * @throws {EarlyExit} If the operation throws (stops execution safely)
270
+ *
271
+ * @example
272
+ * ```typescript
273
+ * const data = await step.try(
274
+ * () => db.query(),
275
+ * {
276
+ * name: "db-query",
277
+ * onError: (e) => ({ type: "DB_ERROR", cause: e })
278
+ * }
279
+ * );
280
+ * ```
281
+ */
282
+ try: <T, const Err extends E>(operation: () => T | Promise<T>, options: {
283
+ error: Err;
284
+ name?: string;
285
+ key?: string;
286
+ } | {
287
+ onError: (cause: unknown) => Err;
288
+ name?: string;
289
+ key?: string;
290
+ }) => Promise<T>;
291
+ }
292
+ /**
293
+ * Unified event stream for workflow execution.
294
+ *
295
+ * Note: step_complete.result uses Result<unknown, unknown, unknown> because events
296
+ * aggregate results from heterogeneous steps. At runtime, the actual Result object
297
+ * preserves its original types, but the event type cannot statically represent them.
298
+ * Use runtime checks or the meta field to interpret cause values.
299
+ */
300
+ type WorkflowEvent<E> = {
301
+ type: "workflow_start";
302
+ workflowId: string;
303
+ ts: number;
304
+ } | {
305
+ type: "workflow_success";
306
+ workflowId: string;
307
+ ts: number;
308
+ durationMs: number;
309
+ } | {
310
+ type: "workflow_error";
311
+ workflowId: string;
312
+ ts: number;
313
+ durationMs: number;
314
+ error: E;
315
+ } | {
316
+ type: "step_start";
317
+ workflowId: string;
318
+ stepKey?: string;
319
+ name?: string;
320
+ ts: number;
321
+ } | {
322
+ type: "step_success";
323
+ workflowId: string;
324
+ stepKey?: string;
325
+ name?: string;
326
+ ts: number;
327
+ durationMs: number;
328
+ } | {
329
+ type: "step_error";
330
+ workflowId: string;
331
+ stepKey?: string;
332
+ name?: string;
333
+ ts: number;
334
+ durationMs: number;
335
+ error: E;
336
+ } | {
337
+ type: "step_aborted";
338
+ workflowId: string;
339
+ stepKey?: string;
340
+ name?: string;
341
+ ts: number;
342
+ durationMs: number;
343
+ } | {
344
+ type: "step_complete";
345
+ workflowId: string;
346
+ stepKey: string;
347
+ name?: string;
348
+ ts: number;
349
+ durationMs: number;
350
+ result: Result<unknown, unknown, unknown>;
351
+ meta?: StepFailureMeta;
352
+ } | {
353
+ type: "step_cache_hit";
354
+ workflowId: string;
355
+ stepKey: string;
356
+ name?: string;
357
+ ts: number;
358
+ } | {
359
+ type: "step_cache_miss";
360
+ workflowId: string;
361
+ stepKey: string;
362
+ name?: string;
363
+ ts: number;
364
+ };
365
+ type RunOptionsWithCatch<E, C = void> = {
366
+ /**
367
+ * Handler for expected errors.
368
+ * Called when a step fails with a known error type.
369
+ */
370
+ onError?: (error: E, stepName?: string) => void;
371
+ /**
372
+ * Listener for workflow events (start, success, error, step events).
373
+ * Use this for logging, telemetry, or debugging.
374
+ */
375
+ onEvent?: (event: WorkflowEvent<E | UnexpectedError>, ctx: C) => void;
376
+ /**
377
+ * Catch-all mapper for unexpected exceptions.
378
+ * Required for "Strict Mode".
379
+ * Converts unknown exceptions (like network crashes or bugs) into your typed error union E.
380
+ */
381
+ catchUnexpected: (cause: unknown) => E;
382
+ /**
383
+ * Unique ID for this workflow execution.
384
+ * Defaults to a random UUID.
385
+ * Useful for correlating logs across distributed systems.
386
+ */
387
+ workflowId?: string;
388
+ /**
389
+ * Arbitrary context object passed to onEvent.
390
+ * Useful for passing request IDs, user IDs, or loggers.
391
+ */
392
+ context?: C;
393
+ };
394
+ type RunOptionsWithoutCatch<E, C = void> = {
395
+ /**
396
+ * Handler for expected errors AND unexpected errors.
397
+ * Unexpected errors will be wrapped in `UnexpectedError`.
398
+ */
399
+ onError?: (error: E | UnexpectedError, stepName?: string) => void;
400
+ onEvent?: (event: WorkflowEvent<E | UnexpectedError>, ctx: C) => void;
401
+ catchUnexpected?: undefined;
402
+ workflowId?: string;
403
+ context?: C;
404
+ };
405
+ type RunOptions<E, C = void> = RunOptionsWithCatch<E, C> | RunOptionsWithoutCatch<E, C>;
406
+ /**
407
+ * Symbol used to identify early exit throws.
408
+ * Exported for the caching layer in workflow.ts.
409
+ * @internal
410
+ */
411
+ declare const EARLY_EXIT_SYMBOL: unique symbol;
412
+ /**
413
+ * Metadata about how a step failed.
414
+ * @internal
415
+ */
416
+ type StepFailureMeta = {
417
+ origin: "result";
418
+ resultCause?: unknown;
419
+ } | {
420
+ origin: "throw";
421
+ thrown: unknown;
422
+ };
423
+ /**
424
+ * Early exit object thrown to short-circuit workflow execution.
425
+ * @internal
426
+ */
427
+ type EarlyExit<E> = {
428
+ [EARLY_EXIT_SYMBOL]: true;
429
+ error: E;
430
+ meta: StepFailureMeta;
431
+ };
432
+ /**
433
+ * Create an early exit throw object.
434
+ * Used by the caching layer to synthesize early exits for cached errors.
435
+ * @internal
436
+ */
437
+ declare function createEarlyExit<E>(error: E, meta: StepFailureMeta): EarlyExit<E>;
438
+ /**
439
+ * Type guard for early exit objects.
440
+ * @internal
441
+ */
442
+ declare function isEarlyExit<E>(e: unknown): e is EarlyExit<E>;
443
+ /**
444
+ * Execute a workflow with "Strict Mode" error handling.
445
+ *
446
+ * In this mode, you MUST provide `catchUnexpected` to map unknown exceptions
447
+ * to your typed error union `E`. This guarantees that the returned Result
448
+ * will only ever contain errors of type `E`.
449
+ *
450
+ * @param fn - The workflow function containing steps
451
+ * @param options - Configuration options, including `catchUnexpected`
452
+ * @returns A Promise resolving to `Result<T, E>`
453
+ *
454
+ * @example
455
+ * ```typescript
456
+ * const result = await run(async (step) => {
457
+ * // ... steps ...
458
+ * }, {
459
+ * catchUnexpected: (e) => ({ type: 'UNKNOWN_ERROR', cause: e })
460
+ * });
461
+ * ```
462
+ */
463
+ declare function run<T, E, C = void>(fn: (step: RunStep<E>) => Promise<T> | T, options: RunOptionsWithCatch<E, C>): AsyncResult<T, E, unknown>;
464
+ /**
465
+ * Execute a workflow with "Typed Mode" error handling.
466
+ *
467
+ * In this mode, you provide an `onError` callback. The returned Result
468
+ * may contain your typed errors `E` OR `UnexpectedError` if an uncaught
469
+ * exception occurs.
470
+ *
471
+ * @param fn - The workflow function containing steps
472
+ * @param options - Configuration options, including `onError`
473
+ * @returns A Promise resolving to `Result<T, E | UnexpectedError>`
474
+ */
475
+ declare function run<T, E, C = void>(fn: (step: RunStep<E | UnexpectedError>) => Promise<T> | T, options: {
476
+ onError: (error: E | UnexpectedError, stepName?: string) => void;
477
+ onEvent?: (event: WorkflowEvent<E | UnexpectedError>, ctx: C) => void;
478
+ workflowId?: string;
479
+ context?: C;
480
+ }): AsyncResult<T, E | UnexpectedError, unknown>;
481
+ /**
482
+ * Execute a workflow with "Safe Default" error handling.
483
+ *
484
+ * In this mode, you don't need to specify any error types.
485
+ * Any error (Result error or thrown exception) will be returned as
486
+ * an `UnexpectedError`.
487
+ *
488
+ * @param fn - The workflow function containing steps
489
+ * @param options - Optional configuration
490
+ * @returns A Promise resolving to `Result<T, UnexpectedError>`
491
+ *
492
+ * @example
493
+ * ```typescript
494
+ * const result = await run(async (step) => {
495
+ * return await step(someOp());
496
+ * });
497
+ * ```
498
+ */
499
+ declare function run<T, C = void>(fn: (step: RunStep) => Promise<T> | T, options?: {
500
+ onEvent?: (event: WorkflowEvent<UnexpectedError>, ctx: C) => void;
501
+ workflowId?: string;
502
+ context?: C;
503
+ }): AsyncResult<T, UnexpectedError, unknown>;
504
+ declare namespace run {
505
+ var strict: <T, E, C = void>(fn: (step: RunStep<E>) => Promise<T> | T, options: {
506
+ onError?: (error: E, stepName?: string) => void;
507
+ onEvent?: (event: WorkflowEvent<E | UnexpectedError>, ctx: C) => void;
508
+ catchUnexpected: (cause: unknown) => E;
509
+ workflowId?: string;
510
+ context?: C;
511
+ }) => AsyncResult<T, E, unknown>;
512
+ }
513
+ /**
514
+ * Error thrown when `unwrap()` is called on an error Result.
515
+ *
516
+ * This error is thrown to prevent silent failures when using `unwrap()`.
517
+ * Prefer using `unwrapOr`, `unwrapOrElse`, or pattern matching with `match` or `isOk`/`isErr`.
518
+ */
519
+ declare class UnwrapError<E = unknown, C = unknown> extends Error {
520
+ readonly error: E;
521
+ readonly cause?: C | undefined;
522
+ constructor(error: E, cause?: C | undefined);
523
+ }
524
+ /**
525
+ * Unwraps a Result, throwing an error if it's a failure.
526
+ *
527
+ * ## When to Use
528
+ *
529
+ * Use `unwrap()` when:
530
+ * - You're certain the Result is successful (e.g., after checking with `isOk`)
531
+ * - You're in a context where errors should crash (e.g., tests, initialization)
532
+ * - You need the value immediately and can't handle errors gracefully
533
+ *
534
+ * ## Why Avoid This
535
+ *
536
+ * **Prefer alternatives** in production code:
537
+ * - `unwrapOr(defaultValue)` - Provide a fallback value
538
+ * - `unwrapOrElse(fn)` - Compute fallback from error
539
+ * - `match()` - Handle both cases explicitly
540
+ * - `isOk()` / `isErr()` - Type-safe pattern matching
541
+ *
542
+ * Throwing errors makes error handling harder and can crash your application.
543
+ *
544
+ * @param r - The Result to unwrap
545
+ * @returns The success value if the Result is successful
546
+ * @throws {UnwrapError} If the Result is an error (includes the error and cause)
547
+ *
548
+ * @example
549
+ * ```typescript
550
+ * // Safe usage after checking
551
+ * const result = someOperation();
552
+ * if (isOk(result)) {
553
+ * const value = unwrap(result); // Safe - we know it's ok
554
+ * }
555
+ *
556
+ * // Unsafe usage (not recommended)
557
+ * const value = unwrap(someOperation()); // May throw!
558
+ * ```
559
+ */
560
+ declare const unwrap: <T, E, C>(r: Result<T, E, C>) => T;
561
+ /**
562
+ * Unwraps a Result, returning a default value if it's a failure.
563
+ *
564
+ * ## When to Use
565
+ *
566
+ * Use `unwrapOr()` when:
567
+ * - You have a sensible default value for errors
568
+ * - You want to continue execution even on failure
569
+ * - The default value is cheap to compute (use `unwrapOrElse` if expensive)
570
+ *
571
+ * ## Why Use This
572
+ *
573
+ * - **Safe**: Never throws, always returns a value
574
+ * - **Simple**: One-liner for common error handling
575
+ * - **Type-safe**: TypeScript knows you'll always get a `T`
576
+ *
577
+ * @param r - The Result to unwrap
578
+ * @param defaultValue - The value to return if the Result is an error
579
+ * @returns The success value if successful, otherwise the default value
580
+ *
581
+ * @example
582
+ * ```typescript
583
+ * // Provide default for missing data
584
+ * const user = unwrapOr(fetchUser(id), { id: 'anonymous', name: 'Guest' });
585
+ *
586
+ * // Provide default for numeric operations
587
+ * const count = unwrapOr(parseCount(input), 0);
588
+ *
589
+ * // Provide default for optional features
590
+ * const config = unwrapOr(loadConfig(), getDefaultConfig());
591
+ * ```
592
+ */
593
+ declare const unwrapOr: <T, E, C>(r: Result<T, E, C>, defaultValue: T) => T;
594
+ /**
595
+ * Unwraps a Result, computing a default value from the error if it's a failure.
596
+ *
597
+ * ## When to Use
598
+ *
599
+ * Use `unwrapOrElse()` when:
600
+ * - The default value is expensive to compute (lazy evaluation)
601
+ * - You need to log or handle the error before providing a default
602
+ * - The default depends on the error type or cause
603
+ * - You want to transform the error into a success value
604
+ *
605
+ * ## Why Use This Instead of `unwrapOr`
606
+ *
607
+ * - **Lazy**: Default is only computed if needed (better performance)
608
+ * - **Error-aware**: You can inspect the error before providing default
609
+ * - **Flexible**: Default can depend on error type or cause
610
+ *
611
+ * @param r - The Result to unwrap
612
+ * @param fn - Function that receives the error and optional cause, returns the default value
613
+ * @returns The success value if successful, otherwise the result of calling `fn(error, cause)`
614
+ *
615
+ * @example
616
+ * ```typescript
617
+ * // Compute default based on error type
618
+ * const port = unwrapOrElse(parsePort(env.PORT), (error) => {
619
+ * if (error === 'INVALID_FORMAT') return 3000;
620
+ * if (error === 'OUT_OF_RANGE') return 8080;
621
+ * return 4000; // default
622
+ * });
623
+ *
624
+ * // Log error before providing default
625
+ * const data = unwrapOrElse(fetchData(), (error, cause) => {
626
+ * console.error('Failed to fetch:', error, cause);
627
+ * return getCachedData();
628
+ * });
629
+ *
630
+ * // Transform error into success value
631
+ * const result = unwrapOrElse(operation(), (error) => {
632
+ * return { success: false, reason: String(error) };
633
+ * });
634
+ * ```
635
+ */
636
+ declare const unwrapOrElse: <T, E, C>(r: Result<T, E, C>, fn: (error: E, cause?: C) => T) => T;
637
+ /**
638
+ * Wraps a synchronous throwing function in a Result.
639
+ *
640
+ * ## When to Use
641
+ *
642
+ * Use `from()` when:
643
+ * - You have a synchronous function that throws exceptions
644
+ * - You want to convert exceptions to typed errors
645
+ * - You're integrating with libraries that throw (e.g., JSON.parse, fs.readFileSync)
646
+ * - You need to handle errors without try/catch blocks
647
+ *
648
+ * ## Why Use This
649
+ *
650
+ * - **Type-safe errors**: Convert thrown exceptions to typed Result errors
651
+ * - **No try/catch**: Cleaner code without nested try/catch blocks
652
+ * - **Composable**: Results can be chained with `andThen`, `map`, etc.
653
+ * - **Explicit errors**: Forces you to handle errors explicitly
654
+ *
655
+ * @param fn - The synchronous function to execute (may throw)
656
+ * @returns A Result with the function's return value or the thrown error
657
+ *
658
+ * @example
659
+ * ```typescript
660
+ * // Wrap JSON.parse
661
+ * const parsed = from(() => JSON.parse('{"key": "value"}'));
662
+ * // parsed: { ok: true, value: { key: "value" } }
663
+ *
664
+ * const error = from(() => JSON.parse('invalid'));
665
+ * // error: { ok: false, error: SyntaxError }
666
+ * ```
667
+ */
668
+ declare function from<T>(fn: () => T): Result<T, unknown>;
669
+ /**
670
+ * Wraps a synchronous throwing function in a Result with custom error mapping.
671
+ *
672
+ * Use this overload when you want to map thrown exceptions to your typed error union.
673
+ *
674
+ * @param fn - The synchronous function to execute (may throw)
675
+ * @param onError - Function to map the thrown exception to a typed error
676
+ * @returns A Result with the function's return value or the mapped error
677
+ *
678
+ * @example
679
+ * ```typescript
680
+ * // Map exceptions to typed errors
681
+ * const parsed = from(
682
+ * () => JSON.parse(input),
683
+ * (cause) => ({ type: 'PARSE_ERROR' as const, cause })
684
+ * );
685
+ * // parsed.error: { type: 'PARSE_ERROR', cause: SyntaxError }
686
+ *
687
+ * // Map to simple error codes
688
+ * const value = from(
689
+ * () => riskyOperation(),
690
+ * () => 'OPERATION_FAILED' as const
691
+ * );
692
+ * ```
693
+ */
694
+ declare function from<T, E>(fn: () => T, onError: (cause: unknown) => E): Result<T, E>;
695
+ /**
696
+ * Wraps a Promise in a Result, converting rejections to errors.
697
+ *
698
+ * ## When to Use
699
+ *
700
+ * Use `fromPromise()` when:
701
+ * - You have an existing Promise that might reject
702
+ * - You want to convert Promise rejections to typed errors
703
+ * - You're working with libraries that return Promises (fetch, database clients)
704
+ * - You need to handle rejections without .catch() chains
705
+ *
706
+ * ## Why Use This
707
+ *
708
+ * - **Type-safe errors**: Convert Promise rejections to typed Result errors
709
+ * - **Composable**: Results can be chained with `andThen`, `map`, etc.
710
+ * - **Explicit handling**: Forces you to handle errors explicitly
711
+ * - **No .catch() chains**: Cleaner than Promise.catch() patterns
712
+ *
713
+ * @param promise - The Promise to await (may reject)
714
+ * @returns A Promise resolving to a Result with the resolved value or rejection reason
715
+ *
716
+ * @example
717
+ * ```typescript
718
+ * // Wrap fetch
719
+ * const result = await fromPromise(
720
+ * fetch('/api').then(r => r.json())
721
+ * );
722
+ * // result.ok: true if fetch succeeded, false if rejected
723
+ * ```
724
+ */
725
+ declare function fromPromise<T>(promise: Promise<T>): AsyncResult<T, unknown>;
726
+ /**
727
+ * Wraps a Promise in a Result with custom error mapping.
728
+ *
729
+ * Use this overload when you want to map Promise rejections to your typed error union.
730
+ *
731
+ * @param promise - The Promise to await (may reject)
732
+ * @param onError - Function to map the rejection reason to a typed error
733
+ * @returns A Promise resolving to a Result with the resolved value or mapped error
734
+ *
735
+ * @example
736
+ * ```typescript
737
+ * // Map fetch errors to typed errors
738
+ * const result = await fromPromise(
739
+ * fetch('/api').then(r => {
740
+ * if (!r.ok) throw new Error(`HTTP ${r.status}`);
741
+ * return r.json();
742
+ * }),
743
+ * () => 'FETCH_FAILED' as const
744
+ * );
745
+ * // result.error: 'FETCH_FAILED' if fetch failed
746
+ *
747
+ * // Map with error details
748
+ * const data = await fromPromise(
749
+ * db.query(sql),
750
+ * (cause) => ({ type: 'DB_ERROR' as const, message: String(cause) })
751
+ * );
752
+ * ```
753
+ */
754
+ declare function fromPromise<T, E>(promise: Promise<T>, onError: (cause: unknown) => E): AsyncResult<T, E>;
755
+ /**
756
+ * Wraps an async function in a Result, catching both thrown exceptions and Promise rejections.
757
+ *
758
+ * ## When to Use
759
+ *
760
+ * Use `tryAsync()` when:
761
+ * - You have an async function that might throw or reject
762
+ * - You want to convert both exceptions and rejections to typed errors
763
+ * - You're creating new async functions (use `fromPromise` for existing Promises)
764
+ * - You need to handle errors without try/catch or .catch()
765
+ *
766
+ * ## Why Use This Instead of `fromPromise`
767
+ *
768
+ * - **Function form**: Takes a function, not a Promise (lazy evaluation)
769
+ * - **Catches both**: Handles both thrown exceptions and Promise rejections
770
+ * - **Cleaner syntax**: No need to wrap in Promise manually
771
+ *
772
+ * @param fn - The async function to execute (may throw or reject)
773
+ * @returns A Promise resolving to a Result with the function's return value or error
774
+ *
775
+ * @example
776
+ * ```typescript
777
+ * // Wrap async function
778
+ * const result = await tryAsync(async () => {
779
+ * const data = await fetchData();
780
+ * return processData(data);
781
+ * });
782
+ * ```
783
+ */
784
+ declare function tryAsync<T>(fn: () => Promise<T>): AsyncResult<T, unknown>;
785
+ /**
786
+ * Wraps an async function in a Result with custom error mapping.
787
+ *
788
+ * Use this overload when you want to map errors to your typed error union.
789
+ *
790
+ * @param fn - The async function to execute (may throw or reject)
791
+ * @param onError - Function to map the error (exception or rejection) to a typed error
792
+ * @returns A Promise resolving to a Result with the function's return value or mapped error
793
+ *
794
+ * @example
795
+ * ```typescript
796
+ * // Map errors to typed errors
797
+ * const result = await tryAsync(
798
+ * async () => await fetchData(),
799
+ * () => 'FETCH_ERROR' as const
800
+ * );
801
+ *
802
+ * // Map with error details
803
+ * const data = await tryAsync(
804
+ * async () => await processFile(path),
805
+ * (cause) => ({ type: 'PROCESSING_ERROR' as const, cause })
806
+ * );
807
+ * ```
808
+ */
809
+ declare function tryAsync<T, E>(fn: () => Promise<T>, onError: (cause: unknown) => E): AsyncResult<T, E>;
810
+ /**
811
+ * Converts a nullable value to a Result.
812
+ *
813
+ * ## When to Use
814
+ *
815
+ * Use `fromNullable()` when:
816
+ * - You have a value that might be `null` or `undefined`
817
+ * - You want to treat null/undefined as an error case
818
+ * - You're working with APIs that return nullable values (DOM APIs, optional properties)
819
+ * - You want to avoid null checks scattered throughout your code
820
+ *
821
+ * ## Why Use This
822
+ *
823
+ * - **Type-safe**: Converts nullable types to non-nullable Results
824
+ * - **Explicit errors**: Forces you to handle null/undefined cases
825
+ * - **Composable**: Results can be chained with `andThen`, `map`, etc.
826
+ * - **No null checks**: Eliminates need for `if (value == null)` checks
827
+ *
828
+ * @param value - The value that may be null or undefined
829
+ * @param onNull - Function that returns an error when value is null/undefined
830
+ * @returns A Result with the value if not null/undefined, otherwise the error from `onNull`
831
+ *
832
+ * @example
833
+ * ```typescript
834
+ * // Convert DOM element lookup
835
+ * const element = fromNullable(
836
+ * document.getElementById('app'),
837
+ * () => 'ELEMENT_NOT_FOUND' as const
838
+ * );
839
+ *
840
+ * // Convert optional property
841
+ * const userId = fromNullable(
842
+ * user.id,
843
+ * () => 'USER_ID_MISSING' as const
844
+ * );
845
+ *
846
+ * // Convert database query result
847
+ * const record = fromNullable(
848
+ * await db.find(id),
849
+ * () => ({ type: 'NOT_FOUND' as const, id })
850
+ * );
851
+ * ```
852
+ */
853
+ declare function fromNullable<T, E>(value: T | null | undefined, onNull: () => E): Result<T, E>;
854
+ /**
855
+ * Transforms the success value of a Result.
856
+ *
857
+ * ## When to Use
858
+ *
859
+ * Use `map()` when:
860
+ * - You need to transform a success value to another type
861
+ * - You want to apply a pure function to the value
862
+ * - You're building a pipeline of transformations
863
+ * - The transformation cannot fail (use `andThen` if it can fail)
864
+ *
865
+ * ## Why Use This
866
+ *
867
+ * - **Functional style**: Composable, chainable transformations
868
+ * - **Error-preserving**: Errors pass through unchanged
869
+ * - **Type-safe**: TypeScript tracks the transformation
870
+ * - **No unwrapping**: Avoids manual `if (r.ok)` checks
871
+ *
872
+ * @param r - The Result to transform
873
+ * @param fn - Pure function that transforms the success value (must not throw)
874
+ * @returns A new Result with the transformed value, or the original error if `r` was an error
875
+ *
876
+ * @example
877
+ * ```typescript
878
+ * // Transform numeric value
879
+ * const doubled = map(ok(21), n => n * 2);
880
+ * // doubled: { ok: true, value: 42 }
881
+ *
882
+ * // Transform object property
883
+ * const name = map(fetchUser(id), user => user.name);
884
+ *
885
+ * // Chain transformations
886
+ * const formatted = map(
887
+ * map(parseNumber(input), n => n * 2),
888
+ * n => `Result: ${n}`
889
+ * );
890
+ * ```
891
+ */
892
+ declare function map<T, U, E, C>(r: Result<T, E, C>, fn: (value: T) => U): Result<U, E, C>;
893
+ /**
894
+ * Transforms the error value of a Result.
895
+ *
896
+ * ## When to Use
897
+ *
898
+ * Use `mapError()` when:
899
+ * - You need to normalize or transform error types
900
+ * - You want to convert errors to a different error type
901
+ * - You're building error handling pipelines
902
+ * - You need to format error messages or codes
903
+ *
904
+ * ## Why Use This
905
+ *
906
+ * - **Error normalization**: Convert errors to a common format
907
+ * - **Type transformation**: Change error type while preserving value type
908
+ * - **Composable**: Can be chained with other transformers
909
+ * - **Success-preserving**: Success values pass through unchanged
910
+ *
911
+ * @param r - The Result to transform
912
+ * @param fn - Function that transforms the error value (must not throw)
913
+ * @returns A new Result with the original value, or the transformed error if `r` was an error
914
+ *
915
+ * @example
916
+ * ```typescript
917
+ * // Normalize error codes
918
+ * const normalized = mapError(err('not_found'), e => e.toUpperCase());
919
+ * // normalized: { ok: false, error: 'NOT_FOUND' }
920
+ *
921
+ * // Convert error types
922
+ * const typed = mapError(
923
+ * err('404'),
924
+ * code => ({ type: 'HTTP_ERROR' as const, status: parseInt(code) })
925
+ * );
926
+ *
927
+ * // Format error messages
928
+ * const formatted = mapError(
929
+ * err('PARSE_ERROR'),
930
+ * code => `Failed to parse: ${code}`
931
+ * );
932
+ * ```
933
+ */
934
+ declare function mapError<T, E, F, C>(r: Result<T, E, C>, fn: (error: E) => F): Result<T, F, C>;
935
+ /**
936
+ * Pattern matches on a Result, calling the appropriate handler.
937
+ *
938
+ * ## When to Use
939
+ *
940
+ * Use `match()` when:
941
+ * - You need to handle both success and error cases
942
+ * - You want to transform a Result to a different type
943
+ * - You need exhaustive handling (both cases must be handled)
944
+ * - You're building user-facing messages or responses
945
+ *
946
+ * ## Why Use This
947
+ *
948
+ * - **Exhaustive**: Forces you to handle both success and error cases
949
+ * - **Type-safe**: TypeScript ensures both handlers are provided
950
+ * - **Functional**: Pattern matching style, similar to Rust's `match` or Haskell's `case`
951
+ * - **Single expression**: Can be used in expressions, not just statements
952
+ *
953
+ * @param r - The Result to match
954
+ * @param handlers - Object with `ok` and `err` handler functions
955
+ * @param handlers.ok - Function called with the success value
956
+ * @param handlers.err - Function called with the error and optional cause
957
+ * @returns The return value of the appropriate handler (both must return the same type `R`)
958
+ *
959
+ * @example
960
+ * ```typescript
961
+ * // Build user-facing messages
962
+ * const message = match(result, {
963
+ * ok: (user) => `Hello ${user.name}`,
964
+ * err: (error) => `Error: ${error}`,
965
+ * });
966
+ *
967
+ * // Transform to API response
968
+ * const response = match(operation(), {
969
+ * ok: (data) => ({ status: 200, body: data }),
970
+ * err: (error) => ({ status: 400, error: String(error) }),
971
+ * });
972
+ *
973
+ * // Handle with cause
974
+ * const log = match(result, {
975
+ * ok: (value) => console.log('Success:', value),
976
+ * err: (error, cause) => console.error('Error:', error, cause),
977
+ * });
978
+ * ```
979
+ */
980
+ declare function match<T, E, C, R>(r: Result<T, E, C>, handlers: {
981
+ ok: (value: T) => R;
982
+ err: (error: E, cause?: C) => R;
983
+ }): R;
984
+ /**
985
+ * Chains Results together (flatMap/monadic bind).
986
+ *
987
+ * ## When to Use
988
+ *
989
+ * Use `andThen()` when:
990
+ * - You need to chain operations that can fail
991
+ * - The next operation depends on the previous success value
992
+ * - You're building a pipeline of dependent operations
993
+ * - You want to avoid nested `if (r.ok)` checks
994
+ *
995
+ * ## Why Use This Instead of `map`
996
+ *
997
+ * - **Can fail**: The chained function returns a Result (can fail)
998
+ * - **Short-circuits**: If first Result fails, second operation never runs
999
+ * - **Error accumulation**: Errors from both operations are in the union
1000
+ * - **Composable**: Can chain multiple operations together
1001
+ *
1002
+ * ## Common Pattern
1003
+ *
1004
+ * This is the fundamental building block for Result pipelines:
1005
+ * ```typescript
1006
+ * andThen(operation1(), value1 =>
1007
+ * andThen(operation2(value1), value2 =>
1008
+ * ok({ value1, value2 })
1009
+ * )
1010
+ * )
1011
+ * ```
1012
+ *
1013
+ * @param r - The first Result
1014
+ * @param fn - Function that takes the success value and returns a new Result (may fail)
1015
+ * @returns The Result from `fn` if `r` was successful, otherwise the original error
1016
+ *
1017
+ * @example
1018
+ * ```typescript
1019
+ * // Chain dependent operations
1020
+ * const userPosts = andThen(
1021
+ * fetchUser('1'),
1022
+ * user => fetchPosts(user.id)
1023
+ * );
1024
+ *
1025
+ * // Build complex pipelines
1026
+ * const result = andThen(parseInput(input), parsed =>
1027
+ * andThen(validate(parsed), validated =>
1028
+ * process(validated)
1029
+ * )
1030
+ * );
1031
+ *
1032
+ * // Chain with different error types
1033
+ * const data = andThen(
1034
+ * fetchUser(id), // Returns Result<User, 'FETCH_ERROR'>
1035
+ * user => fetchPosts(user.id) // Returns Result<Post[], 'NOT_FOUND'>
1036
+ * );
1037
+ * // data.error: 'FETCH_ERROR' | 'NOT_FOUND'
1038
+ * ```
1039
+ */
1040
+ declare function andThen<T, U, E, F, C1, C2>(r: Result<T, E, C1>, fn: (value: T) => Result<U, F, C2>): Result<U, E | F, C1 | C2>;
1041
+ /**
1042
+ * Executes a side effect on a successful Result without changing it.
1043
+ *
1044
+ * ## When to Use
1045
+ *
1046
+ * Use `tap()` when:
1047
+ * - You need to log, debug, or observe success values
1048
+ * - You want to perform side effects in a pipeline
1049
+ * - You need to mutate external state based on success
1050
+ * - You're debugging and want to inspect values without breaking the chain
1051
+ *
1052
+ * ## Why Use This
1053
+ *
1054
+ * - **Non-breaking**: Doesn't change the Result, just performs side effect
1055
+ * - **Composable**: Can be inserted anywhere in a pipeline
1056
+ * - **Type-preserving**: Returns the same Result type
1057
+ * - **Lazy**: Side effect only runs if Result is successful
1058
+ *
1059
+ * @param r - The Result to tap
1060
+ * @param fn - Side effect function called with the success value (return value ignored)
1061
+ * @returns The original Result unchanged (for chaining)
1062
+ *
1063
+ * @example
1064
+ * ```typescript
1065
+ * // Log success values
1066
+ * const logged = tap(result, user => console.log('Got user:', user.name));
1067
+ * // logged === result, but console.log was called
1068
+ *
1069
+ * // Debug in pipeline
1070
+ * const debugged = pipe(
1071
+ * fetchUser(id),
1072
+ * r => tap(r, user => console.log('Fetched:', user)),
1073
+ * r => map(r, user => user.name)
1074
+ * );
1075
+ *
1076
+ * // Mutate external state
1077
+ * const tracked = tap(result, data => {
1078
+ * analytics.track('operation_success', data);
1079
+ * });
1080
+ * ```
1081
+ */
1082
+ declare function tap<T, E, C>(r: Result<T, E, C>, fn: (value: T) => void): Result<T, E, C>;
1083
+ /**
1084
+ * Executes a side effect on an error Result without changing it.
1085
+ *
1086
+ * ## When to Use
1087
+ *
1088
+ * Use `tapError()` when:
1089
+ * - You need to log, debug, or observe error values
1090
+ * - You want to perform side effects on errors in a pipeline
1091
+ * - You need to report errors to external systems (logging, monitoring)
1092
+ * - You're debugging and want to inspect errors without breaking the chain
1093
+ *
1094
+ * ## Why Use This
1095
+ *
1096
+ * - **Non-breaking**: Doesn't change the Result, just performs side effect
1097
+ * - **Composable**: Can be inserted anywhere in a pipeline
1098
+ * - **Type-preserving**: Returns the same Result type
1099
+ * - **Lazy**: Side effect only runs if Result is an error
1100
+ *
1101
+ * @param r - The Result to tap
1102
+ * @param fn - Side effect function called with the error and optional cause (return value ignored)
1103
+ * @returns The original Result unchanged (for chaining)
1104
+ *
1105
+ * @example
1106
+ * ```typescript
1107
+ * // Log errors
1108
+ * const logged = tapError(result, (error, cause) => {
1109
+ * console.error('Error:', error, cause);
1110
+ * });
1111
+ *
1112
+ * // Report to error tracking
1113
+ * const tracked = tapError(result, (error, cause) => {
1114
+ * errorTracker.report(error, cause);
1115
+ * });
1116
+ *
1117
+ * // Debug in pipeline
1118
+ * const debugged = pipe(
1119
+ * operation(),
1120
+ * r => tapError(r, (err, cause) => console.error('Failed:', err)),
1121
+ * r => mapError(r, err => 'FORMATTED_ERROR')
1122
+ * );
1123
+ * ```
1124
+ */
1125
+ declare function tapError<T, E, C>(r: Result<T, E, C>, fn: (error: E, cause?: C) => void): Result<T, E, C>;
1126
+ /**
1127
+ * Transforms the success value of a Result, catching any errors thrown by the transform.
1128
+ *
1129
+ * ## When to Use
1130
+ *
1131
+ * Use `mapTry()` when:
1132
+ * - Your transform function might throw exceptions
1133
+ * - You want to convert transform errors to typed errors
1134
+ * - You're working with libraries that throw (e.g., JSON.parse, Date parsing)
1135
+ * - You need to handle both Result errors and transform exceptions
1136
+ *
1137
+ * ## Why Use This Instead of `map`
1138
+ *
1139
+ * - **Exception-safe**: Catches exceptions from the transform function
1140
+ * - **Error mapping**: Converts thrown exceptions to typed errors
1141
+ * - **Dual error handling**: Handles both Result errors and transform exceptions
1142
+ *
1143
+ * @param result - The Result to transform
1144
+ * @param transform - Function to transform the success value (may throw exceptions)
1145
+ * @param onError - Function to map thrown exceptions to a typed error
1146
+ * @returns A Result with:
1147
+ * - Transformed value if both Result and transform succeed
1148
+ * - Original error if Result was an error
1149
+ * - Transform error if transform threw an exception
1150
+ *
1151
+ * @example
1152
+ * ```typescript
1153
+ * // Safe JSON parsing
1154
+ * const parsed = mapTry(
1155
+ * ok('{"key": "value"}'),
1156
+ * JSON.parse,
1157
+ * () => 'PARSE_ERROR' as const
1158
+ * );
1159
+ *
1160
+ * // Safe date parsing
1161
+ * const date = mapTry(
1162
+ * ok('2024-01-01'),
1163
+ * str => new Date(str),
1164
+ * () => 'INVALID_DATE' as const
1165
+ * );
1166
+ *
1167
+ * // Transform with error details
1168
+ * const processed = mapTry(
1169
+ * result,
1170
+ * value => riskyTransform(value),
1171
+ * (cause) => ({ type: 'TRANSFORM_ERROR' as const, cause })
1172
+ * );
1173
+ * ```
1174
+ */
1175
+ declare function mapTry<T, U, E, F, C>(result: Result<T, E, C>, transform: (value: T) => U, onError: (cause: unknown) => F): Result<U, E | F, C | unknown>;
1176
+ /**
1177
+ * Transforms the error value of a Result, catching any errors thrown by the transform.
1178
+ *
1179
+ * ## When to Use
1180
+ *
1181
+ * Use `mapErrorTry()` when:
1182
+ * - Your error transform function might throw exceptions
1183
+ * - You're doing complex error transformations (e.g., string formatting, object construction)
1184
+ * - You want to handle both Result errors and transform exceptions
1185
+ * - You need to safely normalize error types
1186
+ *
1187
+ * ## Why Use This Instead of `mapError`
1188
+ *
1189
+ * - **Exception-safe**: Catches exceptions from the error transform function
1190
+ * - **Error mapping**: Converts thrown exceptions to typed errors
1191
+ * - **Dual error handling**: Handles both Result errors and transform exceptions
1192
+ *
1193
+ * @param result - The Result to transform
1194
+ * @param transform - Function to transform the error value (may throw exceptions)
1195
+ * @param onError - Function to map thrown exceptions to a typed error
1196
+ * @returns A Result with:
1197
+ * - Original value if Result was successful
1198
+ * - Transformed error if both Result was error and transform succeeded
1199
+ * - Transform error if transform threw an exception
1200
+ *
1201
+ * @example
1202
+ * ```typescript
1203
+ * // Safe error formatting
1204
+ * const formatted = mapErrorTry(
1205
+ * err('not_found'),
1206
+ * e => e.toUpperCase(), // Might throw if e is not a string
1207
+ * () => 'FORMAT_ERROR' as const
1208
+ * );
1209
+ *
1210
+ * // Complex error transformation
1211
+ * const normalized = mapErrorTry(
1212
+ * result,
1213
+ * error => ({ type: 'NORMALIZED', message: String(error) }),
1214
+ * () => 'TRANSFORM_ERROR' as const
1215
+ * );
1216
+ * ```
1217
+ */
1218
+ declare function mapErrorTry<T, E, F, G, C>(result: Result<T, E, C>, transform: (error: E) => F, onError: (cause: unknown) => G): Result<T, F | G, C | unknown>;
1219
+ type AllValues<T extends readonly Result<unknown, unknown, unknown>[]> = {
1220
+ [K in keyof T]: T[K] extends Result<infer V, unknown, unknown> ? V : never;
1221
+ };
1222
+ type AllErrors<T extends readonly Result<unknown, unknown, unknown>[]> = {
1223
+ [K in keyof T]: T[K] extends Result<unknown, infer E, unknown> ? E : never;
1224
+ }[number];
1225
+ type AllCauses<T extends readonly Result<unknown, unknown, unknown>[]> = {
1226
+ [K in keyof T]: T[K] extends Result<unknown, unknown, infer C> ? C : never;
1227
+ }[number];
1228
+ /**
1229
+ * Combines multiple Results into one, requiring all to succeed.
1230
+ *
1231
+ * ## When to Use
1232
+ *
1233
+ * Use `all()` when:
1234
+ * - You have multiple independent operations that all must succeed
1235
+ * - You want to short-circuit on the first error (fail-fast)
1236
+ * - You need all values together (e.g., combining API responses)
1237
+ * - Performance matters (stops on first error, doesn't wait for all)
1238
+ *
1239
+ * ## Why Use This
1240
+ *
1241
+ * - **Fail-fast**: Stops immediately on first error (better performance)
1242
+ * - **Type-safe**: TypeScript infers the array type from input
1243
+ * - **Short-circuit**: Doesn't evaluate remaining Results after error
1244
+ * - **Composable**: Can be chained with other operations
1245
+ *
1246
+ * ## Important
1247
+ *
1248
+ * - **Short-circuits**: Returns first error immediately, doesn't wait for all Results
1249
+ * - **All must succeed**: If any Result fails, the entire operation fails
1250
+ * - **Use `allSettled`**: If you need to collect all errors (e.g., form validation)
1251
+ *
1252
+ * @param results - Array of Results to combine (all must succeed)
1253
+ * @returns A Result with an array of all success values, or the first error encountered
1254
+ *
1255
+ * @example
1256
+ * ```typescript
1257
+ * // Combine multiple successful Results
1258
+ * const combined = all([ok(1), ok(2), ok(3)]);
1259
+ * // combined: { ok: true, value: [1, 2, 3] }
1260
+ *
1261
+ * // Short-circuits on first error
1262
+ * const error = all([ok(1), err('ERROR'), ok(3)]);
1263
+ * // error: { ok: false, error: 'ERROR' }
1264
+ * // Note: ok(3) is never evaluated
1265
+ *
1266
+ * // Combine API responses
1267
+ * const data = all([
1268
+ * fetchUser(id),
1269
+ * fetchPosts(id),
1270
+ * fetchComments(id)
1271
+ * ]);
1272
+ * // data.value: [user, posts, comments] if all succeed
1273
+ * ```
1274
+ */
1275
+ declare function all<const T extends readonly Result<unknown, unknown, unknown>[]>(results: T): Result<AllValues<T>, AllErrors<T>, AllCauses<T>>;
1276
+ /**
1277
+ * Combines multiple Results or Promises of Results into one (async version of `all`).
1278
+ *
1279
+ * ## When to Use
1280
+ *
1281
+ * Use `allAsync()` when:
1282
+ * - You have multiple async operations that all must succeed
1283
+ * - You want to run operations in parallel (better performance)
1284
+ * - You want to short-circuit on the first error (fail-fast)
1285
+ * - You need all values together from parallel operations
1286
+ *
1287
+ * ## Why Use This Instead of `all`
1288
+ *
1289
+ * - **Parallel execution**: All Promises start immediately (faster)
1290
+ * - **Async support**: Works with Promises and AsyncResults
1291
+ * - **Promise rejection handling**: Converts Promise rejections to `PromiseRejectedError`
1292
+ *
1293
+ * ## Important
1294
+ *
1295
+ * - **Short-circuits**: Returns first error immediately, cancels remaining operations
1296
+ * - **Parallel**: All operations start simultaneously (unlike sequential `andThen`)
1297
+ * - **Use `allSettledAsync`**: If you need to collect all errors
1298
+ *
1299
+ * @param results - Array of Results or Promises of Results to combine (all must succeed)
1300
+ * @returns A Promise resolving to a Result with an array of all success values, or the first error
1301
+ *
1302
+ * @example
1303
+ * ```typescript
1304
+ * // Parallel API calls
1305
+ * const combined = await allAsync([
1306
+ * fetchUser('1'),
1307
+ * fetchPosts('1'),
1308
+ * fetchComments('1')
1309
+ * ]);
1310
+ * // All three calls start simultaneously
1311
+ * // combined: { ok: true, value: [user, posts, comments] } if all succeed
1312
+ *
1313
+ * // Mix Results and Promises
1314
+ * const data = await allAsync([
1315
+ * ok(cachedUser), // Already resolved
1316
+ * fetchPosts(userId), // Promise
1317
+ * ]);
1318
+ * ```
1319
+ */
1320
+ declare function allAsync<const T extends readonly (Result<unknown, unknown, unknown> | Promise<Result<unknown, unknown, unknown>>)[]>(results: T): Promise<Result<{
1321
+ [K in keyof T]: T[K] extends Result<infer V, unknown, unknown> | Promise<Result<infer V, unknown, unknown>> ? V : never;
1322
+ }, {
1323
+ [K in keyof T]: T[K] extends Result<unknown, infer E, unknown> | Promise<Result<unknown, infer E, unknown>> ? E : never;
1324
+ }[number] | PromiseRejectedError, {
1325
+ [K in keyof T]: T[K] extends Result<unknown, unknown, infer C> | Promise<Result<unknown, unknown, infer C>> ? C : never;
1326
+ }[number] | PromiseRejectionCause>>;
1327
+ type SettledError<E, C = unknown> = {
1328
+ error: E;
1329
+ cause?: C;
1330
+ };
1331
+ type AllSettledResult<T extends readonly Result<unknown, unknown, unknown>[]> = Result<AllValues<T>, SettledError<AllErrors<T>, AllCauses<T>>[]>;
1332
+ /**
1333
+ * Combines multiple Results, collecting all errors instead of short-circuiting.
1334
+ *
1335
+ * ## When to Use
1336
+ *
1337
+ * Use `allSettled()` when:
1338
+ * - You need to see ALL errors, not just the first one
1339
+ * - You're doing form validation (show all field errors)
1340
+ * - You want to collect partial results (some succeed, some fail)
1341
+ * - You need to process all Results regardless of failures
1342
+ *
1343
+ * ## Why Use This Instead of `all`
1344
+ *
1345
+ * - **Collects all errors**: Returns array of all errors, not just first
1346
+ * - **No short-circuit**: Evaluates all Results even if some fail
1347
+ * - **Partial success**: Can see which operations succeeded and which failed
1348
+ * - **Better UX**: Show users all validation errors at once
1349
+ *
1350
+ * ## Important
1351
+ *
1352
+ * - **No short-circuit**: All Results are evaluated (slower if many fail early)
1353
+ * - **Error array**: Returns array of `{ error, cause }` objects, not single error
1354
+ * - **Use `all`**: If you want fail-fast behavior (better performance)
1355
+ *
1356
+ * @param results - Array of Results to combine (all are evaluated)
1357
+ * @returns A Result with:
1358
+ * - Array of all success values if all succeed
1359
+ * - Array of `{ error, cause }` objects if any fail
1360
+ *
1361
+ * @example
1362
+ * ```typescript
1363
+ * // Form validation - show all errors
1364
+ * const validated = allSettled([
1365
+ * validateEmail(email),
1366
+ * validatePassword(password),
1367
+ * validateAge(age),
1368
+ * ]);
1369
+ * // If email and password fail:
1370
+ * // { ok: false, error: [
1371
+ * // { error: 'INVALID_EMAIL' },
1372
+ * // { error: 'WEAK_PASSWORD' }
1373
+ * // ]}
1374
+ *
1375
+ * // Collect partial results
1376
+ * const results = allSettled([
1377
+ * fetchUser('1'), // succeeds
1378
+ * fetchUser('2'), // fails
1379
+ * fetchUser('3'), // succeeds
1380
+ * ]);
1381
+ * // Can see which succeeded and which failed
1382
+ * ```
1383
+ */
1384
+ declare function allSettled<const T extends readonly Result<unknown, unknown, unknown>[]>(results: T): AllSettledResult<T>;
1385
+ /**
1386
+ * Splits an array of Results into separate arrays of success values and errors.
1387
+ *
1388
+ * ## When to Use
1389
+ *
1390
+ * Use `partition()` when:
1391
+ * - You have an array of Results and need to separate successes from failures
1392
+ * - You want to process successes and errors separately
1393
+ * - You're collecting results from multiple operations (some may fail)
1394
+ * - You need to handle partial success scenarios
1395
+ *
1396
+ * ## Why Use This
1397
+ *
1398
+ * - **Simple separation**: One call splits successes and errors
1399
+ * - **Type-safe**: TypeScript knows `values` is `T[]` and `errors` is `E[]`
1400
+ * - **No unwrapping**: Doesn't require manual `if (r.ok)` checks
1401
+ * - **Preserves order**: Maintains original array order in both arrays
1402
+ *
1403
+ * ## Common Pattern
1404
+ *
1405
+ * Often used after `Promise.all()` with Results:
1406
+ * ```typescript
1407
+ * const results = await Promise.all(ids.map(id => fetchUser(id)));
1408
+ * const { values: users, errors } = partition(results);
1409
+ * // Process successful users, handle errors separately
1410
+ * ```
1411
+ *
1412
+ * @param results - Array of Results to partition
1413
+ * @returns An object with:
1414
+ * - `values`: Array of all success values (type `T[]`)
1415
+ * - `errors`: Array of all error values (type `E[]`)
1416
+ *
1417
+ * @example
1418
+ * ```typescript
1419
+ * // Split successes and errors
1420
+ * const results = [ok(1), err('ERROR_1'), ok(3), err('ERROR_2')];
1421
+ * const { values, errors } = partition(results);
1422
+ * // values: [1, 3]
1423
+ * // errors: ['ERROR_1', 'ERROR_2']
1424
+ *
1425
+ * // Process batch operations
1426
+ * const userResults = await Promise.all(userIds.map(id => fetchUser(id)));
1427
+ * const { values: users, errors: fetchErrors } = partition(userResults);
1428
+ *
1429
+ * // Process successful users
1430
+ * users.forEach(user => processUser(user));
1431
+ *
1432
+ * // Handle errors
1433
+ * fetchErrors.forEach(error => logError(error));
1434
+ * ```
1435
+ */
1436
+ declare function partition<T, E, C>(results: readonly Result<T, E, C>[]): {
1437
+ values: T[];
1438
+ errors: E[];
1439
+ };
1440
+ type AnyValue<T extends readonly Result<unknown, unknown, unknown>[]> = T[number] extends Result<infer U, unknown, unknown> ? U : never;
1441
+ type AnyErrors<T extends readonly Result<unknown, unknown, unknown>[]> = {
1442
+ -readonly [K in keyof T]: T[K] extends Result<unknown, infer E, unknown> ? E : never;
1443
+ }[number];
1444
+ type AnyCauses<T extends readonly Result<unknown, unknown, unknown>[]> = {
1445
+ -readonly [K in keyof T]: T[K] extends Result<unknown, unknown, infer C> ? C : never;
1446
+ }[number];
1447
+ /**
1448
+ * Returns the first successful Result from an array (succeeds fast).
1449
+ *
1450
+ * ## When to Use
1451
+ *
1452
+ * Use `any()` when:
1453
+ * - You have multiple fallback options and need the first that succeeds
1454
+ * - You're trying multiple strategies (e.g., cache → DB → API)
1455
+ * - You want fail-fast success (stops on first success)
1456
+ * - You have redundant data sources and any one will do
1457
+ *
1458
+ * ## Why Use This
1459
+ *
1460
+ * - **Succeeds fast**: Returns immediately on first success (better performance)
1461
+ * - **Fallback pattern**: Perfect for trying multiple options
1462
+ * - **Short-circuits**: Stops evaluating after first success
1463
+ * - **Type-safe**: TypeScript infers the success type
1464
+ *
1465
+ * ## Important
1466
+ *
1467
+ * - **First success wins**: Returns first successful Result, ignores rest
1468
+ * - **All errors**: If all fail, returns first error (not all errors)
1469
+ * - **Empty array**: Returns `EmptyInputError` if array is empty
1470
+ * - **Use `all`**: If you need ALL to succeed
1471
+ *
1472
+ * @param results - Array of Results to check (evaluated in order)
1473
+ * @returns The first successful Result, or first error if all fail, or `EmptyInputError` if empty
1474
+ *
1475
+ * @example
1476
+ * ```typescript
1477
+ * // Try multiple fallback strategies
1478
+ * const data = any([
1479
+ * fetchFromCache(id),
1480
+ * fetchFromDB(id),
1481
+ * fetchFromAPI(id)
1482
+ * ]);
1483
+ * // Returns first that succeeds
1484
+ *
1485
+ * // Try multiple formats
1486
+ * const parsed = any([
1487
+ * parseJSON(input),
1488
+ * parseXML(input),
1489
+ * parseYAML(input)
1490
+ * ]);
1491
+ *
1492
+ * // All errors case
1493
+ * const allErrors = any([err('A'), err('B'), err('C')]);
1494
+ * // allErrors: { ok: false, error: 'A' } (first error)
1495
+ * ```
1496
+ */
1497
+ declare function any<const T extends readonly Result<unknown, unknown, unknown>[]>(results: T): Result<AnyValue<T>, AnyErrors<T> | EmptyInputError, AnyCauses<T>>;
1498
+ type AnyAsyncValue<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = Awaited<T[number]> extends Result<infer U, unknown, unknown> ? U : never;
1499
+ type AnyAsyncErrors<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = {
1500
+ -readonly [K in keyof T]: Awaited<T[K]> extends Result<unknown, infer E, unknown> ? E : never;
1501
+ }[number];
1502
+ type AnyAsyncCauses<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = {
1503
+ -readonly [K in keyof T]: Awaited<T[K]> extends Result<unknown, unknown, infer C> ? C : never;
1504
+ }[number];
1505
+ /**
1506
+ * Returns the first successful Result from an array of Results or Promises (async version of `any`).
1507
+ *
1508
+ * ## When to Use
1509
+ *
1510
+ * Use `anyAsync()` when:
1511
+ * - You have multiple async fallback options and need the first that succeeds
1512
+ * - You're trying multiple async strategies in parallel (cache → DB → API)
1513
+ * - You want fail-fast success from parallel operations
1514
+ * - You have redundant async data sources and any one will do
1515
+ *
1516
+ * ## Why Use This Instead of `any`
1517
+ *
1518
+ * - **Parallel execution**: All Promises start immediately (faster)
1519
+ * - **Async support**: Works with Promises and AsyncResults
1520
+ * - **Promise rejection handling**: Converts Promise rejections to `PromiseRejectedError`
1521
+ *
1522
+ * ## Important
1523
+ *
1524
+ * - **First success wins**: Returns first successful Result (from any Promise)
1525
+ * - **Parallel**: All operations run simultaneously
1526
+ * - **All errors**: If all fail, returns first error encountered
1527
+ *
1528
+ * @param results - Array of Results or Promises of Results to check (all start in parallel)
1529
+ * @returns A Promise resolving to the first successful Result, or first error if all fail
1530
+ *
1531
+ * @example
1532
+ * ```typescript
1533
+ * // Try multiple async fallbacks in parallel
1534
+ * const data = await anyAsync([
1535
+ * fetchFromCache(id), // Fastest wins
1536
+ * fetchFromDB(id),
1537
+ * fetchFromAPI(id)
1538
+ * ]);
1539
+ *
1540
+ * // Try multiple API endpoints
1541
+ * const response = await anyAsync([
1542
+ * fetch('/api/v1/data'),
1543
+ * fetch('/api/v2/data'),
1544
+ * fetch('/backup-api/data')
1545
+ * ]);
1546
+ * ```
1547
+ */
1548
+ declare function anyAsync<const T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]>(results: T): Promise<Result<AnyAsyncValue<T>, AnyAsyncErrors<T> | EmptyInputError | PromiseRejectedError, AnyAsyncCauses<T> | PromiseRejectionCause>>;
1549
+ type AllAsyncValues<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = {
1550
+ [K in keyof T]: Awaited<T[K]> extends Result<infer V, unknown, unknown> ? V : never;
1551
+ };
1552
+ type AllAsyncErrors<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = {
1553
+ [K in keyof T]: Awaited<T[K]> extends Result<unknown, infer E, unknown> ? E : never;
1554
+ }[number];
1555
+ type AllAsyncCauses<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = {
1556
+ [K in keyof T]: Awaited<T[K]> extends Result<unknown, unknown, infer C> ? C : never;
1557
+ }[number];
1558
+ /**
1559
+ * Combines multiple Results or Promises of Results, collecting all errors (async version of `allSettled`).
1560
+ *
1561
+ * ## When to Use
1562
+ *
1563
+ * Use `allSettledAsync()` when:
1564
+ * - You have multiple async operations and need ALL errors
1565
+ * - You're doing async form validation (show all field errors)
1566
+ * - You want to run operations in parallel and collect all results
1567
+ * - You need partial results from parallel operations
1568
+ *
1569
+ * ## Why Use This Instead of `allSettled`
1570
+ *
1571
+ * - **Parallel execution**: All Promises start immediately (faster)
1572
+ * - **Async support**: Works with Promises and AsyncResults
1573
+ * - **Promise rejection handling**: Converts Promise rejections to `PromiseRejectedError`
1574
+ *
1575
+ * ## Important
1576
+ *
1577
+ * - **No short-circuit**: All operations complete (even if some fail)
1578
+ * - **Parallel**: All operations run simultaneously
1579
+ * - **Error array**: Returns array of `{ error, cause }` objects
1580
+ *
1581
+ * @param results - Array of Results or Promises of Results to combine (all are evaluated)
1582
+ * @returns A Promise resolving to a Result with:
1583
+ * - Array of all success values if all succeed
1584
+ * - Array of `{ error, cause }` objects if any fail
1585
+ *
1586
+ * @example
1587
+ * ```typescript
1588
+ * // Async form validation
1589
+ * const validated = await allSettledAsync([
1590
+ * validateEmailAsync(email),
1591
+ * validatePasswordAsync(password),
1592
+ * checkUsernameAvailableAsync(username),
1593
+ * ]);
1594
+ *
1595
+ * // Parallel API calls with error collection
1596
+ * const results = await allSettledAsync([
1597
+ * fetchUser('1'),
1598
+ * fetchUser('2'),
1599
+ * fetchUser('3'),
1600
+ * ]);
1601
+ * // Can see which succeeded and which failed
1602
+ * ```
1603
+ */
1604
+ declare function allSettledAsync<const T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]>(results: T): Promise<Result<AllAsyncValues<T>, SettledError<AllAsyncErrors<T> | PromiseRejectedError, AllAsyncCauses<T> | PromiseRejectionCause>[]>>;
1605
+
1606
+ export { type AsyncResult, type CauseOf, EARLY_EXIT_SYMBOL, type EarlyExit, type EmptyInputError, type ErrorOf, type Errors, type ExtractCause, type ExtractError, type ExtractValue, type MaybeAsyncResult, type PromiseRejectedError, type PromiseRejectionCause, type Result, type RunOptions, type RunOptionsWithCatch, type RunOptionsWithoutCatch, type RunStep, type SettledError, type StepFailureMeta, type StepOptions, type UnexpectedCause, type UnexpectedError, type UnexpectedStepFailureCause, UnwrapError, type WorkflowEvent, all, allAsync, allSettled, allSettledAsync, andThen, any, anyAsync, createEarlyExit, err, from, fromNullable, fromPromise, isEarlyExit, isErr, isOk, isUnexpectedError, map, mapError, mapErrorTry, mapTry, match, ok, partition, run, tap, tapError, tryAsync, unwrap, unwrapOr, unwrapOrElse };