ts-data-forge 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/array/array-utils.d.mts +2617 -0
- package/dist/array/array-utils.d.mts.map +1 -0
- package/dist/array/array-utils.mjs +2915 -0
- package/dist/array/array-utils.mjs.map +1 -0
- package/dist/array/index.d.mts +3 -0
- package/dist/array/index.d.mts.map +1 -0
- package/dist/array/index.mjs +3 -0
- package/dist/array/index.mjs.map +1 -0
- package/dist/array/tuple-utils.d.mts +421 -0
- package/dist/array/tuple-utils.d.mts.map +1 -0
- package/dist/array/tuple-utils.mjs +391 -0
- package/dist/array/tuple-utils.mjs.map +1 -0
- package/dist/collections/imap-mapped.d.mts +445 -0
- package/dist/collections/imap-mapped.d.mts.map +1 -0
- package/dist/collections/imap-mapped.mjs +424 -0
- package/dist/collections/imap-mapped.mjs.map +1 -0
- package/dist/collections/imap.d.mts +359 -0
- package/dist/collections/imap.d.mts.map +1 -0
- package/dist/collections/imap.mjs +338 -0
- package/dist/collections/imap.mjs.map +1 -0
- package/dist/collections/index.d.mts +7 -0
- package/dist/collections/index.d.mts.map +1 -0
- package/dist/collections/index.mjs +7 -0
- package/dist/collections/index.mjs.map +1 -0
- package/dist/collections/iset-mapped.d.mts +576 -0
- package/dist/collections/iset-mapped.d.mts.map +1 -0
- package/dist/collections/iset-mapped.mjs +522 -0
- package/dist/collections/iset-mapped.mjs.map +1 -0
- package/dist/collections/iset.d.mts +426 -0
- package/dist/collections/iset.d.mts.map +1 -0
- package/dist/collections/iset.mjs +437 -0
- package/dist/collections/iset.mjs.map +1 -0
- package/dist/collections/queue.d.mts +190 -0
- package/dist/collections/queue.d.mts.map +1 -0
- package/dist/collections/queue.mjs +317 -0
- package/dist/collections/queue.mjs.map +1 -0
- package/dist/collections/stack.d.mts +210 -0
- package/dist/collections/stack.d.mts.map +1 -0
- package/dist/collections/stack.mjs +353 -0
- package/dist/collections/stack.mjs.map +1 -0
- package/dist/expect-type.d.mts +199 -0
- package/dist/expect-type.d.mts.map +1 -0
- package/dist/expect-type.mjs +201 -0
- package/dist/expect-type.mjs.map +1 -0
- package/dist/functional/index.d.mts +5 -0
- package/dist/functional/index.d.mts.map +1 -0
- package/dist/functional/index.mjs +5 -0
- package/dist/functional/index.mjs.map +1 -0
- package/dist/functional/match.d.mts +215 -0
- package/dist/functional/match.d.mts.map +1 -0
- package/dist/functional/match.mjs +139 -0
- package/dist/functional/match.mjs.map +1 -0
- package/dist/functional/optional.d.mts +517 -0
- package/dist/functional/optional.d.mts.map +1 -0
- package/dist/functional/optional.mjs +532 -0
- package/dist/functional/optional.mjs.map +1 -0
- package/dist/functional/pipe.d.mts +185 -0
- package/dist/functional/pipe.d.mts.map +1 -0
- package/dist/functional/pipe.mjs +129 -0
- package/dist/functional/pipe.mjs.map +1 -0
- package/dist/functional/result.d.mts +796 -0
- package/dist/functional/result.d.mts.map +1 -0
- package/dist/functional/result.mjs +844 -0
- package/dist/functional/result.mjs.map +1 -0
- package/dist/globals.d.mts +38 -0
- package/dist/guard/has-key.d.mts +100 -0
- package/dist/guard/has-key.d.mts.map +1 -0
- package/dist/guard/has-key.mjs +94 -0
- package/dist/guard/has-key.mjs.map +1 -0
- package/dist/guard/index.d.mts +8 -0
- package/dist/guard/index.d.mts.map +1 -0
- package/dist/guard/index.mjs +8 -0
- package/dist/guard/index.mjs.map +1 -0
- package/dist/guard/is-non-empty-string.d.mts +106 -0
- package/dist/guard/is-non-empty-string.d.mts.map +1 -0
- package/dist/guard/is-non-empty-string.mjs +108 -0
- package/dist/guard/is-non-empty-string.mjs.map +1 -0
- package/dist/guard/is-non-null-object.d.mts +105 -0
- package/dist/guard/is-non-null-object.d.mts.map +1 -0
- package/dist/guard/is-non-null-object.mjs +108 -0
- package/dist/guard/is-non-null-object.mjs.map +1 -0
- package/dist/guard/is-primitive.d.mts +146 -0
- package/dist/guard/is-primitive.d.mts.map +1 -0
- package/dist/guard/is-primitive.mjs +161 -0
- package/dist/guard/is-primitive.mjs.map +1 -0
- package/dist/guard/is-record.d.mts +151 -0
- package/dist/guard/is-record.d.mts.map +1 -0
- package/dist/guard/is-record.mjs +155 -0
- package/dist/guard/is-record.mjs.map +1 -0
- package/dist/guard/is-type.d.mts +430 -0
- package/dist/guard/is-type.d.mts.map +1 -0
- package/dist/guard/is-type.mjs +432 -0
- package/dist/guard/is-type.mjs.map +1 -0
- package/dist/guard/key-is-in.d.mts +158 -0
- package/dist/guard/key-is-in.d.mts.map +1 -0
- package/dist/guard/key-is-in.mjs +160 -0
- package/dist/guard/key-is-in.mjs.map +1 -0
- package/dist/index.d.mts +11 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +61 -0
- package/dist/index.mjs.map +1 -0
- package/dist/iterator/index.d.mts +2 -0
- package/dist/iterator/index.d.mts.map +1 -0
- package/dist/iterator/index.mjs +2 -0
- package/dist/iterator/index.mjs.map +1 -0
- package/dist/iterator/range.d.mts +97 -0
- package/dist/iterator/range.d.mts.map +1 -0
- package/dist/iterator/range.mjs +130 -0
- package/dist/iterator/range.mjs.map +1 -0
- package/dist/json/index.d.mts +2 -0
- package/dist/json/index.d.mts.map +1 -0
- package/dist/json/index.mjs +2 -0
- package/dist/json/index.mjs.map +1 -0
- package/dist/json/json.d.mts +597 -0
- package/dist/json/json.d.mts.map +1 -0
- package/dist/json/json.mjs +687 -0
- package/dist/json/json.mjs.map +1 -0
- package/dist/number/branded-types/finite-number.d.mts +291 -0
- package/dist/number/branded-types/finite-number.d.mts.map +1 -0
- package/dist/number/branded-types/finite-number.mjs +296 -0
- package/dist/number/branded-types/finite-number.mjs.map +1 -0
- package/dist/number/branded-types/index.d.mts +27 -0
- package/dist/number/branded-types/index.d.mts.map +1 -0
- package/dist/number/branded-types/index.mjs +27 -0
- package/dist/number/branded-types/index.mjs.map +1 -0
- package/dist/number/branded-types/int.d.mts +242 -0
- package/dist/number/branded-types/int.d.mts.map +1 -0
- package/dist/number/branded-types/int.mjs +239 -0
- package/dist/number/branded-types/int.mjs.map +1 -0
- package/dist/number/branded-types/int16.d.mts +162 -0
- package/dist/number/branded-types/int16.d.mts.map +1 -0
- package/dist/number/branded-types/int16.mjs +141 -0
- package/dist/number/branded-types/int16.mjs.map +1 -0
- package/dist/number/branded-types/int32.d.mts +155 -0
- package/dist/number/branded-types/int32.d.mts.map +1 -0
- package/dist/number/branded-types/int32.mjs +142 -0
- package/dist/number/branded-types/int32.mjs.map +1 -0
- package/dist/number/branded-types/non-negative-finite-number.d.mts +165 -0
- package/dist/number/branded-types/non-negative-finite-number.d.mts.map +1 -0
- package/dist/number/branded-types/non-negative-finite-number.mjs +160 -0
- package/dist/number/branded-types/non-negative-finite-number.mjs.map +1 -0
- package/dist/number/branded-types/non-negative-int16.d.mts +160 -0
- package/dist/number/branded-types/non-negative-int16.d.mts.map +1 -0
- package/dist/number/branded-types/non-negative-int16.mjs +138 -0
- package/dist/number/branded-types/non-negative-int16.mjs.map +1 -0
- package/dist/number/branded-types/non-negative-int32.d.mts +156 -0
- package/dist/number/branded-types/non-negative-int32.d.mts.map +1 -0
- package/dist/number/branded-types/non-negative-int32.mjs +138 -0
- package/dist/number/branded-types/non-negative-int32.mjs.map +1 -0
- package/dist/number/branded-types/non-zero-finite-number.d.mts +154 -0
- package/dist/number/branded-types/non-zero-finite-number.d.mts.map +1 -0
- package/dist/number/branded-types/non-zero-finite-number.mjs +160 -0
- package/dist/number/branded-types/non-zero-finite-number.mjs.map +1 -0
- package/dist/number/branded-types/non-zero-int.d.mts +131 -0
- package/dist/number/branded-types/non-zero-int.d.mts.map +1 -0
- package/dist/number/branded-types/non-zero-int.mjs +128 -0
- package/dist/number/branded-types/non-zero-int.mjs.map +1 -0
- package/dist/number/branded-types/non-zero-int16.d.mts +166 -0
- package/dist/number/branded-types/non-zero-int16.d.mts.map +1 -0
- package/dist/number/branded-types/non-zero-int16.mjs +145 -0
- package/dist/number/branded-types/non-zero-int16.mjs.map +1 -0
- package/dist/number/branded-types/non-zero-int32.d.mts +158 -0
- package/dist/number/branded-types/non-zero-int32.d.mts.map +1 -0
- package/dist/number/branded-types/non-zero-int32.mjs +145 -0
- package/dist/number/branded-types/non-zero-int32.mjs.map +1 -0
- package/dist/number/branded-types/non-zero-safe-int.d.mts +148 -0
- package/dist/number/branded-types/non-zero-safe-int.d.mts.map +1 -0
- package/dist/number/branded-types/non-zero-safe-int.mjs +145 -0
- package/dist/number/branded-types/non-zero-safe-int.mjs.map +1 -0
- package/dist/number/branded-types/non-zero-uint16.d.mts +160 -0
- package/dist/number/branded-types/non-zero-uint16.d.mts.map +1 -0
- package/dist/number/branded-types/non-zero-uint16.mjs +140 -0
- package/dist/number/branded-types/non-zero-uint16.mjs.map +1 -0
- package/dist/number/branded-types/non-zero-uint32.d.mts +156 -0
- package/dist/number/branded-types/non-zero-uint32.d.mts.map +1 -0
- package/dist/number/branded-types/non-zero-uint32.mjs +140 -0
- package/dist/number/branded-types/non-zero-uint32.mjs.map +1 -0
- package/dist/number/branded-types/positive-finite-number.d.mts +171 -0
- package/dist/number/branded-types/positive-finite-number.d.mts.map +1 -0
- package/dist/number/branded-types/positive-finite-number.mjs +165 -0
- package/dist/number/branded-types/positive-finite-number.mjs.map +1 -0
- package/dist/number/branded-types/positive-int.d.mts +270 -0
- package/dist/number/branded-types/positive-int.d.mts.map +1 -0
- package/dist/number/branded-types/positive-int.mjs +257 -0
- package/dist/number/branded-types/positive-int.mjs.map +1 -0
- package/dist/number/branded-types/positive-int16.d.mts +162 -0
- package/dist/number/branded-types/positive-int16.d.mts.map +1 -0
- package/dist/number/branded-types/positive-int16.mjs +139 -0
- package/dist/number/branded-types/positive-int16.mjs.map +1 -0
- package/dist/number/branded-types/positive-int32.d.mts +158 -0
- package/dist/number/branded-types/positive-int32.d.mts.map +1 -0
- package/dist/number/branded-types/positive-int32.mjs +139 -0
- package/dist/number/branded-types/positive-int32.mjs.map +1 -0
- package/dist/number/branded-types/positive-safe-int.d.mts +152 -0
- package/dist/number/branded-types/positive-safe-int.d.mts.map +1 -0
- package/dist/number/branded-types/positive-safe-int.mjs +138 -0
- package/dist/number/branded-types/positive-safe-int.mjs.map +1 -0
- package/dist/number/branded-types/positive-uint16.d.mts +160 -0
- package/dist/number/branded-types/positive-uint16.d.mts.map +1 -0
- package/dist/number/branded-types/positive-uint16.mjs +139 -0
- package/dist/number/branded-types/positive-uint16.mjs.map +1 -0
- package/dist/number/branded-types/positive-uint32.d.mts +156 -0
- package/dist/number/branded-types/positive-uint32.d.mts.map +1 -0
- package/dist/number/branded-types/positive-uint32.mjs +139 -0
- package/dist/number/branded-types/positive-uint32.mjs.map +1 -0
- package/dist/number/branded-types/safe-int.d.mts +243 -0
- package/dist/number/branded-types/safe-int.d.mts.map +1 -0
- package/dist/number/branded-types/safe-int.mjs +240 -0
- package/dist/number/branded-types/safe-int.mjs.map +1 -0
- package/dist/number/branded-types/safe-uint.d.mts +151 -0
- package/dist/number/branded-types/safe-uint.d.mts.map +1 -0
- package/dist/number/branded-types/safe-uint.mjs +138 -0
- package/dist/number/branded-types/safe-uint.mjs.map +1 -0
- package/dist/number/branded-types/uint.d.mts +144 -0
- package/dist/number/branded-types/uint.d.mts.map +1 -0
- package/dist/number/branded-types/uint.mjs +132 -0
- package/dist/number/branded-types/uint.mjs.map +1 -0
- package/dist/number/branded-types/uint16.d.mts +157 -0
- package/dist/number/branded-types/uint16.d.mts.map +1 -0
- package/dist/number/branded-types/uint16.mjs +137 -0
- package/dist/number/branded-types/uint16.mjs.map +1 -0
- package/dist/number/branded-types/uint32.d.mts +185 -0
- package/dist/number/branded-types/uint32.d.mts.map +1 -0
- package/dist/number/branded-types/uint32.mjs +169 -0
- package/dist/number/branded-types/uint32.mjs.map +1 -0
- package/dist/number/enum/index.d.mts +3 -0
- package/dist/number/enum/index.d.mts.map +1 -0
- package/dist/number/enum/index.mjs +3 -0
- package/dist/number/enum/index.mjs.map +1 -0
- package/dist/number/enum/int8.d.mts +202 -0
- package/dist/number/enum/int8.d.mts.map +1 -0
- package/dist/number/enum/int8.mjs +296 -0
- package/dist/number/enum/int8.mjs.map +1 -0
- package/dist/number/enum/uint8.d.mts +128 -0
- package/dist/number/enum/uint8.d.mts.map +1 -0
- package/dist/number/enum/uint8.mjs +251 -0
- package/dist/number/enum/uint8.mjs.map +1 -0
- package/dist/number/index.d.mts +5 -0
- package/dist/number/index.d.mts.map +1 -0
- package/dist/number/index.mjs +31 -0
- package/dist/number/index.mjs.map +1 -0
- package/dist/number/num.d.mts +515 -0
- package/dist/number/num.d.mts.map +1 -0
- package/dist/number/num.mjs +513 -0
- package/dist/number/num.mjs.map +1 -0
- package/dist/number/refined-number-utils.d.mts +191 -0
- package/dist/number/refined-number-utils.d.mts.map +1 -0
- package/dist/number/refined-number-utils.mjs +179 -0
- package/dist/number/refined-number-utils.mjs.map +1 -0
- package/dist/object/index.d.mts +2 -0
- package/dist/object/index.d.mts.map +1 -0
- package/dist/object/index.mjs +2 -0
- package/dist/object/index.mjs.map +1 -0
- package/dist/object/object.d.mts +296 -0
- package/dist/object/object.d.mts.map +1 -0
- package/dist/object/object.mjs +295 -0
- package/dist/object/object.mjs.map +1 -0
- package/dist/others/cast-mutable.d.mts +110 -0
- package/dist/others/cast-mutable.d.mts.map +1 -0
- package/dist/others/cast-mutable.mjs +114 -0
- package/dist/others/cast-mutable.mjs.map +1 -0
- package/dist/others/cast-readonly.d.mts +189 -0
- package/dist/others/cast-readonly.d.mts.map +1 -0
- package/dist/others/cast-readonly.mjs +193 -0
- package/dist/others/cast-readonly.mjs.map +1 -0
- package/dist/others/if-then.d.mts +98 -0
- package/dist/others/if-then.d.mts.map +1 -0
- package/dist/others/if-then.mjs +100 -0
- package/dist/others/if-then.mjs.map +1 -0
- package/dist/others/index.d.mts +8 -0
- package/dist/others/index.d.mts.map +1 -0
- package/dist/others/index.mjs +8 -0
- package/dist/others/index.mjs.map +1 -0
- package/dist/others/map-nullable.d.mts +151 -0
- package/dist/others/map-nullable.d.mts.map +1 -0
- package/dist/others/map-nullable.mjs +159 -0
- package/dist/others/map-nullable.mjs.map +1 -0
- package/dist/others/memoize-function.d.mts +173 -0
- package/dist/others/memoize-function.d.mts.map +1 -0
- package/dist/others/memoize-function.mjs +189 -0
- package/dist/others/memoize-function.mjs.map +1 -0
- package/dist/others/tuple.d.mts +159 -0
- package/dist/others/tuple.d.mts.map +1 -0
- package/dist/others/tuple.mjs +161 -0
- package/dist/others/tuple.mjs.map +1 -0
- package/dist/others/unknown-to-string.d.mts +180 -0
- package/dist/others/unknown-to-string.d.mts.map +1 -0
- package/dist/others/unknown-to-string.mjs +211 -0
- package/dist/others/unknown-to-string.mjs.map +1 -0
- package/dist/tsconfig.json +1 -0
- package/package.json +16 -14
|
@@ -0,0 +1,844 @@
|
|
|
1
|
+
import { isRecord } from '../guard/is-record.mjs';
|
|
2
|
+
import { unknownToString } from '../others/unknown-to-string.mjs';
|
|
3
|
+
import { Optional } from './optional.mjs';
|
|
4
|
+
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-unsafe-type-assertion */
|
|
6
|
+
/** @internal Symbol to identify the 'Ok' variant of Result. */
|
|
7
|
+
const OkTypeSymbol = Symbol('Result.ok');
|
|
8
|
+
/** @internal Symbol to identify the 'Err' variant of Result. */
|
|
9
|
+
const ErrTypeSymbol = Symbol('Result.err');
|
|
10
|
+
/**
|
|
11
|
+
* Namespace for the `Result` type and related functions.
|
|
12
|
+
* Provides utilities to handle operations that can succeed or fail.
|
|
13
|
+
*/
|
|
14
|
+
var Result;
|
|
15
|
+
(function (Result) {
|
|
16
|
+
/**
|
|
17
|
+
* Checks if the given value is a `Result`.
|
|
18
|
+
* @param maybeOptional The value to check.
|
|
19
|
+
* @returns `true` if the value is a `Result`, otherwise `false`.
|
|
20
|
+
*/
|
|
21
|
+
Result.isResult = (maybeOptional) => isRecord(maybeOptional) &&
|
|
22
|
+
Object.hasOwn(maybeOptional, 'type') &&
|
|
23
|
+
Object.hasOwn(maybeOptional, 'value') &&
|
|
24
|
+
(maybeOptional['type'] === ErrTypeSymbol ||
|
|
25
|
+
maybeOptional['type'] === OkTypeSymbol);
|
|
26
|
+
/**
|
|
27
|
+
* Creates a `Result.Ok` containing the given success value.
|
|
28
|
+
*
|
|
29
|
+
* Use this constructor when an operation succeeds and you want to wrap
|
|
30
|
+
* the successful result in a Result type for consistent error handling.
|
|
31
|
+
*
|
|
32
|
+
* @template S The type of the success value.
|
|
33
|
+
* @param value The success value.
|
|
34
|
+
* @returns A `Result.Ok<S>` containing the value.
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* // Basic success case
|
|
38
|
+
* const success = Result.ok(42);
|
|
39
|
+
* console.log(Result.isOk(success)); // true
|
|
40
|
+
* console.log(Result.unwrapOk(success)); // 42
|
|
41
|
+
*
|
|
42
|
+
* // Function that returns a Result
|
|
43
|
+
* function divide(a: number, b: number): Result<number, string> {
|
|
44
|
+
* if (b === 0) {
|
|
45
|
+
* return Result.err("Division by zero");
|
|
46
|
+
* }
|
|
47
|
+
* return Result.ok(a / b);
|
|
48
|
+
* }
|
|
49
|
+
*
|
|
50
|
+
* const result = divide(10, 2);
|
|
51
|
+
* console.log(Result.unwrapOk(result)); // 5
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
Result.ok = (value) => ({
|
|
55
|
+
type: OkTypeSymbol,
|
|
56
|
+
value,
|
|
57
|
+
});
|
|
58
|
+
/**
|
|
59
|
+
* Creates a `Result.Err` containing the given error value.
|
|
60
|
+
*
|
|
61
|
+
* Use this constructor when an operation fails and you want to wrap
|
|
62
|
+
* the error information in a Result type for consistent error handling.
|
|
63
|
+
*
|
|
64
|
+
* @template E The type of the error value.
|
|
65
|
+
* @param value The error value.
|
|
66
|
+
* @returns A `Result.Err<E>` containing the value.
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* // Basic error case
|
|
70
|
+
* const failure = Result.err("Something went wrong");
|
|
71
|
+
* console.log(Result.isErr(failure)); // true
|
|
72
|
+
* console.log(Result.unwrapErr(failure)); // "Something went wrong"
|
|
73
|
+
*
|
|
74
|
+
* // Function that can fail
|
|
75
|
+
* function parseInteger(input: string): Result<number, string> {
|
|
76
|
+
* const num = parseInt(input, 10);
|
|
77
|
+
* if (isNaN(num)) {
|
|
78
|
+
* return Result.err(`Invalid number format: ${input}`);
|
|
79
|
+
* }
|
|
80
|
+
* return Result.ok(num);
|
|
81
|
+
* }
|
|
82
|
+
*
|
|
83
|
+
* const result = parseInteger("abc");
|
|
84
|
+
* console.log(Result.unwrapErr(result)); // "Invalid number format: abc"
|
|
85
|
+
*
|
|
86
|
+
* // Using custom error types
|
|
87
|
+
* interface ValidationError {
|
|
88
|
+
* field: string;
|
|
89
|
+
* message: string;
|
|
90
|
+
* }
|
|
91
|
+
*
|
|
92
|
+
* const validationError = Result.err<ValidationError>({
|
|
93
|
+
* field: "email",
|
|
94
|
+
* message: "Invalid email format"
|
|
95
|
+
* });
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
Result.err = (value) => ({
|
|
99
|
+
type: ErrTypeSymbol,
|
|
100
|
+
value,
|
|
101
|
+
});
|
|
102
|
+
/**
|
|
103
|
+
* @internal
|
|
104
|
+
* Default string conversion function using native String constructor.
|
|
105
|
+
*/
|
|
106
|
+
const toStr_ = String;
|
|
107
|
+
/**
|
|
108
|
+
* Checks if a `Result` is `Result.Ok`.
|
|
109
|
+
* Acts as a type guard, narrowing the type to the success variant.
|
|
110
|
+
*
|
|
111
|
+
* This function is essential for type-safe Result handling, allowing
|
|
112
|
+
* TypeScript to understand that subsequent operations will work with
|
|
113
|
+
* the success value rather than the error value.
|
|
114
|
+
*
|
|
115
|
+
* @template R The `Result.Base` type to check.
|
|
116
|
+
* @param result The `Result` to check.
|
|
117
|
+
* @returns `true` if the `Result` is `Result.Ok`, otherwise `false`.
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* // Basic type guard usage
|
|
121
|
+
* const result: Result<number, string> = divide(10, 2);
|
|
122
|
+
*
|
|
123
|
+
* if (Result.isOk(result)) {
|
|
124
|
+
* // TypeScript knows result is Result.Ok<number>
|
|
125
|
+
* console.log(result.value); // Safe to access .value
|
|
126
|
+
* console.log(Result.unwrapOk(result)); // 5
|
|
127
|
+
* } else {
|
|
128
|
+
* // TypeScript knows result is Result.Err<string>
|
|
129
|
+
* console.log(result.value); // Error message
|
|
130
|
+
* }
|
|
131
|
+
*
|
|
132
|
+
* // Using in conditional logic
|
|
133
|
+
* const processResult = (r: Result<string, Error>) => {
|
|
134
|
+
* return Result.isOk(r)
|
|
135
|
+
* ? r.value.toUpperCase() // Safe string operations
|
|
136
|
+
* : "Error occurred";
|
|
137
|
+
* };
|
|
138
|
+
*
|
|
139
|
+
* // Filtering arrays of Results
|
|
140
|
+
* const results: Result<number, string>[] = [
|
|
141
|
+
* Result.ok(1),
|
|
142
|
+
* Result.err("error"),
|
|
143
|
+
* Result.ok(2)
|
|
144
|
+
* ];
|
|
145
|
+
* const successes = results.filter(Result.isOk);
|
|
146
|
+
* // successes is Result.Ok<number>[]
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
Result.isOk = (result) => result.type === OkTypeSymbol;
|
|
150
|
+
/**
|
|
151
|
+
* Checks if a `Result` is `Result.Err`.
|
|
152
|
+
* Acts as a type guard, narrowing the type to the error variant.
|
|
153
|
+
*
|
|
154
|
+
* This function is essential for type-safe Result handling, allowing
|
|
155
|
+
* TypeScript to understand that subsequent operations will work with
|
|
156
|
+
* the error value rather than the success value.
|
|
157
|
+
*
|
|
158
|
+
* @template R The `Result.Base` type to check.
|
|
159
|
+
* @param result The `Result` to check.
|
|
160
|
+
* @returns `true` if the `Result` is `Result.Err`, otherwise `false`.
|
|
161
|
+
* @example
|
|
162
|
+
* ```typescript
|
|
163
|
+
* // Basic type guard usage
|
|
164
|
+
* const result: Result<number, string> = divide(10, 0);
|
|
165
|
+
*
|
|
166
|
+
* if (Result.isErr(result)) {
|
|
167
|
+
* // TypeScript knows result is Result.Err<string>
|
|
168
|
+
* console.log(result.value); // Safe to access error .value
|
|
169
|
+
* console.log(Result.unwrapErr(result)); // "Division by zero"
|
|
170
|
+
* } else {
|
|
171
|
+
* // TypeScript knows result is Result.Ok<number>
|
|
172
|
+
* console.log(result.value); // Success value
|
|
173
|
+
* }
|
|
174
|
+
*
|
|
175
|
+
* // Error handling patterns
|
|
176
|
+
* const handleResult = (r: Result<Data, ApiError>) => {
|
|
177
|
+
* if (Result.isErr(r)) {
|
|
178
|
+
* logError(r.value); // Safe error operations
|
|
179
|
+
* return null;
|
|
180
|
+
* }
|
|
181
|
+
* return processData(r.value);
|
|
182
|
+
* };
|
|
183
|
+
*
|
|
184
|
+
* // Collecting errors from multiple Results
|
|
185
|
+
* const results: Result<string, ValidationError>[] = validateForm();
|
|
186
|
+
* const errors = results
|
|
187
|
+
* .filter(Result.isErr)
|
|
188
|
+
* .map(err => err.value); // ValidationError[]
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
Result.isErr = (result) => result.type === ErrTypeSymbol;
|
|
192
|
+
/**
|
|
193
|
+
* Unwraps a `Result`, returning the success value.
|
|
194
|
+
* Throws an error if the `Result` is `Result.Err`.
|
|
195
|
+
*
|
|
196
|
+
* This is useful when you're confident that a Result should contain a success value
|
|
197
|
+
* and want to treat errors as exceptional conditions. The error message will be
|
|
198
|
+
* constructed from the error value using the provided string conversion function.
|
|
199
|
+
*
|
|
200
|
+
* @template R The `Result.Base` type to unwrap.
|
|
201
|
+
* @param result The `Result` to unwrap.
|
|
202
|
+
* @param toStr An optional function to convert the error value to a string for the error message. Defaults to `String`.
|
|
203
|
+
* @returns The success value if `Result.Ok`.
|
|
204
|
+
* @throws {Error} Error with the stringified error value if the `Result` is `Result.Err`.
|
|
205
|
+
* @example
|
|
206
|
+
* ```typescript
|
|
207
|
+
* // Basic usage with default string conversion
|
|
208
|
+
* const success = Result.ok(42);
|
|
209
|
+
* console.log(Result.unwrapThrow(success)); // 42
|
|
210
|
+
*
|
|
211
|
+
* const failure = Result.err("Network error");
|
|
212
|
+
* try {
|
|
213
|
+
* Result.unwrapThrow(failure); // throws Error: "Network error"
|
|
214
|
+
* } catch (error) {
|
|
215
|
+
* console.log(error.message); // "Network error"
|
|
216
|
+
* }
|
|
217
|
+
*
|
|
218
|
+
* // Custom error string conversion
|
|
219
|
+
* interface ApiError {
|
|
220
|
+
* code: number;
|
|
221
|
+
* message: string;
|
|
222
|
+
* }
|
|
223
|
+
*
|
|
224
|
+
* const apiResult = Result.err<ApiError>({ code: 404, message: "Not found" });
|
|
225
|
+
* try {
|
|
226
|
+
* Result.unwrapThrow(apiResult, err => `API Error ${err.code}: ${err.message}`);
|
|
227
|
+
* } catch (error) {
|
|
228
|
+
* console.log(error.message); // "API Error 404: Not found"
|
|
229
|
+
* }
|
|
230
|
+
*
|
|
231
|
+
* // In contexts where failure is unexpected
|
|
232
|
+
* const configResult = loadConfiguration();
|
|
233
|
+
* const config = Result.unwrapThrow(configResult, err =>
|
|
234
|
+
* `Failed to load configuration: ${err}`
|
|
235
|
+
* ); // Will throw if config loading fails
|
|
236
|
+
* ```
|
|
237
|
+
*/
|
|
238
|
+
Result.unwrapThrow = (result, toStr = toStr_) => {
|
|
239
|
+
if (Result.isErr(result)) {
|
|
240
|
+
throw new Error(toStr(result.value));
|
|
241
|
+
}
|
|
242
|
+
return result.value;
|
|
243
|
+
};
|
|
244
|
+
/**
|
|
245
|
+
* Unwraps a `Result`, returning the success value or `undefined` if it's an error.
|
|
246
|
+
*
|
|
247
|
+
* This function provides a safe way to extract success values from Results without
|
|
248
|
+
* throwing exceptions. It has overloaded behavior based on the type:
|
|
249
|
+
* - For `Result.Ok<T>`: Always returns `T` (guaranteed by type system)
|
|
250
|
+
* - For general `Result<T, E>`: Returns `T | undefined`
|
|
251
|
+
*
|
|
252
|
+
* @template R The `Result.Base` type to unwrap.
|
|
253
|
+
* @param result The `Result` to unwrap.
|
|
254
|
+
* @returns The success value if `Result.Ok`, otherwise `undefined`.
|
|
255
|
+
* @example
|
|
256
|
+
* ```typescript
|
|
257
|
+
* // With guaranteed Ok - returns the value
|
|
258
|
+
* const success = Result.ok(42);
|
|
259
|
+
* const value = Result.unwrapOk(success); // Type: number, Value: 42
|
|
260
|
+
*
|
|
261
|
+
* // With general Result - may return undefined
|
|
262
|
+
* const maybeResult: Result<string, Error> = fetchData();
|
|
263
|
+
* const data = Result.unwrapOk(maybeResult); // Type: string | undefined
|
|
264
|
+
*
|
|
265
|
+
* // Safe pattern for handling both cases
|
|
266
|
+
* const result = Result.ok("hello");
|
|
267
|
+
* const unwrapped = Result.unwrapOk(result);
|
|
268
|
+
* if (unwrapped !== undefined) {
|
|
269
|
+
* console.log(unwrapped.toUpperCase()); // "HELLO"
|
|
270
|
+
* }
|
|
271
|
+
*
|
|
272
|
+
* // Useful in conditional chains
|
|
273
|
+
* const processResult = (r: Result<number, string>) => {
|
|
274
|
+
* const value = Result.unwrapOk(r);
|
|
275
|
+
* return value !== undefined ? value * 2 : 0;
|
|
276
|
+
* };
|
|
277
|
+
* ```
|
|
278
|
+
*/
|
|
279
|
+
Result.unwrapOk = ((result) => Result.isErr(result)
|
|
280
|
+
? undefined
|
|
281
|
+
: result.value);
|
|
282
|
+
/**
|
|
283
|
+
* Unwraps a `Result`, returning the success value or a default value if it is `Result.Err`.
|
|
284
|
+
* @template R The `Result.Base` type to unwrap.
|
|
285
|
+
* @template D The type of the default value.
|
|
286
|
+
* @param result The `Result` to unwrap.
|
|
287
|
+
* @param defaultValue The value to return if `result` is `Result.Err`.
|
|
288
|
+
* @returns The success value if `Result.Ok`, otherwise `defaultValue`.
|
|
289
|
+
* @example
|
|
290
|
+
* ```typescript
|
|
291
|
+
* // Regular usage
|
|
292
|
+
* const result = Result.ok(42);
|
|
293
|
+
* const value = Result.unwrapOkOr(result, 0);
|
|
294
|
+
* console.log(value); // 42
|
|
295
|
+
*
|
|
296
|
+
* // Curried usage for pipe composition
|
|
297
|
+
* const unwrapWithDefault = Result.unwrapOkOr(0);
|
|
298
|
+
* const value2 = pipe(Result.err("error")).map(unwrapWithDefault).value;
|
|
299
|
+
* console.log(value2); // 0
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
Result.unwrapOkOr = ((...args) => {
|
|
303
|
+
switch (args.length) {
|
|
304
|
+
case 2: {
|
|
305
|
+
// Direct version: first argument is result
|
|
306
|
+
const [result, defaultValue] = args;
|
|
307
|
+
return Result.isErr(result) ? defaultValue : result.value;
|
|
308
|
+
}
|
|
309
|
+
case 1: {
|
|
310
|
+
// Curried version: first argument is default value
|
|
311
|
+
const [defaultValue] = args;
|
|
312
|
+
return (result) => Result.unwrapOkOr(result, defaultValue);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
/**
|
|
317
|
+
* Unwraps a `Result`, returning the error value.
|
|
318
|
+
* Throws an error if the `Result` is `Result.Ok`.
|
|
319
|
+
*
|
|
320
|
+
* This function is used when you expect a Result to be an error and want to
|
|
321
|
+
* extract the error value. If the Result is unexpectedly Ok, it will throw
|
|
322
|
+
* an error with information about the unexpected success value.
|
|
323
|
+
*
|
|
324
|
+
* @template R The `Result.Base` type to unwrap.
|
|
325
|
+
* @param result The `Result` to unwrap.
|
|
326
|
+
* @param toStr An optional function to convert the success value to a string for the error message when the Result is unexpectedly Ok. Defaults to `String`.
|
|
327
|
+
* @returns The error value if `Result.Err`.
|
|
328
|
+
* @throws {Error} Error with message "Expected Err but got Ok: {value}" if the `Result` is `Result.Ok`.
|
|
329
|
+
* @example
|
|
330
|
+
* ```typescript
|
|
331
|
+
* // Basic usage - extracting error from known failure
|
|
332
|
+
* const failure = Result.err("Network timeout");
|
|
333
|
+
* console.log(Result.unwrapErrThrow(failure)); // "Network timeout"
|
|
334
|
+
*
|
|
335
|
+
* // Throws when Result is unexpectedly Ok
|
|
336
|
+
* const success = Result.ok(42);
|
|
337
|
+
* try {
|
|
338
|
+
* Result.unwrapErrThrow(success); // throws Error: "Expected Err but got Ok: 42"
|
|
339
|
+
* } catch (error) {
|
|
340
|
+
* console.log(error.message); // "Expected Err but got Ok: 42"
|
|
341
|
+
* }
|
|
342
|
+
*
|
|
343
|
+
* // Custom success value string conversion
|
|
344
|
+
* interface User { name: string; id: number; }
|
|
345
|
+
* const userResult = Result.ok<User>({ name: "John", id: 123 });
|
|
346
|
+
* try {
|
|
347
|
+
* Result.unwrapErrThrow(userResult, user => `User(${user.name}:${user.id})`);
|
|
348
|
+
* } catch (error) {
|
|
349
|
+
* console.log(error.message); // "Expected Err but got Ok: User(John:123)"
|
|
350
|
+
* }
|
|
351
|
+
*
|
|
352
|
+
* // In error handling contexts
|
|
353
|
+
* const validateAndGetError = (result: Result<any, ValidationError>) => {
|
|
354
|
+
* if (Result.isErr(result)) {
|
|
355
|
+
* return Result.unwrapErrThrow(result); // Safe to unwrap error
|
|
356
|
+
* }
|
|
357
|
+
* throw new Error("Validation unexpectedly succeeded");
|
|
358
|
+
* };
|
|
359
|
+
* ```
|
|
360
|
+
*/
|
|
361
|
+
Result.unwrapErrThrow = (result, toStr = toStr_) => {
|
|
362
|
+
if (Result.isOk(result)) {
|
|
363
|
+
throw new Error(`Expected Err but got Ok: ${toStr(result.value)}`);
|
|
364
|
+
}
|
|
365
|
+
return result.value;
|
|
366
|
+
};
|
|
367
|
+
/**
|
|
368
|
+
* Unwraps a `Result`, returning the error value or `undefined` if it is `Result.Ok`.
|
|
369
|
+
*
|
|
370
|
+
* This provides a safe way to extract error values from Results without throwing
|
|
371
|
+
* exceptions. Useful for error handling patterns where you want to check for
|
|
372
|
+
* specific error conditions.
|
|
373
|
+
*
|
|
374
|
+
* @template R The `Result.Base` type to unwrap.
|
|
375
|
+
* @param result The `Result` to unwrap.
|
|
376
|
+
* @returns The error value if `Result.Err`, otherwise `undefined`.
|
|
377
|
+
* @example
|
|
378
|
+
* ```typescript
|
|
379
|
+
* // Basic error extraction
|
|
380
|
+
* const failure = Result.err("Connection failed");
|
|
381
|
+
* console.log(Result.unwrapErr(failure)); // "Connection failed"
|
|
382
|
+
*
|
|
383
|
+
* const success = Result.ok(42);
|
|
384
|
+
* console.log(Result.unwrapErr(success)); // undefined
|
|
385
|
+
*
|
|
386
|
+
* // Error handling patterns
|
|
387
|
+
* const handleApiCall = (result: Result<Data, ApiError>) => {
|
|
388
|
+
* const error = Result.unwrapErr(result);
|
|
389
|
+
* if (error !== undefined) {
|
|
390
|
+
* switch (error.type) {
|
|
391
|
+
* case "NETWORK_ERROR":
|
|
392
|
+
* return retry(result);
|
|
393
|
+
* case "AUTH_ERROR":
|
|
394
|
+
* return redirectToLogin();
|
|
395
|
+
* default:
|
|
396
|
+
* return showGenericError(error);
|
|
397
|
+
* }
|
|
398
|
+
* }
|
|
399
|
+
* // Handle success case...
|
|
400
|
+
* };
|
|
401
|
+
*
|
|
402
|
+
* // Collecting errors from multiple operations
|
|
403
|
+
* const results = await Promise.all([
|
|
404
|
+
* operation1(),
|
|
405
|
+
* operation2(),
|
|
406
|
+
* operation3()
|
|
407
|
+
* ]);
|
|
408
|
+
*
|
|
409
|
+
* const errors = results
|
|
410
|
+
* .map(Result.unwrapErr)
|
|
411
|
+
* .filter(err => err !== undefined); // Only actual errors
|
|
412
|
+
* ```
|
|
413
|
+
*/
|
|
414
|
+
Result.unwrapErr = (result) => Result.isErr(result) ? result.value : undefined;
|
|
415
|
+
/**
|
|
416
|
+
* Unwraps a `Result`, returning the error value or a default value if it is `Result.Ok`.
|
|
417
|
+
* @template R The `Result.Base` type to unwrap.
|
|
418
|
+
* @template D The type of the default value.
|
|
419
|
+
* @param result The `Result` to unwrap.
|
|
420
|
+
* @param defaultValue The value to return if `result` is `Result.Ok`.
|
|
421
|
+
* @returns The error value if `Result.Err`, otherwise `defaultValue`.
|
|
422
|
+
* @example
|
|
423
|
+
* ```typescript
|
|
424
|
+
* // Regular usage
|
|
425
|
+
* const result = Result.err("failed");
|
|
426
|
+
* const error = Result.unwrapErrOr(result, "default");
|
|
427
|
+
* console.log(error); // "failed"
|
|
428
|
+
*
|
|
429
|
+
* // Curried usage for pipe composition
|
|
430
|
+
* const unwrapErrorWithDefault = Result.unwrapErrOr("unknown error");
|
|
431
|
+
* const error2 = pipe(Result.ok(42)).map(unwrapErrorWithDefault).value;
|
|
432
|
+
* console.log(error2); // "unknown error"
|
|
433
|
+
* ```
|
|
434
|
+
*/
|
|
435
|
+
Result.unwrapErrOr = ((...args) => {
|
|
436
|
+
switch (args.length) {
|
|
437
|
+
case 2: {
|
|
438
|
+
// Direct version: first argument is result
|
|
439
|
+
const [result, defaultValue] = args;
|
|
440
|
+
return Result.isErr(result) ? result.value : defaultValue;
|
|
441
|
+
}
|
|
442
|
+
case 1: {
|
|
443
|
+
// Curried version: first argument is default value
|
|
444
|
+
const [defaultValue] = args;
|
|
445
|
+
return (result) => Result.unwrapErrOr(result, defaultValue);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
/**
|
|
450
|
+
* Maps a `Result<S, E>` to `Result<S2, E>` by applying a function to the success value.
|
|
451
|
+
* If the `Result` is `Result.Err`, returns the original `Err`.
|
|
452
|
+
* @template R The input `Result.Base` type.
|
|
453
|
+
* @template S2 The type of the success value returned by the mapping function.
|
|
454
|
+
* @param result The `Result` to map.
|
|
455
|
+
* @param mapFn The function to apply to the success value if present.
|
|
456
|
+
* @returns A new `Result<S2, UnwrapErr<R>>`.
|
|
457
|
+
* @example
|
|
458
|
+
* ```typescript
|
|
459
|
+
* // Regular usage
|
|
460
|
+
* const result = Result.ok(5);
|
|
461
|
+
* const mapped = Result.map(result, x => x * 2);
|
|
462
|
+
* console.log(Result.unwrap(mapped)); // 10
|
|
463
|
+
*
|
|
464
|
+
* // Curried version for use with pipe
|
|
465
|
+
* const doubler = Result.map((x: number) => x * 2);
|
|
466
|
+
* const result2 = pipe(Result.ok(5)).map(doubler).value;
|
|
467
|
+
* console.log(Result.unwrap(result2)); // 10
|
|
468
|
+
* ```
|
|
469
|
+
*/
|
|
470
|
+
Result.map = ((...args) => {
|
|
471
|
+
switch (args.length) {
|
|
472
|
+
case 2: {
|
|
473
|
+
const [result, mapFn] = args;
|
|
474
|
+
return Result.isErr(result)
|
|
475
|
+
? result
|
|
476
|
+
: Result.ok(mapFn(result.value));
|
|
477
|
+
}
|
|
478
|
+
case 1: {
|
|
479
|
+
// Curried version: first argument is mapping function
|
|
480
|
+
const [mapFn] = args;
|
|
481
|
+
return (result) => Result.map(result, mapFn);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
/**
|
|
486
|
+
* Maps a `Result<S, E>` to `Result<S, E2>` by applying a function to the error value.
|
|
487
|
+
* If the `Result` is `Result.Ok`, returns the original `Ok`.
|
|
488
|
+
* @template R The input `Result.Base` type.
|
|
489
|
+
* @template E2 The type of the error value returned by the mapping function.
|
|
490
|
+
* @param result The `Result` to map.
|
|
491
|
+
* @param mapFn The function to apply to the error value if present.
|
|
492
|
+
* @returns A new `Result<UnwrapOk<R>, E2>`.
|
|
493
|
+
* @example
|
|
494
|
+
* ```typescript
|
|
495
|
+
* // Regular usage
|
|
496
|
+
* const result = Result.err("error");
|
|
497
|
+
* const mapped = Result.mapErr(result, e => e.toUpperCase());
|
|
498
|
+
* console.log(Result.unwrapErr(mapped)); // "ERROR"
|
|
499
|
+
*
|
|
500
|
+
* // Curried usage for pipe composition
|
|
501
|
+
* const errorUppercase = Result.mapErr((e: string) => e.toUpperCase());
|
|
502
|
+
* const result2 = pipe(Result.err("error")).map(errorUppercase).value;
|
|
503
|
+
* console.log(Result.unwrapErr(result2)); // "ERROR"
|
|
504
|
+
* ```
|
|
505
|
+
*/
|
|
506
|
+
Result.mapErr = ((...args) => {
|
|
507
|
+
switch (args.length) {
|
|
508
|
+
case 2: {
|
|
509
|
+
const [result, mapFn] = args;
|
|
510
|
+
return Result.isOk(result)
|
|
511
|
+
? result
|
|
512
|
+
: Result.err(mapFn(result.value));
|
|
513
|
+
}
|
|
514
|
+
case 1: {
|
|
515
|
+
// Curried version: first argument is mapping function
|
|
516
|
+
const [mapFn] = args;
|
|
517
|
+
return (result) => Result.mapErr(result, mapFn);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
/**
|
|
522
|
+
* Applies one of two functions depending on whether the `Result` is `Ok` or `Err`.
|
|
523
|
+
* @template R The input `Result.Base` type.
|
|
524
|
+
* @template S2 The type of the success value returned by `mapFn`.
|
|
525
|
+
* @template E2 The type of the error value returned by `mapErrFn`.
|
|
526
|
+
* @param result The `Result` to fold.
|
|
527
|
+
* @param mapFn The function to apply if `result` is `Ok`.
|
|
528
|
+
* @param mapErrFn The function to apply if `result` is `Err`.
|
|
529
|
+
* @returns A new `Result<S2, E2>` based on the applied function.
|
|
530
|
+
* @example
|
|
531
|
+
* ```typescript
|
|
532
|
+
* // Regular usage
|
|
533
|
+
* const result = Result.ok(42);
|
|
534
|
+
* const folded = Result.fold(result, x => x * 2, () => 0);
|
|
535
|
+
* console.log(Result.unwrapOk(folded)); // 84
|
|
536
|
+
*
|
|
537
|
+
* // Curried usage for pipe composition
|
|
538
|
+
* const folder = Result.fold((x: number) => x * 2, () => 0);
|
|
539
|
+
* const result2 = pipe(Result.ok(42)).map(folder).value;
|
|
540
|
+
* console.log(Result.unwrapOk(result2)); // 84
|
|
541
|
+
* ```
|
|
542
|
+
*/
|
|
543
|
+
Result.fold = ((...args) => {
|
|
544
|
+
switch (args.length) {
|
|
545
|
+
case 3: {
|
|
546
|
+
const [result, mapFn, mapErrFn] = args;
|
|
547
|
+
return Result.isOk(result)
|
|
548
|
+
? Result.ok(mapFn(result.value))
|
|
549
|
+
: Result.err(mapErrFn(result.value));
|
|
550
|
+
}
|
|
551
|
+
case 2: {
|
|
552
|
+
const [mapFn, mapErrFn] = args;
|
|
553
|
+
return (result) => Result.isOk(result) ? Result.ok(mapFn(result.value)) : Result.err(mapErrFn(result.value));
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
/**
|
|
558
|
+
* Applies a function that returns a `Result` to the success value of a `Result`.
|
|
559
|
+
* If the input is `Err`, returns the original `Err`.
|
|
560
|
+
* This is the monadic bind operation for `Result`.
|
|
561
|
+
* @template R The input `Result.Base` type.
|
|
562
|
+
* @template S2 The success type of the `Result` returned by the function.
|
|
563
|
+
* @template E2 The error type of the `Result` returned by the function.
|
|
564
|
+
* @param result The `Result` to flat map.
|
|
565
|
+
* @param flatMapFn The function to apply that returns a `Result`.
|
|
566
|
+
* @returns The result of applying the function, or the original `Err`.
|
|
567
|
+
* @example
|
|
568
|
+
* ```typescript
|
|
569
|
+
* // Regular usage
|
|
570
|
+
* const divide = (a: number, b: number): Result<number, string> =>
|
|
571
|
+
* b === 0 ? Result.err("Division by zero") : Result.ok(a / b);
|
|
572
|
+
*
|
|
573
|
+
* const result = Result.flatMap(Result.ok(10), x => divide(x, 2));
|
|
574
|
+
* console.log(Result.unwrapOk(result)); // 5
|
|
575
|
+
*
|
|
576
|
+
* // Curried usage for pipe composition
|
|
577
|
+
* const divideBy2 = Result.flatMap((x: number) => divide(x, 2));
|
|
578
|
+
* const result2 = pipe(Result.ok(10)).map(divideBy2).value;
|
|
579
|
+
* console.log(Result.unwrapOk(result2)); // 5
|
|
580
|
+
* ```
|
|
581
|
+
*/
|
|
582
|
+
Result.flatMap = ((...args) => {
|
|
583
|
+
switch (args.length) {
|
|
584
|
+
case 2: {
|
|
585
|
+
const [result, flatMapFn] = args;
|
|
586
|
+
return Result.isErr(result)
|
|
587
|
+
? result
|
|
588
|
+
: flatMapFn(result.value);
|
|
589
|
+
}
|
|
590
|
+
case 1: {
|
|
591
|
+
const [flatMapFn] = args;
|
|
592
|
+
return (result) => Result.isErr(result) ? result : flatMapFn(result.value);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
});
|
|
596
|
+
/**
|
|
597
|
+
* Unwraps a `Result`, returning the success value or throwing an error with the provided message.
|
|
598
|
+
* @template R The `Result.Base` type to unwrap.
|
|
599
|
+
* @param result The `Result` to unwrap.
|
|
600
|
+
* @param message The error message to throw if the `Result` is `Result.Err`.
|
|
601
|
+
* @returns The success value if `Result.Ok`.
|
|
602
|
+
* @throws Error with the provided message if the `Result` is `Result.Err`.
|
|
603
|
+
* @example
|
|
604
|
+
* ```typescript
|
|
605
|
+
* // Regular usage
|
|
606
|
+
* const result = Result.ok(42);
|
|
607
|
+
* const value = Result.expectToBe(result, "Operation must succeed");
|
|
608
|
+
* console.log(value); // 42
|
|
609
|
+
*
|
|
610
|
+
* // Curried usage for pipe composition
|
|
611
|
+
* const mustBeOk = Result.expectToBe("Operation must succeed");
|
|
612
|
+
* const value2 = pipe(Result.ok(42)).map(mustBeOk).value;
|
|
613
|
+
* console.log(value2); // 42
|
|
614
|
+
* ```
|
|
615
|
+
*/
|
|
616
|
+
Result.expectToBe = ((...args) => {
|
|
617
|
+
switch (args.length) {
|
|
618
|
+
case 2: {
|
|
619
|
+
// Direct version: first argument is result
|
|
620
|
+
const [result, message] = args;
|
|
621
|
+
if (Result.isOk(result)) {
|
|
622
|
+
return Result.unwrapOk(result);
|
|
623
|
+
}
|
|
624
|
+
throw new Error(message);
|
|
625
|
+
}
|
|
626
|
+
case 1: {
|
|
627
|
+
// Curried version: first argument is message
|
|
628
|
+
const [message] = args;
|
|
629
|
+
return (result) => Result.expectToBe(result, message);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
});
|
|
633
|
+
/**
|
|
634
|
+
* Converts a Promise into a Promise that resolves to a `Result`.
|
|
635
|
+
* If the input Promise resolves, the `Result` will be `Ok` with the resolved value.
|
|
636
|
+
* If the input Promise rejects, the `Result` will be `Err` with the rejection reason.
|
|
637
|
+
* @template P The type of the input Promise.
|
|
638
|
+
* @param promise The Promise to convert.
|
|
639
|
+
* @returns A Promise that resolves to `Result<UnwrapPromise<P>, unknown>`.
|
|
640
|
+
*/
|
|
641
|
+
Result.fromPromise = (promise) => promise.then((v) => Result.ok(v)).catch(Result.err);
|
|
642
|
+
/**
|
|
643
|
+
* Wraps a function that may throw an exception in a `Result`.
|
|
644
|
+
*
|
|
645
|
+
* This is a fundamental utility for converting traditional exception-based error
|
|
646
|
+
* handling into Result-based error handling. Any thrown value is converted to an
|
|
647
|
+
* Error object for consistent error handling.
|
|
648
|
+
*
|
|
649
|
+
* If the function executes successfully, returns `Result.Ok` with the result.
|
|
650
|
+
* If the function throws, returns `Result.Err` with the caught error.
|
|
651
|
+
*
|
|
652
|
+
* @template T The return type of the function.
|
|
653
|
+
* @param fn The function to execute that may throw.
|
|
654
|
+
* @returns A `Result<T, Error>` containing either the successful result or the caught error.
|
|
655
|
+
* @example
|
|
656
|
+
* ```typescript
|
|
657
|
+
* // Wrapping JSON.parse which can throw
|
|
658
|
+
* const parseJson = <T>(text: string): Result<T, Error> =>
|
|
659
|
+
* Result.fromThrowable(() => JSON.parse(text) as T);
|
|
660
|
+
*
|
|
661
|
+
* const validJson = parseJson<{valid: boolean}>('{"valid": true}');
|
|
662
|
+
* if (Result.isOk(validJson)) {
|
|
663
|
+
* console.log(validJson.value.valid); // true
|
|
664
|
+
* }
|
|
665
|
+
*
|
|
666
|
+
* const invalidJson = parseJson('{invalid json}');
|
|
667
|
+
* if (Result.isErr(invalidJson)) {
|
|
668
|
+
* console.log(invalidJson.value.message); // SyntaxError message
|
|
669
|
+
* }
|
|
670
|
+
*
|
|
671
|
+
* // Using with custom validation
|
|
672
|
+
* const parsePositiveNumber = (str: string): Result<number, Error> =>
|
|
673
|
+
* Result.fromThrowable(() => {
|
|
674
|
+
* const num = Number(str);
|
|
675
|
+
* if (Number.isNaN(num)) throw new Error(`Not a number: ${str}`);
|
|
676
|
+
* if (num <= 0) throw new Error(`Must be positive: ${num}`);
|
|
677
|
+
* return num;
|
|
678
|
+
* });
|
|
679
|
+
*
|
|
680
|
+
* const success = parsePositiveNumber('42');
|
|
681
|
+
* console.log(Result.unwrapOkOr(success, 0)); // 42
|
|
682
|
+
*
|
|
683
|
+
* const failure = parsePositiveNumber('abc');
|
|
684
|
+
* console.log(Result.unwrapOkOr(failure, 0)); // 0
|
|
685
|
+
*
|
|
686
|
+
* // Wrapping DOM operations that might fail
|
|
687
|
+
* const getElementText = (id: string): Result<string, Error> =>
|
|
688
|
+
* Result.fromThrowable(() => {
|
|
689
|
+
* const element = document.getElementById(id);
|
|
690
|
+
* if (!element) throw new Error(`Element not found: ${id}`);
|
|
691
|
+
* return element.textContent || "";
|
|
692
|
+
* });
|
|
693
|
+
*
|
|
694
|
+
* // Wrapping file operations
|
|
695
|
+
* const readFileSync = (path: string): Result<string, Error> =>
|
|
696
|
+
* Result.fromThrowable(() =>
|
|
697
|
+
* require('fs').readFileSync(path, 'utf8')
|
|
698
|
+
* );
|
|
699
|
+
* ```
|
|
700
|
+
*/
|
|
701
|
+
Result.fromThrowable = (fn) => {
|
|
702
|
+
try {
|
|
703
|
+
return Result.ok(fn());
|
|
704
|
+
}
|
|
705
|
+
catch (error) {
|
|
706
|
+
if (error instanceof Error) {
|
|
707
|
+
return Result.err(error);
|
|
708
|
+
}
|
|
709
|
+
const msg = unknownToString(error);
|
|
710
|
+
if (Result.isErr(msg)) {
|
|
711
|
+
return Result.err(new Error(String(error)));
|
|
712
|
+
}
|
|
713
|
+
else {
|
|
714
|
+
return Result.err(new Error(msg.value));
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
/**
|
|
719
|
+
* Swaps the success and error values of a `Result`.
|
|
720
|
+
* @template R The input `Result.Base` type.
|
|
721
|
+
* @param result The `Result` to swap.
|
|
722
|
+
* @returns A new `Result` with success and error swapped.
|
|
723
|
+
* @example
|
|
724
|
+
* ```typescript
|
|
725
|
+
* const okResult = Result.ok(42);
|
|
726
|
+
* const swapped = Result.swap(okResult);
|
|
727
|
+
* console.log(Result.isErr(swapped)); // true
|
|
728
|
+
* console.log(Result.unwrapErr(swapped)); // 42
|
|
729
|
+
* ```
|
|
730
|
+
*/
|
|
731
|
+
Result.swap = (result) => Result.isOk(result) ? Result.err(Result.unwrapOk(result)) : Result.ok(result.value);
|
|
732
|
+
/**
|
|
733
|
+
* Converts a `Result` to an `Optional`.
|
|
734
|
+
*
|
|
735
|
+
* This conversion is useful when you want to discard error information and only
|
|
736
|
+
* care about whether an operation succeeded. The error information is lost in
|
|
737
|
+
* this conversion, so use it when error details are not needed.
|
|
738
|
+
*
|
|
739
|
+
* If the `Result` is `Ok`, returns `Some` with the value.
|
|
740
|
+
* If the `Result` is `Err`, returns `None`.
|
|
741
|
+
*
|
|
742
|
+
* @template R The input `Result.Base` type.
|
|
743
|
+
* @param result The `Result` to convert.
|
|
744
|
+
* @returns An `Optional<UnwrapOk<R>>` containing the success value or representing `None`.
|
|
745
|
+
* @example
|
|
746
|
+
* ```typescript
|
|
747
|
+
* // Basic conversion
|
|
748
|
+
* const okResult = Result.ok(42);
|
|
749
|
+
* const optional = Result.toOptional(okResult);
|
|
750
|
+
* console.log(Optional.isSome(optional)); // true
|
|
751
|
+
* console.log(Optional.unwrap(optional)); // 42
|
|
752
|
+
*
|
|
753
|
+
* const errResult = Result.err("Network error");
|
|
754
|
+
* const none = Result.toOptional(errResult);
|
|
755
|
+
* console.log(Optional.isNone(none)); // true
|
|
756
|
+
*
|
|
757
|
+
* // Use case: when you only care about success, not error details
|
|
758
|
+
* const fetchUserName = (id: number): Result<string, ApiError> => {
|
|
759
|
+
* // ... implementation
|
|
760
|
+
* };
|
|
761
|
+
*
|
|
762
|
+
* const maybeUserName = Result.toOptional(fetchUserName(123));
|
|
763
|
+
* const displayName = Optional.unwrapOr(maybeUserName, "Unknown User");
|
|
764
|
+
*
|
|
765
|
+
* // Converting multiple Results and filtering successes
|
|
766
|
+
* const userIds = [1, 2, 3, 4];
|
|
767
|
+
* const userNames = userIds
|
|
768
|
+
* .map(fetchUserName)
|
|
769
|
+
* .map(Result.toOptional)
|
|
770
|
+
* .filter(Optional.isSome)
|
|
771
|
+
* .map(Optional.unwrap); // string[]
|
|
772
|
+
*
|
|
773
|
+
* // Chaining with Optional operations
|
|
774
|
+
* const processResult = (r: Result<string, Error>) =>
|
|
775
|
+
* pipe(Result.toOptional(r))
|
|
776
|
+
* .map(Optional.map(s => s.toUpperCase()))
|
|
777
|
+
* .map(Optional.filter(s => s.length > 0))
|
|
778
|
+
* .value;
|
|
779
|
+
* ```
|
|
780
|
+
*/
|
|
781
|
+
Result.toOptional = (result) => Result.isOk(result) ? Optional.some(Result.unwrapOk(result)) : Optional.none;
|
|
782
|
+
/**
|
|
783
|
+
* Returns the `Result` if it is `Ok`, otherwise returns the alternative.
|
|
784
|
+
* @template R The input `Result.Base` type.
|
|
785
|
+
* @param result The `Result` to check.
|
|
786
|
+
* @param alternative The alternative `Result` to return if the first is `Err`.
|
|
787
|
+
* @returns The first `Result` if `Ok`, otherwise the alternative.
|
|
788
|
+
* @example
|
|
789
|
+
* ```typescript
|
|
790
|
+
* // Regular usage
|
|
791
|
+
* const primary = Result.err("error");
|
|
792
|
+
* const fallback = Result.ok("default");
|
|
793
|
+
* const result = Result.orElse(primary, fallback);
|
|
794
|
+
* console.log(Result.unwrapOk(result)); // "default"
|
|
795
|
+
*
|
|
796
|
+
* // Curried usage for pipe composition
|
|
797
|
+
* const fallbackTo = Result.orElse(Result.ok("fallback"));
|
|
798
|
+
* const result2 = pipe(Result.err("error")).map(fallbackTo).value;
|
|
799
|
+
* console.log(Result.unwrapOk(result2)); // "fallback"
|
|
800
|
+
* ```
|
|
801
|
+
*/
|
|
802
|
+
Result.orElse = ((...args) => {
|
|
803
|
+
switch (args.length) {
|
|
804
|
+
case 2: {
|
|
805
|
+
const [result, alternative] = args;
|
|
806
|
+
return Result.isOk(result) ? result : alternative;
|
|
807
|
+
}
|
|
808
|
+
case 1: {
|
|
809
|
+
// Curried version: one argument (alternative) provided
|
|
810
|
+
const [alternative] = args;
|
|
811
|
+
return (result) => Result.orElse(result, alternative);
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
});
|
|
815
|
+
/**
|
|
816
|
+
* Combines two `Result` values into a single `Result` containing a tuple.
|
|
817
|
+
* If either `Result` is `Err`, returns the first `Err` encountered.
|
|
818
|
+
* @template S1 The success type of the first `Result`.
|
|
819
|
+
* @template E1 The error type of the first `Result`.
|
|
820
|
+
* @template S2 The success type of the second `Result`.
|
|
821
|
+
* @template E2 The error type of the second `Result`.
|
|
822
|
+
* @param resultA The first `Result`.
|
|
823
|
+
* @param resultB The second `Result`.
|
|
824
|
+
* @returns A `Result` containing a tuple of both values, or the first `Err`.
|
|
825
|
+
* @example
|
|
826
|
+
* ```typescript
|
|
827
|
+
* const a = Result.ok(1);
|
|
828
|
+
* const b = Result.ok("hello");
|
|
829
|
+
* const zipped = Result.zip(a, b);
|
|
830
|
+
* console.log(Result.unwrapOk(zipped)); // [1, "hello"]
|
|
831
|
+
*
|
|
832
|
+
* const withErr = Result.zip(a, Result.err("error"));
|
|
833
|
+
* console.log(Result.unwrapErr(withErr)); // "error"
|
|
834
|
+
* ```
|
|
835
|
+
*/
|
|
836
|
+
Result.zip = (resultA, resultB) => Result.isOk(resultA)
|
|
837
|
+
? Result.isOk(resultB)
|
|
838
|
+
? Result.ok([resultA.value, resultB.value])
|
|
839
|
+
: resultB
|
|
840
|
+
: resultA;
|
|
841
|
+
})(Result || (Result = {}));
|
|
842
|
+
|
|
843
|
+
export { Result };
|
|
844
|
+
//# sourceMappingURL=result.mjs.map
|