@madkarma/result 1.0.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -19
- package/dist/index.d.ts +1 -57
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -30
- package/dist/index.js.map +1 -1
- package/dist/result.d.ts +196 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +145 -0
- package/dist/result.js.map +1 -0
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# @madkarma/result
|
|
2
2
|
|
|
3
|
-
Rust's Result type, for TypeScript.
|
|
3
|
+
Rust's Result type, for TypeScript.
|
|
4
|
+
|
|
5
|
+
Inspired by [this video](https://www.youtube.com/watch?v=ovnyeq-Xxrc) by Web Dev Simplified and [vultix/ts-results](https://github.com/vultix/ts-results).
|
|
6
|
+
|
|
7
|
+
This library mimics the Rust `Result` enum and includes its chainable methods adapted for TypeScript. For full documentation on the available methods, please refer to the [official Rust Result documentation](https://doc.rust-lang.org/std/result/enum.Result.html) (or read the JSDocs directly in your editor).
|
|
4
8
|
|
|
5
9
|
## Installation
|
|
6
10
|
|
|
@@ -19,40 +23,49 @@ yarn add @madkarma/result
|
|
|
19
23
|
```typescript
|
|
20
24
|
import { Ok, Err } from '@madkarma/result';
|
|
21
25
|
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
const parseUserId = (id: string) => {
|
|
27
|
+
const parsed = parseInt(id, 10);
|
|
28
|
+
if (isNaN(parsed))
|
|
29
|
+
return Err({
|
|
30
|
+
code: 'INVALID_INPUT',
|
|
31
|
+
message: 'ID must be a valid number'
|
|
32
|
+
});
|
|
25
33
|
|
|
26
|
-
if (
|
|
34
|
+
if (parsed <= 0)
|
|
27
35
|
return Err({ code: 'INVALID_ID', message: 'ID must be positive' });
|
|
28
36
|
|
|
29
|
-
|
|
37
|
+
return Ok(parsed);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const fetchUser = (id: number) => {
|
|
41
|
+
if (id === 13) return Err({ code: 'NOT_FOUND', message: 'User not found' });
|
|
30
42
|
|
|
31
|
-
return Ok({ id, name: 'Alice' });
|
|
43
|
+
return Ok({ id, name: 'Alice', role: 'admin' });
|
|
32
44
|
};
|
|
33
45
|
|
|
34
|
-
|
|
46
|
+
// Processing an input by chaining methods
|
|
47
|
+
const { value: user, error } = parseUserId('10')
|
|
48
|
+
.map((id) => id + 3) // Transform the Ok value (10 -> 13)
|
|
49
|
+
.andThen(fetchUser); // Chain operations that return another Result
|
|
35
50
|
|
|
36
|
-
if (error)
|
|
51
|
+
if (error) {
|
|
37
52
|
switch (error.code) {
|
|
38
|
-
case '
|
|
39
|
-
console.error(error.message);
|
|
40
|
-
break;
|
|
53
|
+
case 'INVALID_INPUT':
|
|
41
54
|
case 'INVALID_ID':
|
|
42
|
-
console.error(error.message);
|
|
55
|
+
console.error(`Validation Error: ${error.message}`);
|
|
43
56
|
break;
|
|
44
57
|
case 'NOT_FOUND':
|
|
45
|
-
console.error(error.message);
|
|
58
|
+
console.error(`Database Error: ${error.message}`);
|
|
46
59
|
break;
|
|
47
60
|
}
|
|
48
|
-
else
|
|
61
|
+
} else {
|
|
62
|
+
console.log(`Welcome, ${user.role} ${user.name}!`);
|
|
63
|
+
}
|
|
49
64
|
```
|
|
50
65
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
Instead of Rust's `match` expressions, check `[value, error]` directly and use a JavaScript `switch` on `error.code` to emulate pattern matching.
|
|
66
|
+
## How this differs from Rust
|
|
54
67
|
|
|
55
|
-
|
|
68
|
+
Instead of Rust's `match` expressions, check `{ value, error }` directly and use a `switch` on `error.code` to emulate pattern matching.
|
|
56
69
|
|
|
57
70
|
## Contributing
|
|
58
71
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,58 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
* `Result<T, E>` is the type used for returning and propagating errors.
|
|
3
|
-
*
|
|
4
|
-
* It is a type with the parameters, `Ok(T)`, representing success and containing a value,
|
|
5
|
-
* and `Err(E)`, representing error and containing an error value.
|
|
6
|
-
*
|
|
7
|
-
* Functions return `Result` whenever errors are expected and recoverable.
|
|
8
|
-
*
|
|
9
|
-
* The error type `E` must be an object that contains a `code` property of type `string`.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```typescript
|
|
13
|
-
* const divide = (a: number, b: number) => {
|
|
14
|
-
* if (b === 0) return Err({ code: 'DIVIDE_BY_ZERO' });
|
|
15
|
-
* return Ok(a / b);
|
|
16
|
-
* }
|
|
17
|
-
*
|
|
18
|
-
* const [value, error] = divide(10, 2);
|
|
19
|
-
* if (error) console.error(error.code);
|
|
20
|
-
* else console.log(value);
|
|
21
|
-
* ```
|
|
22
|
-
*
|
|
23
|
-
* @see https://www.youtube.com/watch?v=ovnyeq-Xxrc
|
|
24
|
-
* @template T - Contains the success value.
|
|
25
|
-
* @template E - Contains the error value. Must have a `code` property of type `string`.
|
|
26
|
-
*/
|
|
27
|
-
export type Result<T, E extends {
|
|
28
|
-
code: string;
|
|
29
|
-
}> = [T, null] | [null, E];
|
|
30
|
-
/**
|
|
31
|
-
* Contains the success value.
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* ```typescript
|
|
35
|
-
* const [value, _] = Ok(42);
|
|
36
|
-
* ```
|
|
37
|
-
*
|
|
38
|
-
* @see https://www.youtube.com/watch?v=ovnyeq-Xxrc
|
|
39
|
-
* @param value - The value to wrap in a successful result.
|
|
40
|
-
* @returns A `Result` representing a successful outcome.
|
|
41
|
-
*/
|
|
42
|
-
export declare const Ok: <T>(value: T) => Result<T, never>;
|
|
43
|
-
/**
|
|
44
|
-
* Contains the error value.
|
|
45
|
-
*
|
|
46
|
-
* @example
|
|
47
|
-
* ```typescript
|
|
48
|
-
* const [_, error] = Err({ code: 'NOT_FOUND' });
|
|
49
|
-
* ```
|
|
50
|
-
*
|
|
51
|
-
* @see https://www.youtube.com/watch?v=ovnyeq-Xxrc
|
|
52
|
-
* @param error - The error to wrap in a failed result. Must have a `code` property of type `string`.
|
|
53
|
-
* @returns A `Result` representing a failed outcome.
|
|
54
|
-
*/
|
|
55
|
-
export declare const Err: <const C extends string, E extends {
|
|
56
|
-
code: C;
|
|
57
|
-
}>(error: E) => Result<never, E>;
|
|
1
|
+
export * from './result';
|
|
58
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,31 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
* Contains the success value.
|
|
3
|
-
*
|
|
4
|
-
* @example
|
|
5
|
-
* ```typescript
|
|
6
|
-
* const [value, _] = Ok(42);
|
|
7
|
-
* ```
|
|
8
|
-
*
|
|
9
|
-
* @see https://www.youtube.com/watch?v=ovnyeq-Xxrc
|
|
10
|
-
* @param value - The value to wrap in a successful result.
|
|
11
|
-
* @returns A `Result` representing a successful outcome.
|
|
12
|
-
*/
|
|
13
|
-
export const Ok = (value) => [value, null];
|
|
14
|
-
/**
|
|
15
|
-
* Contains the error value.
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```typescript
|
|
19
|
-
* const [_, error] = Err({ code: 'NOT_FOUND' });
|
|
20
|
-
* ```
|
|
21
|
-
*
|
|
22
|
-
* @see https://www.youtube.com/watch?v=ovnyeq-Xxrc
|
|
23
|
-
* @param error - The error to wrap in a failed result. Must have a `code` property of type `string`.
|
|
24
|
-
* @returns A `Result` representing a failed outcome.
|
|
25
|
-
*/
|
|
26
|
-
export const Err = (error) => {
|
|
27
|
-
if (typeof error.code !== 'string')
|
|
28
|
-
throw new TypeError('Error object must have a code property of type string');
|
|
29
|
-
return [null, error];
|
|
30
|
-
};
|
|
1
|
+
export * from './result';
|
|
31
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}
|
package/dist/result.d.ts
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The base interface for all errors returned by a `Result`.
|
|
3
|
+
* It requires a `code` property which can be used to identify the error type.
|
|
4
|
+
*/
|
|
5
|
+
export interface ResultError {
|
|
6
|
+
code: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Represents a successful `Result` containing a value of type `T`.
|
|
10
|
+
*/
|
|
11
|
+
export type OkResult<T, E extends ResultError> = {
|
|
12
|
+
readonly value: T;
|
|
13
|
+
readonly error: null;
|
|
14
|
+
} & ResultMethods<T, E>;
|
|
15
|
+
/**
|
|
16
|
+
* Represents a failed `Result` containing an error of type `E`.
|
|
17
|
+
*/
|
|
18
|
+
export type ErrResult<T, E extends ResultError> = {
|
|
19
|
+
readonly value: null;
|
|
20
|
+
readonly error: E;
|
|
21
|
+
} & ResultMethods<T, E>;
|
|
22
|
+
/**
|
|
23
|
+
* `Result<T, E>` is the type used for returning and propagating errors.
|
|
24
|
+
*
|
|
25
|
+
* It is a type with the parameters, `Ok(T)`, representing success and containing a value,
|
|
26
|
+
* and `Err(E)`, representing error and containing an error value.
|
|
27
|
+
*
|
|
28
|
+
* Functions return `Result` whenever errors are expected and recoverable.
|
|
29
|
+
*
|
|
30
|
+
* The error type `E` must extend `ResultError` which contains a `code` property of type `string`.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const divide = (a: number, b: number) => {
|
|
35
|
+
* if (b === 0) return Err({ code: 'DIVIDE_BY_ZERO' });
|
|
36
|
+
* return Ok(a / b);
|
|
37
|
+
* }
|
|
38
|
+
*
|
|
39
|
+
* const { value, error } = divide(10, 2);
|
|
40
|
+
* if (error) console.error(error.code);
|
|
41
|
+
* else console.log(value);
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @see https://www.youtube.com/watch?v=ovnyeq-Xxrc
|
|
45
|
+
* @template T - Contains the success value.
|
|
46
|
+
* @template E - Contains the error value. Must have a `code` property of type `string`.
|
|
47
|
+
*/
|
|
48
|
+
export type Result<T, E extends ResultError> = OkResult<T, E> | ErrResult<T, E>;
|
|
49
|
+
interface ResultMethods<T, E extends ResultError> {
|
|
50
|
+
/**
|
|
51
|
+
* Returns `true` if the result is `Ok`.
|
|
52
|
+
*/
|
|
53
|
+
isOk(): this is OkResult<T, E>;
|
|
54
|
+
/**
|
|
55
|
+
* Returns `true` if the result is `Ok` and the value inside of it matches a predicate.
|
|
56
|
+
*/
|
|
57
|
+
isOkAnd(fn: (val: T) => boolean): this is OkResult<T, E>;
|
|
58
|
+
/**
|
|
59
|
+
* Returns `true` if the result is `Err`.
|
|
60
|
+
*/
|
|
61
|
+
isErr(): this is ErrResult<T, E>;
|
|
62
|
+
/**
|
|
63
|
+
* Returns `true` if the result is `Err` and the value inside of it matches a predicate.
|
|
64
|
+
*/
|
|
65
|
+
isErrAnd(fn: (err: E) => boolean): this is ErrResult<T, E>;
|
|
66
|
+
/**
|
|
67
|
+
* Maps a `Result<T, E>` to `Result<U, E>` by applying a function to a contained `Ok` value, leaving an `Err` value untouched.
|
|
68
|
+
*
|
|
69
|
+
* This function can be used to compose the results of two functions.
|
|
70
|
+
*/
|
|
71
|
+
map<U>(fn: (val: T) => U): Result<U, E>;
|
|
72
|
+
/**
|
|
73
|
+
* Returns the provided default (if `Err`), or applies a function to the contained value (if `Ok`).
|
|
74
|
+
*
|
|
75
|
+
* Arguments passed to `mapOr` are eagerly evaluated; if you are passing the result of a function call, it is recommended to use `mapOrElse`, which is lazily evaluated.
|
|
76
|
+
*/
|
|
77
|
+
mapOr<U>(fallback: U, fn: (val: T) => U): U;
|
|
78
|
+
/**
|
|
79
|
+
* Maps a `Result<T, E>` to `U` by applying fallback function `fallbackFn` to a contained `Err` value, or function `fn` to a contained `Ok` value.
|
|
80
|
+
*
|
|
81
|
+
* This function can be used to unpack a successful result while handling an error.
|
|
82
|
+
*/
|
|
83
|
+
mapOrElse<U>(fallbackFn: (err: E) => U, fn: (val: T) => U): U;
|
|
84
|
+
/**
|
|
85
|
+
* Maps a `Result<T, E>` to `Result<T, F>` by applying a function to a contained `Err` value, leaving an `Ok` value untouched.
|
|
86
|
+
*
|
|
87
|
+
* This function can be used to pass through a successful result while handling an error.
|
|
88
|
+
*/
|
|
89
|
+
mapErr<F extends ResultError>(fn: (err: E) => F): Result<T, F>;
|
|
90
|
+
/**
|
|
91
|
+
* Calls a function with a reference to the contained value if `Ok`.
|
|
92
|
+
*
|
|
93
|
+
* Returns the original result.
|
|
94
|
+
*/
|
|
95
|
+
inspect(fn: (val: T) => void): Result<T, E>;
|
|
96
|
+
/**
|
|
97
|
+
* Calls a function with a reference to the contained value if `Err`.
|
|
98
|
+
*
|
|
99
|
+
* Returns the original result.
|
|
100
|
+
*/
|
|
101
|
+
inspectErr(fn: (err: E) => void): Result<T, E>;
|
|
102
|
+
/**
|
|
103
|
+
* Returns an iterator over the possibly contained value.
|
|
104
|
+
*
|
|
105
|
+
* The iterator yields one value if the result is `Result::Ok`, otherwise none.
|
|
106
|
+
*/
|
|
107
|
+
iter(): Iterable<T>;
|
|
108
|
+
/**
|
|
109
|
+
* Returns the contained `Ok` value, consuming the `self` value.
|
|
110
|
+
*
|
|
111
|
+
* @throws Throws if the value is an `Err`, with an error message including the passed message, and the content of the `Err`.
|
|
112
|
+
*/
|
|
113
|
+
expect(msg: string): T;
|
|
114
|
+
/**
|
|
115
|
+
* Returns the contained `Ok` value, consuming the `self` value.
|
|
116
|
+
*
|
|
117
|
+
* @throws Throws if the value is an `Err`, with an error message provided by the `Err`'s value.
|
|
118
|
+
*/
|
|
119
|
+
unwrap(): T;
|
|
120
|
+
/**
|
|
121
|
+
* Returns the contained `Err` value, consuming the `self` value.
|
|
122
|
+
*
|
|
123
|
+
* @throws Throws if the value is an `Ok`, with an error message including the passed message, and the content of the `Ok`.
|
|
124
|
+
*/
|
|
125
|
+
expectErr(msg: string): E;
|
|
126
|
+
/**
|
|
127
|
+
* Returns the contained `Err` value, consuming the `self` value.
|
|
128
|
+
*
|
|
129
|
+
* @throws Throws if the value is an `Ok`, with a custom error message provided by the `Ok`'s value.
|
|
130
|
+
*/
|
|
131
|
+
unwrapErr(): E;
|
|
132
|
+
/**
|
|
133
|
+
* Returns `res` if the result is `Ok`, otherwise returns the `Err` value of `self`.
|
|
134
|
+
*
|
|
135
|
+
* Arguments passed to `and` are eagerly evaluated; if you are passing the result of a function call, it is recommended to use `andThen`, which is lazily evaluated.
|
|
136
|
+
*/
|
|
137
|
+
and<U, E2 extends ResultError>(res: Result<U, E2>): Result<U, E | E2>;
|
|
138
|
+
/**
|
|
139
|
+
* Calls `fn` if the result is `Ok`, otherwise returns the `Err` value of `self`.
|
|
140
|
+
*
|
|
141
|
+
* This function can be used for control flow based on `Result` values.
|
|
142
|
+
*/
|
|
143
|
+
andThen<U, F extends ResultError>(fn: (val: T) => Result<U, F>): Result<U, E | F>;
|
|
144
|
+
/**
|
|
145
|
+
* Returns `res` if the result is `Err`, otherwise returns the `Ok` value of `self`.
|
|
146
|
+
*
|
|
147
|
+
* Arguments passed to `or` are eagerly evaluated; if you are passing the result of a function call, it is recommended to use `orElse`, which is lazily evaluated.
|
|
148
|
+
*/
|
|
149
|
+
or<T2, F extends ResultError>(res: Result<T2, F>): Result<T | T2, F>;
|
|
150
|
+
/**
|
|
151
|
+
* Calls `fn` if the result is `Err`, otherwise returns the `Ok` value of `self`.
|
|
152
|
+
*
|
|
153
|
+
* This function can be used for control flow based on result values.
|
|
154
|
+
*/
|
|
155
|
+
orElse<T2, F extends ResultError>(fn: (err: E) => Result<T2, F>): Result<T | T2, F>;
|
|
156
|
+
/**
|
|
157
|
+
* Returns the contained `Ok` value or a provided default.
|
|
158
|
+
*
|
|
159
|
+
* Arguments passed to `unwrapOr` are eagerly evaluated; if you are passing the result of a function call, it is recommended to use `unwrapOrElse`, which is lazily evaluated.
|
|
160
|
+
*/
|
|
161
|
+
unwrapOr<T2>(fallback: T2): T | T2;
|
|
162
|
+
/**
|
|
163
|
+
* Returns the contained `Ok` value or computes it from a closure.
|
|
164
|
+
*/
|
|
165
|
+
unwrapOrElse<T2>(fn: (err: E) => T2): T | T2;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Contains the success value.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```typescript
|
|
172
|
+
* const { value } = Ok(42);
|
|
173
|
+
* ```
|
|
174
|
+
*
|
|
175
|
+
* @see https://www.youtube.com/watch?v=ovnyeq-Xxrc
|
|
176
|
+
* @param value - The value to wrap in a successful result.
|
|
177
|
+
* @returns A `Result` representing a successful outcome.
|
|
178
|
+
*/
|
|
179
|
+
export declare const Ok: <T, E extends ResultError = never>(value: T) => Result<T, E>;
|
|
180
|
+
/**
|
|
181
|
+
* Contains the error value.
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* ```typescript
|
|
185
|
+
* const { error } = Err({ code: 'NOT_FOUND' });
|
|
186
|
+
* ```
|
|
187
|
+
*
|
|
188
|
+
* @see https://www.youtube.com/watch?v=ovnyeq-Xxrc
|
|
189
|
+
* @param error - The error to wrap in a failed result. Must have a `code` property of type `string`.
|
|
190
|
+
* @returns A `Result` representing a failed outcome.
|
|
191
|
+
*/
|
|
192
|
+
export declare const Err: <const C extends string, E extends ResultError & {
|
|
193
|
+
code: C;
|
|
194
|
+
}>(error: E) => Result<never, E>;
|
|
195
|
+
export {};
|
|
196
|
+
//# sourceMappingURL=result.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"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"}
|
package/dist/result.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
class ResultImpl {
|
|
2
|
+
// will error at runtime if trying to access # fields
|
|
3
|
+
#value;
|
|
4
|
+
#error;
|
|
5
|
+
constructor(value, error) {
|
|
6
|
+
this.#value = value;
|
|
7
|
+
this.#error = error;
|
|
8
|
+
}
|
|
9
|
+
// will prevent mutation at runtime
|
|
10
|
+
get value() {
|
|
11
|
+
return this.#value;
|
|
12
|
+
}
|
|
13
|
+
// will prevent mutation at runtime
|
|
14
|
+
get error() {
|
|
15
|
+
return this.#error;
|
|
16
|
+
}
|
|
17
|
+
isOk() {
|
|
18
|
+
return this.error === null;
|
|
19
|
+
}
|
|
20
|
+
isOkAnd(fn) {
|
|
21
|
+
return this.isOk() && fn(this.value);
|
|
22
|
+
}
|
|
23
|
+
isErr() {
|
|
24
|
+
return this.error !== null;
|
|
25
|
+
}
|
|
26
|
+
isErrAnd(fn) {
|
|
27
|
+
return this.isErr() && fn(this.error);
|
|
28
|
+
}
|
|
29
|
+
map(fn) {
|
|
30
|
+
if (this.isErr()) {
|
|
31
|
+
return new ResultImpl(null, this.error);
|
|
32
|
+
}
|
|
33
|
+
return new ResultImpl(fn(this.value), null);
|
|
34
|
+
}
|
|
35
|
+
mapOr(fallback, fn) {
|
|
36
|
+
if (this.isErr())
|
|
37
|
+
return fallback;
|
|
38
|
+
return fn(this.value);
|
|
39
|
+
}
|
|
40
|
+
mapOrElse(fallbackFn, fn) {
|
|
41
|
+
if (this.isErr())
|
|
42
|
+
return fallbackFn(this.error);
|
|
43
|
+
return fn(this.value);
|
|
44
|
+
}
|
|
45
|
+
mapErr(fn) {
|
|
46
|
+
if (this.isErr())
|
|
47
|
+
return new ResultImpl(null, fn(this.error));
|
|
48
|
+
return new ResultImpl(this.value, null);
|
|
49
|
+
}
|
|
50
|
+
inspect(fn) {
|
|
51
|
+
if (this.isOk())
|
|
52
|
+
fn(this.value);
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
inspectErr(fn) {
|
|
56
|
+
if (this.isErr())
|
|
57
|
+
fn(this.error);
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
*iter() {
|
|
61
|
+
if (this.isOk())
|
|
62
|
+
yield this.value;
|
|
63
|
+
}
|
|
64
|
+
expect(msg) {
|
|
65
|
+
if (this.isErr())
|
|
66
|
+
throw new Error(msg);
|
|
67
|
+
return this.value;
|
|
68
|
+
}
|
|
69
|
+
unwrap() {
|
|
70
|
+
if (this.error !== null)
|
|
71
|
+
throw this.error;
|
|
72
|
+
return this.value;
|
|
73
|
+
}
|
|
74
|
+
expectErr(msg) {
|
|
75
|
+
if (this.isOk())
|
|
76
|
+
throw new Error(msg);
|
|
77
|
+
return this.error;
|
|
78
|
+
}
|
|
79
|
+
unwrapErr() {
|
|
80
|
+
if (this.isOk())
|
|
81
|
+
throw new Error(String(this.value));
|
|
82
|
+
return this.error;
|
|
83
|
+
}
|
|
84
|
+
and(res) {
|
|
85
|
+
if (this.isOk())
|
|
86
|
+
return res;
|
|
87
|
+
return new ResultImpl(null, this.error);
|
|
88
|
+
}
|
|
89
|
+
andThen(fn) {
|
|
90
|
+
if (this.isOk())
|
|
91
|
+
return fn(this.value);
|
|
92
|
+
return new ResultImpl(null, this.error);
|
|
93
|
+
}
|
|
94
|
+
or(res) {
|
|
95
|
+
if (this.isErr())
|
|
96
|
+
return res;
|
|
97
|
+
return new ResultImpl(this.value, null);
|
|
98
|
+
}
|
|
99
|
+
orElse(fn) {
|
|
100
|
+
if (this.isErr())
|
|
101
|
+
return fn(this.error);
|
|
102
|
+
return new ResultImpl(this.value, null);
|
|
103
|
+
}
|
|
104
|
+
unwrapOr(fallback) {
|
|
105
|
+
if (this.isErr())
|
|
106
|
+
return fallback;
|
|
107
|
+
return this.value;
|
|
108
|
+
}
|
|
109
|
+
unwrapOrElse(fn) {
|
|
110
|
+
if (this.isErr())
|
|
111
|
+
return fn(this.error);
|
|
112
|
+
return this.value;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Contains the success value.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* const { value } = Ok(42);
|
|
121
|
+
* ```
|
|
122
|
+
*
|
|
123
|
+
* @see https://www.youtube.com/watch?v=ovnyeq-Xxrc
|
|
124
|
+
* @param value - The value to wrap in a successful result.
|
|
125
|
+
* @returns A `Result` representing a successful outcome.
|
|
126
|
+
*/
|
|
127
|
+
export const Ok = (value) => {
|
|
128
|
+
return new ResultImpl(value, null);
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Contains the error value.
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* const { error } = Err({ code: 'NOT_FOUND' });
|
|
136
|
+
* ```
|
|
137
|
+
*
|
|
138
|
+
* @see https://www.youtube.com/watch?v=ovnyeq-Xxrc
|
|
139
|
+
* @param error - The error to wrap in a failed result. Must have a `code` property of type `string`.
|
|
140
|
+
* @returns A `Result` representing a failed outcome.
|
|
141
|
+
*/
|
|
142
|
+
export const Err = (error) => {
|
|
143
|
+
return new ResultImpl(null, error);
|
|
144
|
+
};
|
|
145
|
+
//# sourceMappingURL=result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.js","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@madkarma/result",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Rust's Result type, for TypeScript",
|
|
5
5
|
"devDependencies": {
|
|
6
6
|
"prettier": "3.8.3",
|
|
7
|
-
"typescript": "^6.0.3"
|
|
7
|
+
"typescript": "^6.0.3",
|
|
8
|
+
"vitest": "^4.1.6"
|
|
8
9
|
},
|
|
9
10
|
"type": "module",
|
|
10
11
|
"exports": {
|
|
@@ -18,6 +19,8 @@
|
|
|
18
19
|
"dist"
|
|
19
20
|
],
|
|
20
21
|
"scripts": {
|
|
22
|
+
"test:dev": "vitest watch",
|
|
23
|
+
"test": "vitest run",
|
|
21
24
|
"build": "tsc",
|
|
22
25
|
"dev": "tsc --watch",
|
|
23
26
|
"format": "prettier --write --ignore-unknown .",
|