1/**
2 * Models a value that has already succeeded or failed.
3 *
4 * A `Result<A, E>` is `Success<A, E>` when a value is available and
5 * `Failure<A, E>` when an error is available. It is plain data, so inspecting
6 * or transforming it does not run side effects. This module includes helpers
7 * for creating, checking, mapping, combining, and extracting results, plus
8 * conversions to and from `Option` and nullable values.
9 *
10 * @since 4.0.0
11 */
12
13import * as Equivalence from "./Equivalence.ts"
14import type { LazyArg } from "./Function.ts"
15import { constNull, constUndefined, dual, identity } from "./Function.ts"
16import type { TypeLambda } from "./HKT.ts"
17import type { Inspectable } from "./Inspectable.ts"
18import * as doNotation from "./internal/doNotation.ts"
19import * as option_ from "./internal/option.ts"
20import * as InternalRecord from "./internal/record.ts"
21import * as result from "./internal/result.ts"
22import type { Option } from "./Option.ts"
23import type { Pipeable } from "./Pipeable.ts"
24import type { Predicate, Refinement } from "./Predicate.ts"
25import { isFunction } from "./Predicate.ts"
26import type { Covariant, NoInfer, NotFunction } from "./Types.ts"
27import type * as Unify from "./Unify.ts"
28import type * as Gen from "./Utils.ts"
29
30const TypeId = "~effect/Result"
31
32/**
33 * A value that is either `Success<A, E>` or `Failure<A, E>`.
34 *
35 * **When to use**
36 *
37 * Use when both success and failure should remain available as data and
38 * `Option` would lose failure information.
39 *
40 * **Details**
41 *
42 * - Use {@link succeed} / {@link fail} to construct
43 * - Use {@link match} to fold both branches
44 * - Use {@link isSuccess} / {@link isFailure} to narrow the type
45 *
46 * `E` defaults to `never`, so `Result<number>` means a result that cannot fail.
47 *
48 * **Example** (Creating and matching a Result)
49 *
50 * ```ts import.meta.vitest
51 * import { Result } from "effect"
52 *
53 * Result.match(Result.succeed(42), {
54 * onSuccess: (value) => `Success: ${value}`,
55 * onFailure: (error) => `Error: ${error}`
56 * }) // => "Success: 42"
57 * ```
58 *
59 * @see {@link succeed} / {@link fail} to create values
60 * @see {@link match} to fold both branches
61 * @see {@link isSuccess} / {@link isFailure} for type guards
62 *
63 * @category models
64 * @since 4.0.0
65 */
66export type Result<A, E = never> = Success<A, E> | Failure<A, E>
67
68/**
69 * The failure variant of {@link Result}. Wraps an error of type `E`.
70 *
71 * **Details**
72 *
73 * - Access the error via the `.failure` property
74 * - Use {@link isFailure} to narrow a `Result` to `Failure`
75 * - Create with {@link fail}
76 *
77 * **Example** (Accessing the failure value)
78 *
79 * ```ts import.meta.vitest
80 * import { Result } from "effect"
81 *
82 * const failure = Result.fail("Network error")
83 *
84 * if (Result.isFailure(failure)) {
85 * failure.failure // => "Network error"
86 * }
87 * ```
88 *
89 * @see {@link fail} to create a Failure
90 * @see {@link isFailure} to narrow the type
91 * @see {@link Success} for the other variant
92 *
93 * @category models
94 * @since 4.0.0
95 */
96export interface Failure<out A, out E> extends Pipeable, Inspectable {
97 readonly _tag: "Failure"
98 readonly _op: "Failure"
99 readonly failure: E
100 readonly [TypeId]: {
101 readonly _A: Covariant<E>
102 readonly _E: Covariant<A>
103 }
104 [Symbol.iterator](): ResultIterator<Result<A, E>>
105 [Unify.typeSymbol]?: unknown
106 [Unify.unifySymbol]?: ResultUnify<this>
107 [Unify.ignoreSymbol]?: ResultUnifyIgnore
108}
109
110/**
111 * Iterator protocol used to yield a `Result` inside {@link gen}, returning the
112 * success value type back to the generator.
113 *
114 * **When to use**
115 *
116 * Use when defining or typing `[Symbol.iterator]()` for `Result` values so
117 * `yield*` can pass the success value type back into `Result.gen`.
118 *
119 * @see {@link gen} for writing generator-based `Result` code that consumes this iterator protocol
120 *
121 * @category generators
122 * @since 4.0.0
123 */
124export interface ResultIterator<T extends Result<any, any>> {
125 next(
126 ...args: ReadonlyArray<any>
127 ): IteratorResult<T, Result.Success<T>>
128}
129
130/**
131 * The success variant of {@link Result}. Wraps a value of type `A`.
132 *
133 * **Details**
134 *
135 * - Access the value via the `.success` property
136 * - Use {@link isSuccess} to narrow a `Result` to `Success`
137 * - Create with {@link succeed}
138 *
139 * **Example** (Accessing the success value)
140 *
141 * ```ts import.meta.vitest
142 * import { Result } from "effect"
143 *
144 * const success = Result.succeed(42)
145 *
146 * if (Result.isSuccess(success)) {
147 * success.success // => 42
148 * }
149 * ```
150 *
151 * @see {@link succeed} to create a Success
152 * @see {@link isSuccess} to narrow the type
153 * @see {@link Failure} for the other variant
154 *
155 * @category models
156 * @since 4.0.0
157 */
158export interface Success<out A, out E> extends Pipeable, Inspectable {
159 readonly _tag: "Success"
160 readonly _op: "Success"
161 readonly success: A
162 readonly [TypeId]: {
163 readonly _A: Covariant<E>
164 readonly _E: Covariant<A>
165 }
166 [Symbol.iterator](): ResultIterator<Result<A, E>>
167 [Unify.typeSymbol]?: unknown
168 [Unify.unifySymbol]?: ResultUnify<this>
169 [Unify.ignoreSymbol]?: ResultUnifyIgnore
170}
171
172/**
173 * Type-level utility for unifying `Result` types in generic contexts.
174 *
175 * **Details**
176 *
177 * This is an internal interface used by the Effect type system. You typically
178 * do not need to reference it directly.
179 *
180 * @category models
181 * @since 4.0.0
182 */
183export interface ResultUnify<T extends { [Unify.typeSymbol]?: any }> {
184 Result?: () => T[Unify.typeSymbol] extends Result<infer A, infer E> | infer _ ? Result<A, E> : never
185}
186
187/**
188 * Marker interface for ignoring unification in `Result` types.
189 *
190 * **Details**
191 *
192 * This is an internal interface used by the Effect type system. You typically
193 * do not need to reference it directly.
194 *
195 * @category models
196 * @since 4.0.0
197 */
198export interface ResultUnifyIgnore {}
199
200/**
201 * Higher-kinded type representation for `Result`.
202 *
203 * **Details**
204 *
205 * Used internally to integrate `Result` with generic type-class utilities
206 * (e.g., `map`, `flatMap` abstractions). You typically do not need to
207 * reference this directly.
208 *
209 * @category utility types
210 * @since 4.0.0
211 */
212export interface ResultTypeLambda extends TypeLambda {
213 readonly type: Result<this["Target"], this["Out1"]>
214}
215
216/**
217 * Namespace containing type-level utilities for extracting the inner types
218 * of a `Result`.
219 *
220 * **Example** (Extracting inner types)
221 *
222 * ```ts import.meta.vitest
223 * import { Result } from "effect"
224 *
225 * type R = Result.Result<number, string>
226 *
227 * // number
228 * type A = Result.Result.Success<R>
229 *
230 * // string
231 * type E = Result.Result.Failure<R>
232 *
233 * const success: A = 42
234 * const failure: E = "error"
235 * ```
236 *
237 * @since 4.0.0
238 */
239export declare namespace Result {
240 /**
241 * Extracts the failure type `E` from `Result<A, E>`.
242 *
243 * @category utility types
244 * @since 4.0.0
245 */
246 export type Failure<T extends Result<any, any>> = [T] extends [Result<infer _A, infer _E>] ? _E : never
247 /**
248 * Extracts the success type `A` from `Result<A, E>`.
249 *
250 * @category utility types
251 * @since 4.0.0
252 */
253 export type Success<T extends Result<any, any>> = [T] extends [Result<infer _A, infer _E>] ? _A : never
254}
255
256/**
257 * Creates a `Result` holding a `Success` value.
258 *
259 * **Details**
260 *
261 * - Use when you have a value and want to lift it into the `Result` type
262 * - The error type `E` defaults to `never`
263 *
264 * **Example** (Wrapping a value)
265 *
266 * ```ts import.meta.vitest
267 * import { Result } from "effect"
268 *
269 * Result.succeed(42) // => Result.succeed(42)
270 * ```
271 *
272 * @see {@link fail} to create a Failure
273 * @see {@link void_ void} for a pre-built `Success<void>`
274 *
275 * @category constructors
276 * @since 4.0.0
277 */
278export const succeed: <A>(right: A) => Result<A> = result.succeed
279
280/**
281 * Creates a `Result` holding a `Failure` value.
282 *
283 * **When to use**
284 *
285 * Use to represent a failed `Result` with a typed failure value.
286 *
287 * **Details**
288 *
289 * - The success type `A` defaults to `never`
290 *
291 * **Example** (Creating a failure)
292 *
293 * ```ts import.meta.vitest
294 * import { Result } from "effect"
295 *
296 * Result.fail("Something went wrong") // => Result.fail("Something went wrong")
297 * ```
298 *
299 * @see {@link succeed} to create a Success
300 * @see {@link mapError} to transform the error
301 *
302 * @category constructors
303 * @since 4.0.0
304 */
305export const fail: <E>(left: E) => Result<never, E> = result.fail
306
307const void_: Result<void> = succeed(void 0)
308export {
309 /**
310 * Provides a pre-built successful `Result` that carries `undefined`.
311 *
312 * **When to use**
313 *
314 * Use when you need a successful `Result` value that signals completion
315 * without carrying meaningful data.
316 *
317 * **Details**
318 *
319 * This is equivalent to `Result.succeed(undefined)`, but reuses a shared
320 * `Success` wrapper instead of allocating one each time.
321 *
322 * **Example** (Referencing void results)
323 *
324 * ```ts import.meta.vitest
325 * import { Result } from "effect"
326 *
327 * const result: Result.Result<void> = Result.void // => Result.succeed(undefined)
328 * ```
329 *
330 * @see {@link succeed} to create a Success with a specific value
331 *
332 * @category constructors
333 * @since 3.13.0
334 */
335 void_ as void
336}
337
338/**
339 * Provides a pre-built failed `Result` whose failure value is `undefined`.
340 *
341 * **When to use**
342 *
343 * Use when you need a failed `Result` value that acts only as a control signal
344 * without failure data.
345 *
346 * **Details**
347 *
348 * This is equivalent to `Result.fail(undefined)` with type
349 * `Result<never, void>`, but reuses a shared `Failure` wrapper instead of
350 * allocating one each time.
351 *
352 * **Example** (Failing without a payload)
353 *
354 * ```ts import.meta.vitest
355 * import { Result } from "effect"
356 *
357 * Result.failVoid // => Result.fail(undefined)
358 * ```
359 *
360 * @see {@link fail} to create a Failure with a specific value
361 *
362 * @category constructors
363 * @since 4.0.0
364 */
365export const failVoid: Result<never, void> = fail(void 0)
366
367/**
368 * Converts a possibly `null` or `undefined` value into a `Result`.
369 *
370 * **When to use**
371 *
372 * Use when you need `null` or `undefined` input to become a `Failure` while
373 * present values remain available as `Success`.
374 *
375 * **Details**
376 *
377 * - Non-nullish values become `Success<NonNullable<A>>`
378 * - `null` or `undefined` becomes `Failure<E>` using the provided function
379 * - Supports both data-first and data-last (piped) usage
380 * - The `onNullish` callback receives the original value
381 *
382 * **Example** (Handling nullable values)
383 *
384 * ```ts import.meta.vitest
385 * import { Result } from "effect"
386 *
387 * Result.fromNullishOr(1, () => "fallback") // => Result.succeed(1)
388 *
389 * Result.fromNullishOr(null, () => "fallback") // => Result.fail("fallback")
390 * ```
391 *
392 * @see {@link fromOption} to convert from an Option
393 * @see {@link succeed} / {@link fail} for direct construction
394 *
395 * @category constructors
396 * @since 4.0.0
397 */
398export const fromNullishOr: {
399 <A, E>(onNullish: (a: A) => E): (self: A) => Result<NonNullable<A>, E>
400 <A, E>(self: A, onNullish: (a: A) => E): Result<NonNullable<A>, E>
401} = dual(
402 2,
403 <A, E>(self: A, onNullish: (a: A) => E): Result<NonNullable<A>, E> =>
404 self == null ? fail(onNullish(self)) : succeed(self)
405)
406
407/**
408 * Converts an `Option<A>` into a `Result<A, E>`.
409 *
410 * **When to use**
411 *
412 * Use when an existing `Option` should become a `Result`, preserving `Some` as
413 * success and turning `None` into a caller-provided failure.
414 *
415 * **Details**
416 *
417 * - `Some<A>` becomes `Success<A>`
418 * - `None` becomes `Failure<E>` using the provided function
419 * - Supports both data-first and data-last (piped) usage
420 *
421 * **Example** (Converting an Option to a Result)
422 *
423 * ```ts import.meta.vitest
424 * import { Option, Result } from "effect"
425 *
426 * Result.fromOption(Option.some(1), () => "missing") // => Result.succeed(1)
427 *
428 * Result.fromOption(Option.none(), () => "missing") // => Result.fail("missing")
429 * ```
430 *
431 * @see {@link getSuccess} to extract the success value as an Option
432 * @see {@link getFailure} to extract the failure value as an Option
433 * @see {@link fromNullishOr} to build a Result from nullable values
434 *
435 * @category constructors
436 * @since 2.0.0
437 */
438export const fromOption: {
439 <E>(onNone: () => E): <A>(self: Option<A>) => Result<A, E>
440 <A, E>(self: Option<A>, onNone: () => E): Result<A, E>
441} = result.fromOption
442
443const try_: {
444 <A, E>(
445 options: {
446 readonly try: LazyArg<A>
447 readonly catch: (error: unknown) => E
448 }
449 ): Result<A, E>
450 <A>(evaluate: LazyArg<A>): Result<A, unknown>
451} = <A, E>(
452 evaluate: LazyArg<A> | {
453 readonly try: LazyArg<A>
454 readonly catch: (error: unknown) => E
455 }
456) => {
457 if (isFunction(evaluate)) {
458 try {
459 return succeed(evaluate())
460 } catch (e) {
461 return fail(e)
462 }
463 } else {
464 try {
465 return succeed(evaluate.try())
466 } catch (e) {
467 return fail(evaluate.catch(e))
468 }
469 }
470}
471
472export {
473 /**
474 * Wraps a synchronous computation that may throw into a `Result` safely.
475 *
476 * **Details**
477 *
478 * - If the function returns normally, the result is `Success<A>`
479 * - If the function throws, the exception is caught and becomes `Failure<E>`
480 * - With a single function argument, the error type is `unknown`
481 * - With `{ try, catch }` options, the `catch` function maps the thrown value to `E`
482 *
483 * **Example** (Catching JSON parse errors)
484 *
485 * ```ts import.meta.vitest
486 * import { Result } from "effect"
487 *
488 * Result.try(() => JSON.parse('{"name": "Alice"}')) // => Result.succeed({ name: "Alice" })
489 *
490 * const err = Result.try({
491 * try: () => JSON.parse("not json"),
492 * catch: (e) => `Parse failed: ${e}`
493 * })
494 * Result.isFailure(err) // => true
495 * ```
496 *
497 * @see {@link succeed} / {@link fail} for direct construction
498 * @see {@link fromNullishOr} for nullable values
499 *
500 * @category constructors
501 * @since 2.0.0
502 */
503 try_ as try
504}
505
506/**
507 * Checks whether a value is a `Result` (either `Success` or `Failure`).
508 *
509 * **When to use**
510 *
511 * Use to validate unknown input before operating on it as a `Result`.
512 *
513 * **Details**
514 *
515 * - Returns `true` for both `Success` and `Failure` variants
516 * - Acts as a TypeScript type guard, narrowing to `Result<unknown, unknown>`
517 *
518 * **Example** (Checking if a value is a Result)
519 *
520 * ```ts import.meta.vitest
521 * import { Result } from "effect"
522 *
523 * Result.isResult(Result.succeed(1)) // => true
524 *
525 * Result.isResult({ value: 1 }) // => false
526 * ```
527 *
528 * @see {@link isSuccess} / {@link isFailure} to narrow to a specific variant
529 *
530 * @category guards
531 * @since 4.0.0
532 */
533export const isResult: (input: unknown) => input is Result<unknown, unknown> = result.isResult
534
535/**
536 * Checks whether a `Result` is a `Failure`.
537 *
538 * **When to use**
539 *
540 * Use to narrow a known `Result` to the `Failure` variant.
541 *
542 * **Details**
543 *
544 * - Acts as a TypeScript type guard, narrowing to `Failure<A, E>`
545 * - After narrowing, you can access `.failure` to read the error value
546 *
547 * **Example** (Narrowing to failure)
548 *
549 * ```ts import.meta.vitest
550 * import { Result } from "effect"
551 *
552 * const result = Result.fail("oops")
553 *
554 * if (Result.isFailure(result)) {
555 * result.failure // => "oops"
556 * }
557 * ```
558 *
559 * @see {@link isSuccess} for the opposite check
560 * @see {@link isResult} to check if a value is any Result
561 *
562 * @category guards
563 * @since 4.0.0
564 */
565export const isFailure: <A, E>(self: Result<A, E>) => self is Failure<A, E> = result.isFailure
566
567/**
568 * Checks whether a `Result` is a `Success`.
569 *
570 * **When to use**
571 *
572 * Use to narrow a known `Result` to the `Success` variant.
573 *
574 * **Details**
575 *
576 * - Acts as a TypeScript type guard, narrowing to `Success<A, E>`
577 * - After narrowing, you can access `.success` to read the value
578 *
579 * **Example** (Narrowing to success)
580 *
581 * ```ts import.meta.vitest
582 * import { Result } from "effect"
583 *
584 * const result = Result.succeed(42)
585 *
586 * if (Result.isSuccess(result)) {
587 * result.success // => 42
588 * }
589 * ```
590 *
591 * @see {@link isFailure} for the opposite check
592 * @see {@link isResult} to check if a value is any Result
593 *
594 * @category guards
595 * @since 4.0.0
596 */
597export const isSuccess: <A, E>(self: Result<A, E>) => self is Success<A, E> = result.isSuccess
598
599/**
600 * Extracts the success value as an `Option`, discarding the failure.
601 *
602 * **When to use**
603 *
604 * Use when you need to extract the success value from a `Result` as an
605 * `Option` and discard failure information.
606 *
607 * **Details**
608 *
609 * - `Success<A>` becomes `Some<A>`
610 * - `Failure<E>` becomes `None`
611 *
612 * **Example** (Extracting the success as an Option)
613 *
614 * ```ts import.meta.vitest
615 * import { Option, Result } from "effect"
616 *
617 * Result.getSuccess(Result.succeed("ok")) // => Option.some("ok")
618 *
619 * Result.getSuccess(Result.fail("err")) // => Option.none()
620 * ```
621 *
622 * @see {@link getFailure} to extract the error instead
623 * @see {@link fromOption} for the reverse conversion
624 *
625 * @category getters
626 * @since 4.0.0
627 */
628export const getSuccess: <A, E>(self: Result<A, E>) => Option<A> = result.getSuccess
629
630/**
631 * Extracts the failure value as an `Option`, discarding the success.
632 *
633 * **When to use**
634 *
635 * Use when you need to extract the failure value from a `Result` as an
636 * `Option` and discard successful values.
637 *
638 * **Details**
639 *
640 * - `Failure<E>` becomes `Some<E>`
641 * - `Success<A>` becomes `None`
642 *
643 * **Example** (Extracting the failure as an Option)
644 *
645 * ```ts import.meta.vitest
646 * import { Option, Result } from "effect"
647 *
648 * Result.getFailure(Result.succeed("ok")) // => Option.none()
649 *
650 * Result.getFailure(Result.fail("err")) // => Option.some("err")
651 * ```
652 *
653 * @see {@link getSuccess} to extract the success instead
654 * @see {@link fromOption} for the reverse conversion
655 *
656 * @category getters
657 * @since 4.0.0
658 */
659export const getFailure: <A, E>(self: Result<A, E>) => Option<E> = result.getFailure
660
661/**
662 * Creates an `Equivalence` for comparing two `Result` values.
663 *
664 * **Details**
665 *
666 * - Two `Success` values are equal when the `success` equivalence says so
667 * - Two `Failure` values are equal when the `failure` equivalence says so
668 * - A `Success` and a `Failure` are never equal
669 *
670 * **Example** (Comparing Results for equality)
671 *
672 * ```ts import.meta.vitest
673 * import { Equivalence, Result } from "effect"
674 *
675 * const eq = Result.makeEquivalence(
676 * Equivalence.strictEqual<number>(),
677 * Equivalence.strictEqual<string>()
678 * )
679 *
680 * eq(Result.succeed(1), Result.succeed(1)) // => true
681 *
682 * eq(Result.succeed(1), Result.fail("x")) // => false
683 * ```
684 *
685 * @category instances
686 * @since 4.0.0
687 */
688export const makeEquivalence = <A, E>(
689 success: Equivalence.Equivalence<A>,
690 failure: Equivalence.Equivalence<E>
691): Equivalence.Equivalence<Result<A, E>> =>
692 Equivalence.make((x, y) =>
693 isFailure(x) ?
694 isFailure(y) && failure(x.failure, y.failure) :
695 isSuccess(y) && success(x.success, y.success)
696 )
697
698/**
699 * Transforms both the success and failure channels of a `Result`.
700 *
701 * **When to use**
702 *
703 * Use to transform both success and failure values without changing whether the
704 * result succeeds or fails.
705 *
706 * **Details**
707 *
708 * - Applies `onSuccess` if the result is a `Success`
709 * - Applies `onFailure` if the result is a `Failure`
710 *
711 * **Example** (Mapping both channels)
712 *
713 * ```ts import.meta.vitest
714 * import { pipe, Result } from "effect"
715 *
716 * pipe(
717 * Result.succeed(1),
718 * Result.mapBoth({
719 * onSuccess: (n) => n + 1,
720 * onFailure: (e) => `Error: ${e}`
721 * })
722 * ) // => Result.succeed(2)
723 * ```
724 *
725 * @see {@link map} to transform only the success value
726 * @see {@link mapError} to transform only the error value
727 * @see {@link match} to fold into a single value
728 *
729 * @category mapping
730 * @since 2.0.0
731 */
732export const mapBoth: {
733 <E, E2, A, A2>(options: {
734 readonly onFailure: (left: E) => E2
735 readonly onSuccess: (right: A) => A2
736 }): (self: Result<A, E>) => Result<A2, E2>
737 <E, A, E2, A2>(self: Result<A, E>, options: {
738 readonly onFailure: (left: E) => E2
739 readonly onSuccess: (right: A) => A2
740 }): Result<A2, E2>
741} = dual(
742 2,
743 <E, A, E2, A2>(self: Result<A, E>, { onFailure, onSuccess }: {
744 readonly onFailure: (left: E) => E2
745 readonly onSuccess: (right: A) => A2
746 }): Result<A2, E2> => isFailure(self) ? fail(onFailure(self.failure)) : succeed(onSuccess(self.success))
747)
748
749/**
750 * Transforms the failure channel of a `Result`, leaving the success channel unchanged.
751 *
752 * **When to use**
753 *
754 * Use to transform only the failure channel while preserving success values.
755 *
756 * **Details**
757 *
758 * - If the result is a `Failure`, applies `f` to the error and returns a new `Failure`
759 * - If the result is a `Success`, returns it as-is
760 *
761 * **Example** (Adding context to an error)
762 *
763 * ```ts import.meta.vitest
764 * import { pipe, Result } from "effect"
765 *
766 * pipe(
767 * Result.fail("not found"),
768 * Result.mapError((e) => `Error: ${e}`)
769 * ) // => Result.fail("Error: not found")
770 * ```
771 *
772 * @see {@link map} to transform only the success value
773 * @see {@link mapBoth} to transform both channels
774 *
775 * @category mapping
776 * @since 4.0.0
777 */
778export const mapError: {
779 <E, E2>(f: (err: E) => E2): <A>(self: Result<A, E>) => Result<A, E2>
780 <A, E, E2>(self: Result<A, E>, f: (err: E) => E2): Result<A, E2>
781} = dual(
782 2,
783 <A, E, E2>(self: Result<A, E>, f: (err: E) => E2): Result<A, E2> =>
784 isFailure(self) ? fail(f(self.failure)) : self as unknown as Result<A, E2>
785)
786
787/**
788 * Transforms the success channel of a `Result`, leaving the failure channel unchanged.
789 *
790 * **When to use**
791 *
792 * Use to apply a transformation to the success value of a `Result` while
793 * preserving any existing failure.
794 *
795 * **Details**
796 *
797 * - If the result is a `Success`, applies `f` to the value and returns a new `Success`
798 * - If the result is a `Failure`, returns it as-is
799 * - Use {@link flatMap} if `f` returns a `Result` (to avoid nested Results)
800 *
801 * **Example** (Doubling the success value)
802 *
803 * ```ts import.meta.vitest
804 * import { pipe, Result } from "effect"
805 *
806 * pipe(
807 * Result.succeed(3),
808 * Result.map((n) => n * 2)
809 * ) // => Result.succeed(6)
810 * ```
811 *
812 * @see {@link mapError} to transform only the error value
813 * @see {@link mapBoth} to transform both channels
814 * @see {@link flatMap} when `f` returns a `Result`
815 *
816 * @category mapping
817 * @since 2.0.0
818 */
819export const map: {
820 <A, A2>(f: (ok: A) => A2): <E>(self: Result<A, E>) => Result<A2, E>
821 <A, E, A2>(self: Result<A, E>, f: (ok: A) => A2): Result<A2, E>
822} = dual(
823 2,
824 <A, E, A2>(self: Result<A, E>, f: (ok: A) => A2): Result<A2, E> =>
825 isSuccess(self) ? succeed(f(self.success)) : self as unknown as Result<A2, E>
826)
827
828/**
829 * Folds a `Result` into a single value by applying one of two functions.
830 *
831 * **When to use**
832 *
833 * Use when a `Result`'s success and failure branches should be collapsed into
834 * one plain output type.
835 *
836 * **Details**
837 *
838 * - Applies `onSuccess` if the result is a `Success`
839 * - Applies `onFailure` if the result is a `Failure`
840 * - Both branches must return the same type (or a common supertype)
841 *
842 * **Example** (Folding to a string)
843 *
844 * ```ts import.meta.vitest
845 * import { pipe, Result } from "effect"
846 *
847 * const format = Result.match({
848 * onSuccess: (n: number) => `Got ${n}`,
849 * onFailure: (e: string) => `Err: ${e}`
850 * })
851 *
852 * format(Result.succeed(42)) // => "Got 42"
853 *
854 * format(Result.fail("timeout")) // => "Err: timeout"
855 * ```
856 *
857 * @see {@link merge} to extract `A | E` without mapping
858 * @see {@link getOrElse} to unwrap only the success with a fallback
859 *
860 * @category pattern matching
861 * @since 2.0.0
862 */
863export const match: {
864 <E, B, A, C = B>(options: {
865 readonly onFailure: (error: E) => B
866 readonly onSuccess: (ok: A) => C
867 }): (self: Result<A, E>) => B | C
868 <A, E, B, C = B>(self: Result<A, E>, options: {
869 readonly onFailure: (error: E) => B
870 readonly onSuccess: (ok: A) => C
871 }): B | C
872} = dual(
873 2,
874 <A, E, B, C = B>(self: Result<A, E>, { onFailure, onSuccess }: {
875 readonly onFailure: (error: E) => B
876 readonly onSuccess: (ok: A) => C
877 }): B | C => isFailure(self) ? onFailure(self.failure) : onSuccess(self.success)
878)
879
880/**
881 * Lifts a value into a `Result` based on a predicate or refinement.
882 *
883 * **When to use**
884 *
885 * Use to construct a `Result` from a raw value guarded by a predicate or
886 * refinement.
887 *
888 * **Details**
889 *
890 * - If the predicate returns `true`, the value becomes `Success<A>`
891 * - If the predicate returns `false`, `orFailWith` produces the error for `Failure<E>`
892 * - Also accepts a `Refinement` to narrow the success type
893 * - Supports both data-first and data-last (piped) usage
894 *
895 * **Example** (Validating a number)
896 *
897 * ```ts import.meta.vitest
898 * import { pipe, Result } from "effect"
899 *
900 * pipe(
901 * 5,
902 * Result.liftPredicate(
903 * (n: number) => n > 0,
904 * (n) => `${n} is not positive`
905 * )
906 * ) // => Result.succeed(5)
907 * ```
908 *
909 * @see {@link filterOrFail} to validate a value that is already in a `Result`
910 * @see {@link fromNullishOr} for nullable-based construction
911 *
912 * @category constructors
913 * @since 3.4.0
914 */
915export const liftPredicate: {
916 <A, B extends A, E>(refinement: Refinement<A, B>, orFailWith: (a: A) => E): (a: A) => Result<B, E>
917 <B extends A, E, A = B>(
918 predicate: Predicate<A>,
919 orFailWith: (a: A) => E
920 ): (a: B) => Result<B, E>
921 <A, E, B extends A>(
922 self: A,
923 refinement: Refinement<A, B>,
924 orFailWith: (a: A) => E
925 ): Result<B, E>
926 <B extends A, E, A = B>(
927 self: B,
928 predicate: Predicate<A>,
929 orFailWith: (a: A) => E
930 ): Result<B, E>
931} = dual(
932 3,
933 <A, E>(a: A, predicate: Predicate<A>, orFailWith: (a: A) => E): Result<A, E> =>
934 predicate(a) ? succeed(a) : fail(orFailWith(a))
935)
936
937/**
938 * Validates the success value of a `Result` using a predicate, failing with a
939 * custom error if the predicate returns `false`.
940 *
941 * **When to use**
942 *
943 * Use to validate an already-successful `Result` value with a predicate or
944 * refinement.
945 *
946 * **Details**
947 *
948 * - If the result is already a `Failure`, it is returned as-is
949 * - If the predicate passes, the `Success` is returned unchanged
950 * - If the predicate fails, `orFailWith` produces the error for a new `Failure`
951 * - Also accepts a `Refinement` to narrow the success type
952 * - The error type of the output is the union of both error types
953 *
954 * **Example** (Filtering a success value)
955 *
956 * ```ts import.meta.vitest
957 * import { pipe, Result } from "effect"
958 *
959 * pipe(
960 * Result.succeed(0),
961 * Result.filterOrFail(
962 * (n) => n > 0,
963 * (n) => `${n} is not positive`
964 * )
965 * ) // => Result.fail("0 is not positive")
966 * ```
967 *
968 * @see {@link liftPredicate} to create a `Result` from a raw value with a predicate
969 * @see {@link flatMap} for general conditional chaining
970 *
971 * @category filtering
972 * @since 4.0.0
973 */
974export const filterOrFail: {
975 <A, B extends A, E2>(
976 refinement: Refinement<NoInfer<A>, B>,
977 orFailWith: (value: NoInfer<A>) => E2
978 ): <E>(self: Result<A, E>) => Result<B, E2 | E>
979 <A, E2>(
980 predicate: Predicate<NoInfer<A>>,
981 orFailWith: (value: NoInfer<A>) => E2
982 ): <E>(self: Result<A, E>) => Result<A, E2 | E>
983 <A, E, B extends A, E2>(
984 self: Result<A, E>,
985 refinement: Refinement<A, B>,
986 orFailWith: (value: A) => E2
987 ): Result<B, E | E2>
988 <A, E, E2>(self: Result<A, E>, predicate: Predicate<A>, orFailWith: (value: A) => E2): Result<A, E | E2>
989} = dual(3, <A, E, E2>(
990 self: Result<A, E>,
991 predicate: Predicate<A>,
992 orFailWith: (value: A) => E2
993): Result<A, E | E2> => flatMap(self, (a) => predicate(a) ? succeed(a) : fail(orFailWith(a))))
994
995/**
996 * Unwraps a `Result` into `A | E` by returning the inner value regardless
997 * of whether it is a success or failure.
998 *
999 * **Details**
1000 *
1001 * - `Success<A>` returns `A`
1002 * - `Failure<E>` returns `E`
1003 * - Useful when both channels share a compatible type
1004 *
1005 * **Example** (Extracting the inner value)
1006 *
1007 * ```ts import.meta.vitest
1008 * import { Result } from "effect"
1009 *
1010 * Result.merge(Result.succeed(42)) // => 42
1011 *
1012 * Result.merge(Result.fail("error")) // => "error"
1013 * ```
1014 *
1015 * @see {@link match} to map each branch to a common type
1016 * @see {@link getOrElse} to provide a fallback for failures
1017 *
1018 * @category getters
1019 * @since 2.0.0
1020 */
1021export const merge: <A, E>(self: Result<A, E>) => E | A = match({ onFailure: identity, onSuccess: identity })
1022
1023/**
1024 * Extracts the success value, or computes a fallback from the error.
1025 *
1026 * **When to use**
1027 *
1028 * Use when you need the success value from a `Result`, with a fallback computed
1029 * from the failure value.
1030 *
1031 * **Details**
1032 *
1033 * - `Success<A>` returns the inner value
1034 * - `Failure<E>` applies `onFailure` to the error and returns the result
1035 * - The return type is `A | A2` (union of both branches)
1036 *
1037 * **Example** (Providing a fallback)
1038 *
1039 * ```ts import.meta.vitest
1040 * import { Result } from "effect"
1041 *
1042 * Result.getOrElse(Result.succeed(1), () => 0) // => 1
1043 *
1044 * Result.getOrElse(Result.fail("err"), () => 0) // => 0
1045 * ```
1046 *
1047 * @see {@link getOrNull} / {@link getOrUndefined} for simpler fallbacks
1048 * @see {@link getOrThrow} to throw on failure
1049 * @see {@link match} to map both branches
1050 * @see {@link orElse} to recover with another Result instead of unwrapping
1051 *
1052 * @category getters
1053 * @since 2.0.0
1054 */
1055export const getOrElse: {
1056 <E, A2>(onFailure: (err: E) => A2): <A>(self: Result<A, E>) => A2 | A
1057 <A, E, A2>(self: Result<A, E>, onFailure: (err: E) => A2): A | A2
1058} = dual(
1059 2,
1060 <A, E, A2>(self: Result<A, E>, onFailure: (err: E) => A2): A | A2 =>
1061 isFailure(self) ? onFailure(self.failure) : self.success
1062)
1063
1064/**
1065 * Extracts the success value, or returns `null` on failure.
1066 *
1067 * **When to use**
1068 *
1069 * Use when you need to pass failed `Result` values to APIs that represent
1070 * absence as `null`.
1071 *
1072 * **Details**
1073 *
1074 * - `Success<A>` returns `A`
1075 * - `Failure<E>` returns `null`
1076 *
1077 * **Example** (Unwrapping to nullable)
1078 *
1079 * ```ts import.meta.vitest
1080 * import { Result } from "effect"
1081 *
1082 * Result.getOrNull(Result.succeed(1)) // => 1
1083 *
1084 * Result.getOrNull(Result.fail("err")) // => null
1085 * ```
1086 *
1087 * @see {@link getOrUndefined} to return `undefined` instead
1088 * @see {@link getOrElse} for a custom fallback
1089 *
1090 * @category getters
1091 * @since 2.0.0
1092 */
1093export const getOrNull: <A, E>(self: Result<A, E>) => A | null = getOrElse(constNull)
1094
1095/**
1096 * Extracts the success value, or returns `undefined` on failure.
1097 *
1098 * **When to use**
1099 *
1100 * Use when you need to pass failed `Result` values to APIs that represent
1101 * absence as `undefined`.
1102 *
1103 * **Details**
1104 *
1105 * - `Success<A>` returns `A`
1106 * - `Failure<E>` returns `undefined`
1107 *
1108 * **Example** (Unwrapping to optional)
1109 *
1110 * ```ts import.meta.vitest
1111 * import { Result } from "effect"
1112 *
1113 * Result.getOrUndefined(Result.succeed(1)) // => 1
1114 *
1115 * Result.getOrUndefined(Result.fail("err")) // => undefined
1116 * ```
1117 *
1118 * @see {@link getOrNull} to return `null` instead
1119 * @see {@link getOrElse} for a custom fallback
1120 *
1121 * @category getters
1122 * @since 2.0.0
1123 */
1124export const getOrUndefined: <A, E>(self: Result<A, E>) => A | undefined = getOrElse(constUndefined)
1125
1126/**
1127 * Extracts the success value or throws a custom error derived from the failure.
1128 *
1129 * **When to use**
1130 *
1131 * Use when converting a `Result` into a thrown exception with a custom error
1132 * message or error type.
1133 *
1134 * **Details**
1135 *
1136 * - `Success<A>` returns `A`
1137 * - `Failure<E>` throws the value returned by `onFailure(e)`
1138 *
1139 * **Example** (Throwing a custom error)
1140 *
1141 * ```ts import.meta.vitest
1142 * import { Result } from "effect"
1143 *
1144 * Result.getOrThrowWith(Result.succeed(1), () => new Error("fail")) // => 1
1145 *
1146 * const failure = Result.try({
1147 * try: () => Result.getOrThrowWith(
1148 * Result.fail("oops"),
1149 * (error) => new Error(`Unexpected: ${error}`)
1150 * ),
1151 * catch: (error) => (error as Error).message
1152 * })
1153 * Result.merge(failure) // => "Unexpected: oops"
1154 * ```
1155 *
1156 * @see {@link getOrThrow} to throw the raw failure value
1157 * @see {@link getOrElse} for a non-throwing alternative
1158 *
1159 * @category getters
1160 * @since 2.0.0
1161 */
1162export const getOrThrowWith: {
1163 <E>(onFailure: (err: E) => unknown): <A>(self: Result<A, E>) => A
1164 <A, E>(self: Result<A, E>, onFailure: (err: E) => unknown): A
1165} = dual(2, <A, E>(self: Result<A, E>, onFailure: (err: E) => unknown): A => {
1166 if (isSuccess(self)) {
1167 return self.success
1168 }
1169 throw onFailure(self.failure)
1170})
1171
1172/**
1173 * Extracts the success value or throws the raw failure value `E`.
1174 *
1175 * **When to use**
1176 *
1177 * Use when unchecked boundaries should turn failures into thrown exceptions.
1178 *
1179 * **Details**
1180 *
1181 * - `Success<A>` returns `A`
1182 * - `Failure<E>` throws `E` directly
1183 * - Use {@link getOrThrowWith} for a custom error object
1184 *
1185 * **Example** (Unwrapping or throwing)
1186 *
1187 * ```ts import.meta.vitest
1188 * import { Result } from "effect"
1189 *
1190 * Result.getOrThrow(Result.succeed(1)) // => 1
1191 *
1192 * const failure = Result.try(() => Result.getOrThrow(Result.fail("error")))
1193 * Result.merge(failure) // => "error"
1194 * ```
1195 *
1196 * @see {@link getOrThrowWith} for custom error mapping
1197 * @see {@link getOrElse} for a non-throwing alternative
1198 *
1199 * @category getters
1200 * @since 2.0.0
1201 */
1202export const getOrThrow: <A, E>(self: Result<A, E>) => A = getOrThrowWith(identity)
1203
1204/**
1205 * Returns the original `Result` if it is a `Success`, otherwise applies
1206 * `that` to the error and returns the resulting `Result`.
1207 *
1208 * **When to use**
1209 *
1210 * Use when a failure should recover into another `Result` while keeping
1211 * successes unchanged.
1212 *
1213 * **Details**
1214 *
1215 * - `Success<A>` is returned unchanged
1216 * - `Failure<E>` calls `that(e)` to produce a new `Result`
1217 *
1218 * **Example** (Recovering from a failure)
1219 *
1220 * ```ts import.meta.vitest
1221 * import { pipe, Result } from "effect"
1222 *
1223 * pipe(
1224 * Result.fail("primary failed"),
1225 * Result.orElse(() => Result.succeed(99))
1226 * ) // => Result.succeed(99)
1227 * ```
1228 *
1229 * @see {@link getOrElse} to unwrap with a fallback value (not a Result)
1230 * @see {@link mapError} to transform the error without recovering
1231 *
1232 * @category error handling
1233 * @since 2.0.0
1234 */
1235export const orElse: {
1236 <E, A2, E2>(that: (err: E) => Result<A2, E2>): <A>(self: Result<A, E>) => Result<A | A2, E2>
1237 <A, E, A2, E2>(self: Result<A, E>, that: (err: E) => Result<A2, E2>): Result<A | A2, E2>
1238} = dual(
1239 2,
1240 <A, E, A2, E2>(self: Result<A, E>, that: (err: E) => Result<A2, E2>): Result<A | A2, E2> =>
1241 isFailure(self) ? that(self.failure) : succeed(self.success)
1242)
1243
1244/**
1245 * Chains a function that returns a `Result` onto a successful value.
1246 *
1247 * **When to use**
1248 *
1249 * Use to sequence `Result`-returning computations that should short-circuit on
1250 * failure.
1251 *
1252 * **Details**
1253 *
1254 * - If `self` is a `Success`, applies `f` to the value and returns the resulting `Result`
1255 * - If `self` is a `Failure`, short-circuits and returns it unchanged
1256 * - The error types are merged into a union (`E | E2`)
1257 * - This is the monadic `bind` / `>>=` for `Result`
1258 *
1259 * **Example** (Validating sequentially)
1260 *
1261 * ```ts import.meta.vitest
1262 * import { pipe, Result } from "effect"
1263 *
1264 * pipe(
1265 * Result.succeed(5),
1266 * Result.flatMap((n) =>
1267 * n > 0 ? Result.succeed(n * 2) : Result.fail("not positive")
1268 * )
1269 * ) // => Result.succeed(10)
1270 * ```
1271 *
1272 * @see {@link andThen} for a more flexible variant that also accepts plain values
1273 * @see {@link map} when `f` does not return a `Result`
1274 *
1275 * @category sequencing
1276 * @since 2.0.0
1277 */
1278export const flatMap: {
1279 <A, A2, E2>(f: (a: A) => Result<A2, E2>): <E>(self: Result<A, E>) => Result<A2, E | E2>
1280 <A, E, A2, E2>(self: Result<A, E>, f: (a: A) => Result<A2, E2>): Result<A2, E | E2>
1281} = dual(
1282 2,
1283 <A, E, A2, E2>(self: Result<A, E>, f: (a: A) => Result<A2, E2>): Result<A2, E | E2> =>
1284 isFailure(self) ? fail(self.failure) : f(self.success)
1285)
1286
1287/**
1288 * Provides a flexible variant of {@link flatMap} that accepts multiple input shapes.
1289 *
1290 * **When to use**
1291 *
1292 * Use to sequence a next step that may be a `Result`, a function, or a plain
1293 * value.
1294 *
1295 * **Details**
1296 *
1297 * The second argument can be:
1298 * - A function `(a: A) => Result<A2, E2>` (same as `flatMap`)
1299 * - A function `(a: A) => A2` (auto-wrapped in `succeed`)
1300 * - A `Result<A2, E2>` value (ignores the success of `self`)
1301 * - A plain value `A2` (auto-wrapped in `succeed`, ignores `self`)
1302 *
1303 * If `self` is a `Failure`, the second argument is never evaluated.
1304 *
1305 * **Example** (Chaining Result values with different argument types)
1306 *
1307 * ```ts import.meta.vitest
1308 * import { pipe, Result } from "effect"
1309 *
1310 * // With a function returning a Result
1311 * const a = pipe(
1312 * Result.succeed(1),
1313 * Result.andThen((n) => Result.succeed(n + 1))
1314 * ) // => Result.succeed(2)
1315 *
1316 * // With a plain mapping function
1317 * const b = pipe(
1318 * Result.succeed(1),
1319 * Result.andThen((n) => n + 1)
1320 * ) // => Result.succeed(2)
1321 *
1322 * // With a constant value
1323 * const c = pipe(Result.succeed(1), Result.andThen("done")) // => Result.succeed("done")
1324 * ```
1325 *
1326 * @see {@link flatMap} for the stricter variant (function returning Result only)
1327 * @see {@link map} when you always return a plain value
1328 *
1329 * @category sequencing
1330 * @since 2.0.0
1331 */
1332export const andThen: {
1333 <A, A2, E2>(f: (a: A) => Result<A2, E2>): <E>(self: Result<A, E>) => Result<A2, E | E2>
1334 <A2, E2>(f: Result<A2, E2>): <A, E>(self: Result<A, E>) => Result<A2, E | E2>
1335 <A, A2>(f: (a: A) => A2): <E>(self: Result<A, E>) => Result<A2, E>
1336 <A2>(right: NotFunction<A2>): <A, E>(self: Result<A, E>) => Result<A2, E>
1337 <A, E, A2, E2>(self: Result<A, E>, f: (a: A) => Result<A2, E2>): Result<A2, E | E2>
1338 <A, E, A2, E2>(self: Result<A, E>, f: Result<A2, E2>): Result<A2, E | E2>
1339 <A, E, A2>(self: Result<A, E>, f: (a: A) => A2): Result<A2, E>
1340 <A, E, A2>(self: Result<A, E>, f: NotFunction<A2>): Result<A2, E>
1341} = dual(
1342 2,
1343 <A, E, A2, E2>(
1344 self: Result<A, E>,
1345 f: ((a: A) => Result<A2, E2> | A2) | Result<A2, E2> | A2
1346 ): Result<A2, E | E2> =>
1347 flatMap(self, (a) => {
1348 const out = isFunction(f) ? f(a) : f
1349 return isResult(out) ? out : succeed(out)
1350 })
1351)
1352
1353/**
1354 * Collects a structure of `Result`s into a single `Result` of collected values.
1355 *
1356 * **When to use**
1357 *
1358 * Use to collect independent `Result` values into one `Result` while preserving
1359 * the original structure.
1360 *
1361 * **Details**
1362 *
1363 * Accepts:
1364 * - A tuple/array: returns `Result` with a tuple/array of success values
1365 * - A struct (record): returns `Result` with a struct of success values
1366 * - An iterable: returns `Result` with an array of success values
1367 *
1368 * Short-circuits on the first `Failure` encountered; later elements are not inspected.
1369 *
1370 * **Example** (Collecting a tuple and a struct)
1371 *
1372 * ```ts import.meta.vitest
1373 * import { Result } from "effect"
1374 *
1375 * // Tuple
1376 * Result.all([Result.succeed(1), Result.succeed("two")]) // => Result.succeed([1, "two"])
1377 *
1378 * // Struct
1379 * Result.all({ x: Result.succeed(1), y: Result.fail("err") }) // => Result.fail("err")
1380 * ```
1381 *
1382 * @see {@link flatMap} for chaining two Results sequentially
1383 * @see {@link gen} for generator-based composition of multiple Results
1384 *
1385 * @category sequencing
1386 * @since 2.0.0
1387 */
1388// @ts-expect-error
1389export const all: <const I extends Iterable<Result<any, any>> | Record<string, Result<any, any>>>(
1390 input: I
1391) => [I] extends [ReadonlyArray<Result<any, any>>] ? Result<
1392 { -readonly [K in keyof I]: [I[K]] extends [Result<infer R, any>] ? R : never },
1393 I[number] extends never ? never : [I[number]] extends [Result<any, infer L>] ? L : never
1394 >
1395 : [I] extends [Iterable<Result<infer R, infer L>>] ? Result<Array<R>, L>
1396 : Result<
1397 { -readonly [K in keyof I]: [I[K]] extends [Result<infer R, any>] ? R : never },
1398 I[keyof I] extends never ? never : [I[keyof I]] extends [Result<any, infer L>] ? L : never
1399 > = (
1400 input: Iterable<Result<any, any>> | Record<string, Result<any, any>>
1401 ): Result<any, any> => {
1402 if (Symbol.iterator in input) {
1403 const out: Array<Result<any, any>> = []
1404 for (const e of input) {
1405 if (isFailure(e)) {
1406 return e
1407 }
1408 out.push(e.success)
1409 }
1410 return succeed(out)
1411 }
1412
1413 const out: Record<string, any> = {}
1414 for (const key of Object.keys(input)) {
1415 const e = input[key]
1416 if (isFailure(e)) {
1417 return e
1418 }
1419 InternalRecord.assignProperty(out, key, e.success)
1420 }
1421 return succeed(out)
1422 }
1423
1424/**
1425 * Swaps the success and failure channels of a `Result`.
1426 *
1427 * **When to use**
1428 *
1429 * Use to swap channels when failure-focused operations are easier through
1430 * success-oriented combinators.
1431 *
1432 * **Details**
1433 *
1434 * - `Success<A>` becomes `Failure<A>` (i.e., `Result<E, A>`)
1435 * - `Failure<E>` becomes `Success<E>` (i.e., `Result<E, A>`)
1436 * - Useful when you want to apply success-oriented operations (like `map`)
1437 * to the error channel, then flip back
1438 *
1439 * **Example** (Swapping channels)
1440 *
1441 * ```ts import.meta.vitest
1442 * import { Result } from "effect"
1443 *
1444 * Result.flip(Result.succeed(42)) // => Result.fail(42)
1445 *
1446 * Result.flip(Result.fail("error")) // => Result.succeed("error")
1447 * ```
1448 *
1449 * @see {@link mapError} to transform the error without swapping
1450 *
1451 * @category transforming
1452 * @since 2.0.0
1453 */
1454export const flip = <A, E>(self: Result<A, E>): Result<E, A> =>
1455 isFailure(self) ? succeed(self.failure) : fail(self.success)
1456
1457/**
1458 * Provides generator-based syntax for composing `Result` values sequentially.
1459 *
1460 * **When to use**
1461 *
1462 * Use when you need generator syntax to compose sequential `Result`
1463 * computations instead of nested `flatMap` calls.
1464 *
1465 * **Details**
1466 *
1467 * - Use `yield*` to unwrap a `Result` inside the generator; if any yielded
1468 * `Result` is a `Failure`, the generator short-circuits and returns that failure
1469 * - The return value of the generator is wrapped in `Success`
1470 * - Evaluated eagerly and synchronously (unlike `Effect.gen`)
1471 *
1472 * **Example** (Composing multiple Results)
1473 *
1474 * ```ts import.meta.vitest
1475 * import { Result } from "effect"
1476 *
1477 * Result.gen(function*() {
1478 * const a = yield* Result.succeed(1)
1479 * const b = yield* Result.succeed(2)
1480 * return a + b
1481 * }) // => Result.succeed(3)
1482 * ```
1483 *
1484 * @see {@link flatMap} for point-free sequential composition
1485 * @see {@link all} to collect multiple independent Results
1486 *
1487 * @category generators
1488 * @since 2.0.0
1489 */
1490export const gen: Gen.Gen<ResultTypeLambda> = (...args) => {
1491 const f = args.length === 1 ? args[0] : args[1].bind(args[0])
1492 const iterator = f()
1493 let state: IteratorResult<any> = iterator.next()
1494 while (!state.done) {
1495 const current = state.value
1496 if (isFailure(current)) {
1497 return current
1498 }
1499 state = iterator.next(current.success as never)
1500 }
1501 return succeed(state.value) as any
1502}
1503
1504// -------------------------------------------------------------------------------------
1505// do notation
1506// -------------------------------------------------------------------------------------
1507
1508/**
1509 * Provides the starting point for the "do notation" simulation with `Result`.
1510 *
1511 * **When to use**
1512 *
1513 * Use to start a `Result` do-notation pipeline from an empty successful record
1514 * before adding named fields from `Result`-producing computations and pure
1515 * computed values.
1516 *
1517 * **Details**
1518 *
1519 * Creates a `Result<{}>` (success with an empty object). Use with
1520 * {@link bind} to add `Result`-producing fields and {@link let_ let}
1521 * to add pure computed fields.
1522 *
1523 * **Example** (Building an object step by step)
1524 *
1525 * ```ts import.meta.vitest
1526 * import { pipe, Result } from "effect"
1527 *
1528 * pipe(
1529 * Result.Do,
1530 * Result.bind("x", () => Result.succeed(2)),
1531 * Result.bind("y", () => Result.succeed(3)),
1532 * Result.let("sum", ({ x, y }) => x + y)
1533 * ) // => Result.succeed({ x: 2, y: 3, sum: 5 })
1534 * ```
1535 *
1536 * @see {@link bind} to add Result-producing fields
1537 * @see {@link let_ let} to add pure computed fields
1538 * @see {@link gen} for an alternative generator-based syntax
1539 * @see {@link bindTo} for starting a do-notation chain from an existing Result
1540 *
1541 * @category constructors
1542 * @since 2.0.0
1543 */
1544export const Do: Result<{}> = succeed({})
1545
1546/**
1547 * Adds a named field to the do-notation accumulator by running a `Result`-producing
1548 * function that receives the current accumulated object.
1549 *
1550 * **When to use**
1551 *
1552 * Use when you need to add a `Result`-producing step to a `Result`
1553 * do-notation pipeline and store its successful value under a named field in
1554 * the accumulated object.
1555 *
1556 * **Details**
1557 *
1558 * - Short-circuits on the first `Failure`
1559 * - The field name must not collide with existing keys
1560 * - Use {@link let_ let} for pure (non-Result) computed fields
1561 *
1562 * **Example** (Binding Result values)
1563 *
1564 * ```ts import.meta.vitest
1565 * import { pipe, Result } from "effect"
1566 *
1567 * pipe(
1568 * Result.Do,
1569 * Result.bind("x", () => Result.succeed(2)),
1570 * Result.bind("y", ({ x }) => Result.succeed(x + 3))
1571 * ) // => Result.succeed({ x: 2, y: 5 })
1572 * ```
1573 *
1574 * @see {@link Do} to start the do-notation chain
1575 * @see {@link let_ let} for pure computed fields
1576 * @see {@link bindTo} to wrap an initial Result into a named field
1577 *
1578 * @category sequencing
1579 * @since 2.0.0
1580 */
1581export const bind: {
1582 <N extends string, A extends object, B, L2>(
1583 name: Exclude<N, keyof A>,
1584 f: (a: NoInfer<A>) => Result<B, L2>
1585 ): <L1>(self: Result<A, L1>) => Result<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, L1 | L2>
1586 <A extends object, L1, N extends string, B, L2>(
1587 self: Result<A, L1>,
1588 name: Exclude<N, keyof A>,
1589 f: (a: NoInfer<A>) => Result<B, L2>
1590 ): Result<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, L1 | L2>
1591} = doNotation.bind<ResultTypeLambda>(map, flatMap)
1592
1593/**
1594 * Wraps the success value of a `Result` into a named field, producing a
1595 * `Result<Record<N, A>>`.
1596 *
1597 * **When to use**
1598 *
1599 * Use to name the success value of an existing `Result` before continuing a
1600 * do-notation pipeline.
1601 *
1602 * **Details**
1603 *
1604 * This is typically used to start a do-notation chain from an existing
1605 * `Result`.
1606 *
1607 * **Example** (Wrapping a value into a named field)
1608 *
1609 * ```ts import.meta.vitest
1610 * import { pipe, Result } from "effect"
1611 *
1612 * pipe(
1613 * Result.succeed(42),
1614 * Result.bindTo("answer")
1615 * ) // => Result.succeed({ answer: 42 })
1616 * ```
1617 *
1618 * @see {@link Do} to start from an empty object
1619 * @see {@link bind} to add more fields
1620 *
1621 * @category mapping
1622 * @since 2.0.0
1623 */
1624export const bindTo: {
1625 <N extends string>(name: N): <R, L>(self: Result<R, L>) => Result<Record<N, R>, L>
1626 <R, L, N extends string>(self: Result<R, L>, name: N): Result<Record<N, R>, L>
1627} = doNotation.bindTo<ResultTypeLambda>(map)
1628
1629const let_: {
1630 <N extends string, R extends object, B>(
1631 name: Exclude<N, keyof R>,
1632 f: (r: NoInfer<R>) => B
1633 ): <L>(self: Result<R, L>) => Result<{ [K in N | keyof R]: K extends keyof R ? R[K] : B }, L>
1634 <R extends object, L, N extends string, B>(
1635 self: Result<R, L>,
1636 name: Exclude<N, keyof R>,
1637 f: (r: NoInfer<R>) => B
1638 ): Result<{ [K in N | keyof R]: K extends keyof R ? R[K] : B }, L>
1639} = doNotation.let_<ResultTypeLambda>(map)
1640
1641export {
1642 /**
1643 * Adds a named field to the do-notation accumulator by computing a pure
1644 * (non-Result) value from the current accumulated object.
1645 *
1646 * **When to use**
1647 *
1648 * Use when you need to add a derived field that cannot fail inside a
1649 * do-notation pipeline.
1650 *
1651 * **Details**
1652 *
1653 * - Use {@link bind} when the computation returns a `Result`
1654 * - The field name must not collide with existing keys
1655 *
1656 * **Example** (Adding a computed field)
1657 *
1658 * ```ts import.meta.vitest
1659 * import { pipe, Result } from "effect"
1660 *
1661 * pipe(
1662 * Result.Do,
1663 * Result.bind("x", () => Result.succeed(2)),
1664 * Result.bind("y", () => Result.succeed(3)),
1665 * Result.let("sum", ({ x, y }) => x + y)
1666 * ) // => Result.succeed({ x: 2, y: 3, sum: 5 })
1667 * ```
1668 *
1669 * @see {@link Do} to start the do-notation chain
1670 * @see {@link bind} for Result-producing fields
1671 *
1672 * @category mapping
1673 * @since 2.0.0
1674 */
1675 let_ as let
1676}
1677
1678/**
1679 * Transforms `Option<Result<A, E>>` into `Result<Option<A>, E>`.
1680 *
1681 * **When to use**
1682 *
1683 * Use when optional absence should be treated as a successful `None`, while an
1684 * inner `Result` failure should still fail the whole result.
1685 *
1686 * **Details**
1687 *
1688 * - `None` becomes `Success(None)`
1689 * - `Some(Success(a))` becomes `Success(Some(a))`
1690 * - `Some(Failure(e))` becomes `Failure(e)`
1691 *
1692 * **Example** (Transposing an Option of a Result)
1693 *
1694 * ```ts import.meta.vitest
1695 * import { Option, Result } from "effect"
1696 *
1697 * Result.transposeOption(Option.some(Result.succeed(42))) // => Result.succeed(Option.some(42))
1698 *
1699 * Result.transposeOption(Option.none<Result.Result<number, string>>()) // => Result.succeed(Option.none())
1700 * ```
1701 *
1702 * @see {@link transposeMapOption} to map and transpose in one step
1703 *
1704 * @category transposing
1705 * @since 3.14.0
1706 */
1707export const transposeOption = <A = never, E = never>(
1708 self: Option<Result<A, E>>
1709): Result<Option<A>, E> => {
1710 return option_.isNone(self) ? succeedNone : map(self.value, option_.some)
1711}
1712
1713/**
1714 * Maps an `Option` value with a `Result`-producing function, then transposes
1715 * the structure from `Option<Result<B, E>>` to `Result<Option<B>, E>`.
1716 *
1717 * **When to use**
1718 *
1719 * Use when an optional value should be validated only when present, preserving
1720 * absence as a successful `None`.
1721 *
1722 * **Details**
1723 *
1724 * - `None` becomes `Success(None)` (the function is never called)
1725 * - `Some(a)` where `f(a)` is `Success(b)` becomes `Success(Some(b))`
1726 * - `Some(a)` where `f(a)` is `Failure(e)` becomes `Failure(e)`
1727 *
1728 * **Example** (Mapping and transposing in one step)
1729 *
1730 * ```ts import.meta.vitest
1731 * import { Option, Result } from "effect"
1732 *
1733 * const parse = (s: string) =>
1734 * isNaN(Number(s))
1735 * ? Result.fail("not a number" as const)
1736 * : Result.succeed(Number(s))
1737 *
1738 * Result.transposeMapOption(Option.some("42"), parse) // => Result.succeed(Option.some(42))
1739 *
1740 * Result.transposeMapOption(Option.none(), parse) // => Result.succeed(Option.none())
1741 * ```
1742 *
1743 * @see {@link transposeOption} when the Option already contains a Result
1744 *
1745 * @category transposing
1746 * @since 3.15.0
1747 */
1748export const transposeMapOption = dual<
1749 <A, B, E = never>(
1750 f: (self: A) => Result<B, E>
1751 ) => (self: Option<A>) => Result<Option<B>, E>,
1752 <A, B, E = never>(
1753 self: Option<A>,
1754 f: (self: A) => Result<B, E>
1755 ) => Result<Option<B>, E>
1756>(2, (self, f) => option_.isNone(self) ? succeedNone : map(f(self.value), option_.some))
1757
1758/**
1759 * Provides a pre-built `Result<Option<never>>` that succeeds with `None`.
1760 *
1761 * **When to use**
1762 *
1763 * Use when an optional success should be absent, such as the `None` branch of
1764 * `transposeOption` or `transposeMapOption`.
1765 *
1766 * **Details**
1767 *
1768 * This is equivalent to `Result.succeed(Option.none())`, but reuses a shared
1769 * `Success` wrapper instead of allocating one each time.
1770 *
1771 * **Example** (Succeeding with None)
1772 *
1773 * ```ts import.meta.vitest
1774 * import { Option, Result } from "effect"
1775 *
1776 * Result.succeedNone // => Result.succeed(Option.none())
1777 * ```
1778 *
1779 * @see {@link succeedSome} for the `Some` counterpart
1780 * @see {@link transposeOption} to transpose an Option that already contains a Result
1781 * @see {@link transposeMapOption} to map and transpose an Option in one step
1782 *
1783 * @category constructors
1784 * @since 4.0.0
1785 */
1786export const succeedNone = succeed(option_.none)
1787
1788/**
1789 * Creates a `Result<Option<A>>` that succeeds with `Some(a)`.
1790 *
1791 * **Details**
1792 *
1793 * - Equivalent to `Result.succeed(Option.some(a))`
1794 * - Useful with {@link transposeOption} patterns
1795 *
1796 * **Example** (Wrapping a value in Some inside a Result)
1797 *
1798 * ```ts import.meta.vitest
1799 * import { Option, Result } from "effect"
1800 *
1801 * Result.succeedSome(42) // => Result.succeed(Option.some(42))
1802 * ```
1803 *
1804 * @see {@link succeedNone} for the `None` counterpart
1805 *
1806 * @category constructors
1807 * @since 4.0.0
1808 */
1809export const succeedSome = <A, E = never>(a: A): Result<Option<A>, E> => succeed(option_.some(a))
1810
1811/**
1812 * Runs a side-effect on the success value without altering the `Result`.
1813 *
1814 * **Details**
1815 *
1816 * - If the result is a `Success`, calls `f` with the value (return value is ignored)
1817 * - If the result is a `Failure`, `f` is not called
1818 * - Returns the original `Result` unchanged (same reference)
1819 * - Useful for logging, debugging, or performing mutations outside the Result chain
1820 *
1821 * **Example** (Logging a success value)
1822 *
1823 * ```ts import.meta.vitest
1824 * import { pipe, Result } from "effect"
1825 *
1826 * const values: Array<number> = []
1827 * const result = pipe(
1828 * Result.succeed(42),
1829 * Result.tap((n) => values.push(n))
1830 * )
1831 *
1832 * values // => [42]
1833 * result // => Result.succeed(42)
1834 * ```
1835 *
1836 * @see {@link map} to transform the success value
1837 *
1838 * @category mapping
1839 * @since 4.0.0
1840 */
1841export const tap: {
1842 <A>(f: (a: A) => void): <E>(self: Result<A, E>) => Result<A, E>
1843 <A, E>(self: Result<A, E>, f: (a: A) => void): Result<A, E>
1844} = dual(
1845 2,
1846 <A, E>(self: Result<A, E>, f: (a: A) => void): Result<A, E> => {
1847 if (isSuccess(self)) {
1848 f(self.success)
1849 }
1850 return self
1851 }
1852)