@qlever-llc/result 0.6.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 +25 -0
- package/esm/_dnt.polyfills.d.ts +7 -0
- package/esm/_dnt.polyfills.d.ts.map +1 -0
- package/esm/_dnt.polyfills.js +1 -0
- package/esm/error.d.ts +113 -0
- package/esm/error.d.ts.map +1 -0
- package/esm/error.js +163 -0
- package/esm/mod.d.ts +62 -0
- package/esm/mod.d.ts.map +1 -0
- package/esm/mod.js +59 -0
- package/esm/package.json +3 -0
- package/esm/result.d.ts +852 -0
- package/esm/result.d.ts.map +1 -0
- package/esm/result.js +1033 -0
- package/package.json +33 -0
- package/script/_dnt.polyfills.d.ts +7 -0
- package/script/_dnt.polyfills.d.ts.map +1 -0
- package/script/_dnt.polyfills.js +2 -0
- package/script/error.d.ts +113 -0
- package/script/error.d.ts.map +1 -0
- package/script/error.js +171 -0
- package/script/mod.d.ts +62 -0
- package/script/mod.d.ts.map +1 -0
- package/script/mod.js +67 -0
- package/script/package.json +3 -0
- package/script/result.d.ts +852 -0
- package/script/result.d.ts.map +1 -0
- package/script/result.js +1038 -0
package/esm/result.d.ts
ADDED
|
@@ -0,0 +1,852 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A class-based Result<T, E> system inspired by Rust's Result type.
|
|
3
|
+
*
|
|
4
|
+
* This module provides Result and AsyncResult classes for elegant error handling
|
|
5
|
+
* with method chaining and the `take()` pattern for early returns.
|
|
6
|
+
*
|
|
7
|
+
* @module @qlever-llc/result
|
|
8
|
+
*/
|
|
9
|
+
import type { BaseError } from "./error.js";
|
|
10
|
+
import { UnexpectedError } from "./error.js";
|
|
11
|
+
/**
|
|
12
|
+
* Represents a successful result containing a value.
|
|
13
|
+
*/
|
|
14
|
+
export interface OkValue<T> {
|
|
15
|
+
readonly success: true;
|
|
16
|
+
readonly value: T;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Represents a failed result containing an error.
|
|
20
|
+
*/
|
|
21
|
+
export interface ErrValue<E extends BaseError> {
|
|
22
|
+
readonly success: false;
|
|
23
|
+
readonly error: E;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Internal type representing the raw result data.
|
|
27
|
+
*/
|
|
28
|
+
type ResultValue<T, E extends BaseError> = OkValue<T> | ErrValue<E>;
|
|
29
|
+
/**
|
|
30
|
+
* Extracts the Ok type T from a Result<T, E>.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* type MyResult = Result<number, ValidationError>;
|
|
35
|
+
* type Value = Infer<MyResult>; // number
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export type Infer<R> = R extends Result<infer T, BaseError> ? T : never;
|
|
39
|
+
/**
|
|
40
|
+
* Extracts the Err type E from a Result<T, E>.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* type MyResult = Result<number, ValidationError>;
|
|
45
|
+
* type Error = InferErr<MyResult>; // ValidationError
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export type InferErr<R> = R extends Result<unknown, infer E> ? E : never;
|
|
49
|
+
/**
|
|
50
|
+
* A type that accepts either a Result or AsyncResult with the same T and E types.
|
|
51
|
+
*
|
|
52
|
+
* This allows functions to return either synchronous or asynchronous results
|
|
53
|
+
* interchangeably, making it easy to optimize or refactor without changing signatures.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* function getUser(id: string): MaybeAsync<User, NotFoundError> {
|
|
58
|
+
* if (cache.has(id)) {
|
|
59
|
+
* return Result.ok(cache.get(id)); // Synchronous return
|
|
60
|
+
* }
|
|
61
|
+
* return AsyncResult.try(async () => {
|
|
62
|
+
* return await fetchUser(id); // Asynchronous return
|
|
63
|
+
* });
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export type MaybeAsync<T, E extends BaseError> = Result<T, E> | AsyncResult<T, E> | Promise<Result<T, E>>;
|
|
68
|
+
/**
|
|
69
|
+
* A synchronous Result class that represents either success (Ok) or failure (Err).
|
|
70
|
+
*
|
|
71
|
+
* Provides method chaining for transformations and the `take()` pattern for
|
|
72
|
+
* unwrapping values with early returns.
|
|
73
|
+
*
|
|
74
|
+
* @template T - The type of the success value
|
|
75
|
+
* @template E - The type of the error (must extend BaseError)
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```typescript
|
|
79
|
+
* function divide(a: number, b: number): Result<number, ValidationError> {
|
|
80
|
+
* if (b === 0) {
|
|
81
|
+
* return Result.err(new ValidationError("Division by zero"));
|
|
82
|
+
* }
|
|
83
|
+
* return Result.ok(a / b);
|
|
84
|
+
* }
|
|
85
|
+
*
|
|
86
|
+
* const result = divide(10, 2)
|
|
87
|
+
* .map(x => x * 2)
|
|
88
|
+
* .map(x => x + 1);
|
|
89
|
+
*
|
|
90
|
+
* const value = result.take();
|
|
91
|
+
* if (isErr(value)) return value;
|
|
92
|
+
* console.log(value); // 11
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare class Result<T, E extends BaseError> {
|
|
96
|
+
private readonly _value;
|
|
97
|
+
private constructor();
|
|
98
|
+
/**
|
|
99
|
+
* Creates a successful Result containing a value.
|
|
100
|
+
*
|
|
101
|
+
* @template T - The type of the success value
|
|
102
|
+
* @template E - The type of the error (defaults to never)
|
|
103
|
+
* @param value - The success value to wrap
|
|
104
|
+
* @returns A Result instance containing the value
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* const result = Result.ok(42);
|
|
109
|
+
* const value = result.take();
|
|
110
|
+
* if (!isErr(value)) {
|
|
111
|
+
* console.log(value); // 42
|
|
112
|
+
* }
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
static ok<T, E extends BaseError = never>(value: T): Result<T, E>;
|
|
116
|
+
/**
|
|
117
|
+
* Creates a failed Result containing an error.
|
|
118
|
+
*
|
|
119
|
+
* @template E - The type of the error (must extend BaseError)
|
|
120
|
+
* @template T - The type of the success value (defaults to never)
|
|
121
|
+
* @param error - The error to wrap
|
|
122
|
+
* @returns A Result instance containing the error
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* const result = Result.err(new ValidationError("Invalid input"));
|
|
127
|
+
* const value = result.take();
|
|
128
|
+
* if (isErr(value)) {
|
|
129
|
+
* console.error(value.error.message); // "Invalid input"
|
|
130
|
+
* }
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
static err<E extends BaseError, T = never>(error: E): Result<T, E>;
|
|
134
|
+
/**
|
|
135
|
+
* Wraps a function that might throw into a Result.
|
|
136
|
+
*
|
|
137
|
+
* Catches any exceptions and wraps them in UnexpectedError.
|
|
138
|
+
*
|
|
139
|
+
* @template T - The type of the return value
|
|
140
|
+
* @param fn - Function that might throw
|
|
141
|
+
* @param context - Optional context to add to the error
|
|
142
|
+
* @returns Ok with the return value, or Err with UnexpectedError
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```typescript
|
|
146
|
+
* const obj = Result.try(() =>
|
|
147
|
+
* typeof data === "string" ? JSON.parse(data) : data
|
|
148
|
+
* );
|
|
149
|
+
*
|
|
150
|
+
* const value = obj.take();
|
|
151
|
+
* if (isErr(value)) {
|
|
152
|
+
* console.error("Parse failed:", value.error);
|
|
153
|
+
* return;
|
|
154
|
+
* }
|
|
155
|
+
* console.log(value); // parsed object
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
static try<T>(fn: () => T, context?: Record<string, unknown>): Result<T, UnexpectedError>;
|
|
159
|
+
/**
|
|
160
|
+
* Type guard to check if a value is an Ok Result.
|
|
161
|
+
*
|
|
162
|
+
* @template T - The type of the success value
|
|
163
|
+
* @template E - The type of the error
|
|
164
|
+
* @param result - The Result to check
|
|
165
|
+
* @returns True if the result is Ok, false otherwise
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* const result = Result.ok(42);
|
|
170
|
+
* if (Result.isOk(result)) {
|
|
171
|
+
* // TypeScript knows result is Ok<number> here
|
|
172
|
+
* }
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
static isOk<T, E extends BaseError>(result: Result<T, E>): result is Result<T, never>;
|
|
176
|
+
/**
|
|
177
|
+
* Type guard to check if a value is an Err Result.
|
|
178
|
+
*
|
|
179
|
+
* This function has multiple overloads:
|
|
180
|
+
* 1. Check if a Result is Err
|
|
181
|
+
* 2. Check if any value (including from take()) is Err
|
|
182
|
+
*
|
|
183
|
+
* @template T - The type of the success value
|
|
184
|
+
* @template E - The type of the error
|
|
185
|
+
* @param value - The value to check (Result or unknown)
|
|
186
|
+
* @returns True if the value is Err, false otherwise
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```typescript
|
|
190
|
+
* const result = Result.err(new ValidationError("Failed"));
|
|
191
|
+
* if (Result.isErr(result)) {
|
|
192
|
+
* console.log(result.error.message);
|
|
193
|
+
* }
|
|
194
|
+
*
|
|
195
|
+
* // Works with take() output
|
|
196
|
+
* const value = result.take();
|
|
197
|
+
* if (Result.isErr(value)) {
|
|
198
|
+
* return value; // Early return with error Result
|
|
199
|
+
* }
|
|
200
|
+
* // TypeScript knows value is T here
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
static isErr<T, E extends BaseError>(result: Result<T, E>): result is Result<never, E>;
|
|
204
|
+
static isErr<T, E extends BaseError>(value: T | Result<never, E>): value is Result<never, E>;
|
|
205
|
+
/**
|
|
206
|
+
* Combines multiple Results into a single Result containing an array.
|
|
207
|
+
*
|
|
208
|
+
* If all Results are Ok, returns Ok with an array of all values.
|
|
209
|
+
* If any Result is Err, returns the first Err encountered.
|
|
210
|
+
*
|
|
211
|
+
* @template T - The type of the Ok values
|
|
212
|
+
* @template E - The type of the errors
|
|
213
|
+
* @param results - Array of Results to combine
|
|
214
|
+
* @returns Ok with array of values, or the first Err
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```typescript
|
|
218
|
+
* const results = [Result.ok(1), Result.ok(2), Result.ok(3)];
|
|
219
|
+
* const combined = Result.all(results);
|
|
220
|
+
* // Ok([1, 2, 3])
|
|
221
|
+
*
|
|
222
|
+
* const withError = [Result.ok(1), Result.err(new ValidationError("Failed")), Result.ok(3)];
|
|
223
|
+
* const combined2 = Result.all(withError);
|
|
224
|
+
* // Err(ValidationError)
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
static all<T, E extends BaseError>(results: readonly Result<T, E>[]): Result<T[], E>;
|
|
228
|
+
/**
|
|
229
|
+
* Returns the first Ok result from an array of Results.
|
|
230
|
+
*
|
|
231
|
+
* If any Result is Ok, returns that Ok result.
|
|
232
|
+
* If all Results are Err, returns the last Err.
|
|
233
|
+
*
|
|
234
|
+
* @template T - The type of the Ok values
|
|
235
|
+
* @template E - The type of the errors
|
|
236
|
+
* @param results - Array of Results to check
|
|
237
|
+
* @returns The first Ok, or the last Err if all failed
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```typescript
|
|
241
|
+
* const results = [Result.err(new Error("e1")), Result.ok(2), Result.ok(3)];
|
|
242
|
+
* const first = Result.any(results);
|
|
243
|
+
* // Ok(2)
|
|
244
|
+
*
|
|
245
|
+
* const allErrors = [
|
|
246
|
+
* Result.err(new Error("e1")),
|
|
247
|
+
* Result.err(new Error("e2")),
|
|
248
|
+
* Result.err(new Error("e3"))
|
|
249
|
+
* ];
|
|
250
|
+
* const first2 = Result.any(allErrors);
|
|
251
|
+
* // Err(Error("e3")) - the last error
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
254
|
+
static any<T, E extends BaseError>(results: readonly Result<T, E>[]): Result<T, E>;
|
|
255
|
+
/**
|
|
256
|
+
* Type guard to check if this Result is Ok.
|
|
257
|
+
*
|
|
258
|
+
* @returns True if this result is Ok, false otherwise
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* ```typescript
|
|
262
|
+
* const result = Result.ok(42);
|
|
263
|
+
* if (result.isOk()) {
|
|
264
|
+
* // TypeScript knows result is Ok here
|
|
265
|
+
* }
|
|
266
|
+
* ```
|
|
267
|
+
*/
|
|
268
|
+
isOk(): this is Result<T, never>;
|
|
269
|
+
/**
|
|
270
|
+
* Type guard to check if this Result is Err.
|
|
271
|
+
*
|
|
272
|
+
* @returns True if this result is Err, false otherwise
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* ```typescript
|
|
276
|
+
* const result = Result.err(new ValidationError("Failed"));
|
|
277
|
+
* if (result.isErr()) {
|
|
278
|
+
* // TypeScript knows result is Err here
|
|
279
|
+
* }
|
|
280
|
+
* ```
|
|
281
|
+
*/
|
|
282
|
+
isErr(): this is Result<never, E>;
|
|
283
|
+
/**
|
|
284
|
+
* Transforms the Ok value using a mapper function, leaving Err untouched.
|
|
285
|
+
*
|
|
286
|
+
* @template U - The type of the transformed value
|
|
287
|
+
* @param fn - Function to transform the Ok value
|
|
288
|
+
* @returns A new Result with the transformed value, or the original Err
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* ```typescript
|
|
292
|
+
* const result = Result.ok(5)
|
|
293
|
+
* .map(x => x * 2)
|
|
294
|
+
* .map(x => x.toString());
|
|
295
|
+
*
|
|
296
|
+
* const value = result.take();
|
|
297
|
+
* if (!isErr(value)) {
|
|
298
|
+
* console.log(value); // "10"
|
|
299
|
+
* }
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
map<U>(fn: (value: T) => U): Result<U, E>;
|
|
303
|
+
/**
|
|
304
|
+
* Transforms the Err value using a mapper function, leaving Ok untouched.
|
|
305
|
+
*
|
|
306
|
+
* @template F - The type of the transformed error
|
|
307
|
+
* @param fn - Function to transform the Err value
|
|
308
|
+
* @returns A new Result with the transformed error, or the original Ok
|
|
309
|
+
*
|
|
310
|
+
* @example
|
|
311
|
+
* ```typescript
|
|
312
|
+
* const result = Result.err(new ValidationError("Failed"))
|
|
313
|
+
* .mapErr(e => new NetworkError({ cause: e }));
|
|
314
|
+
* ```
|
|
315
|
+
*/
|
|
316
|
+
mapErr<F extends BaseError>(fn: (error: E) => F): Result<T, F>;
|
|
317
|
+
/**
|
|
318
|
+
* Chains operations that return Results (also known as flatMap).
|
|
319
|
+
*
|
|
320
|
+
* If this Result is Ok, calls the function with the Ok value and returns its Result.
|
|
321
|
+
* If this Result is Err, returns the Err without calling the function.
|
|
322
|
+
*
|
|
323
|
+
* @template U - The type of the new Ok value
|
|
324
|
+
* @template F - The type of the new error
|
|
325
|
+
* @param fn - Function that takes the Ok value and returns a new Result
|
|
326
|
+
* @returns The Result from calling fn, or the original Err
|
|
327
|
+
*
|
|
328
|
+
* @example
|
|
329
|
+
* ```typescript
|
|
330
|
+
* function parseNumber(s: string): Result<number, ValidationError> {
|
|
331
|
+
* const n = Number(s);
|
|
332
|
+
* if (isNaN(n)) {
|
|
333
|
+
* return Result.err(new ValidationError("Not a number"));
|
|
334
|
+
* }
|
|
335
|
+
* return Result.ok(n);
|
|
336
|
+
* }
|
|
337
|
+
*
|
|
338
|
+
* const result = Result.ok("42")
|
|
339
|
+
* .andThen(parseNumber)
|
|
340
|
+
* .map(x => x * 2);
|
|
341
|
+
* ```
|
|
342
|
+
*/
|
|
343
|
+
andThen<U, F extends BaseError>(fn: (value: T) => Result<U, F>): Result<U, E | F>;
|
|
344
|
+
/**
|
|
345
|
+
* Extracts the value from Ok or returns the Err for early returns.
|
|
346
|
+
*
|
|
347
|
+
* This is the equivalent of Rust's `?` operator. Use it with `isErr()` for
|
|
348
|
+
* early returns in functions that return Results.
|
|
349
|
+
*
|
|
350
|
+
* Returns either:
|
|
351
|
+
* - The unwrapped value T if this result is Ok
|
|
352
|
+
* - An Err Result<never, E> if this result is Err (can be directly returned)
|
|
353
|
+
*
|
|
354
|
+
* @returns The unwrapped value or Err Result
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* ```typescript
|
|
358
|
+
* function processData(input: string): Result<number, ValidationError> {
|
|
359
|
+
* const parsed = parseInput(input).take();
|
|
360
|
+
* if (isErr(parsed)) return parsed;
|
|
361
|
+
*
|
|
362
|
+
* const validated = validate(parsed).take();
|
|
363
|
+
* if (isErr(validated)) return validated;
|
|
364
|
+
*
|
|
365
|
+
* return Result.ok(validated * 2);
|
|
366
|
+
* }
|
|
367
|
+
* ```
|
|
368
|
+
*/
|
|
369
|
+
take(): [T] extends [never] ? Result<never, E> : T | Result<never, E>;
|
|
370
|
+
/**
|
|
371
|
+
* Adds context to an Err result for early returns.
|
|
372
|
+
* Chainable with take() for adding context when propagating errors.
|
|
373
|
+
*
|
|
374
|
+
* @param message - Context message describing the operation that failed
|
|
375
|
+
* @param extra - Optional additional context data
|
|
376
|
+
* @returns This Result with context added to the error
|
|
377
|
+
*
|
|
378
|
+
* @example
|
|
379
|
+
* ```typescript
|
|
380
|
+
* const user = await getUser(id).take();
|
|
381
|
+
* if (isErr(user)) return user.context("failed to fetch user");
|
|
382
|
+
*
|
|
383
|
+
* // With extra data:
|
|
384
|
+
* if (isErr(user)) return user.context("failed to fetch user", { userId: id });
|
|
385
|
+
* ```
|
|
386
|
+
*/
|
|
387
|
+
context(message: string, extra?: Record<string, unknown>): Result<T, E>;
|
|
388
|
+
/**
|
|
389
|
+
* Pattern matching for Results - handle both Ok and Err cases.
|
|
390
|
+
*
|
|
391
|
+
* @template U - The type of the return value
|
|
392
|
+
* @param pattern - Object with ok and err handler functions
|
|
393
|
+
* @returns The result of calling either the ok or err handler
|
|
394
|
+
*
|
|
395
|
+
* @example
|
|
396
|
+
* ```typescript
|
|
397
|
+
* const message = result.match({
|
|
398
|
+
* ok: (value) => `Success: ${value}`,
|
|
399
|
+
* err: (error) => `Error: ${error.message}`
|
|
400
|
+
* });
|
|
401
|
+
* ```
|
|
402
|
+
*/
|
|
403
|
+
match<U>(pattern: {
|
|
404
|
+
ok: (value: T) => U;
|
|
405
|
+
err: (error: E) => U;
|
|
406
|
+
}): U;
|
|
407
|
+
/**
|
|
408
|
+
* Returns the Ok value or a default value if Err.
|
|
409
|
+
*
|
|
410
|
+
* @template U - The type of the default value
|
|
411
|
+
* @param defaultValue - The value to return if this result is Err
|
|
412
|
+
* @returns The Ok value or the default value
|
|
413
|
+
*
|
|
414
|
+
* @example
|
|
415
|
+
* ```typescript
|
|
416
|
+
* const value = result.unwrapOr(0);
|
|
417
|
+
* console.log(value); // 42 or 0
|
|
418
|
+
* ```
|
|
419
|
+
*/
|
|
420
|
+
unwrapOr<U>(defaultValue: U): T | U;
|
|
421
|
+
/**
|
|
422
|
+
* Returns the Ok value or computes a default from the error.
|
|
423
|
+
*
|
|
424
|
+
* @template U - The type of the default value
|
|
425
|
+
* @param fn - Function to compute the default value from the error
|
|
426
|
+
* @returns The Ok value or the computed default value
|
|
427
|
+
*
|
|
428
|
+
* @example
|
|
429
|
+
* ```typescript
|
|
430
|
+
* const value = result.unwrapOrElse(error => {
|
|
431
|
+
* console.error(error);
|
|
432
|
+
* return 0;
|
|
433
|
+
* });
|
|
434
|
+
* ```
|
|
435
|
+
*/
|
|
436
|
+
unwrapOrElse<U>(fn: (error: E) => U): T | U;
|
|
437
|
+
/**
|
|
438
|
+
* Returns this result if Ok, otherwise returns the fallback result.
|
|
439
|
+
*
|
|
440
|
+
* @template U - The type of the fallback Ok value
|
|
441
|
+
* @param other - The fallback Result to use if this is Err
|
|
442
|
+
* @returns This result if Ok, otherwise the fallback
|
|
443
|
+
*
|
|
444
|
+
* @example
|
|
445
|
+
* ```typescript
|
|
446
|
+
* const result = fetchFromCache()
|
|
447
|
+
* .or(fetchFromDatabase())
|
|
448
|
+
* .or(fetchFromAPI());
|
|
449
|
+
* ```
|
|
450
|
+
*/
|
|
451
|
+
or<U>(other: Result<U, E>): Result<T | U, E>;
|
|
452
|
+
/**
|
|
453
|
+
* Returns this result if Ok, otherwise computes a fallback from the error.
|
|
454
|
+
*
|
|
455
|
+
* @template R - The Result type returned by the fallback function
|
|
456
|
+
* @param fn - Function to compute a fallback Result from the error
|
|
457
|
+
* @returns This result if Ok, otherwise the computed fallback
|
|
458
|
+
*
|
|
459
|
+
* @example
|
|
460
|
+
* ```typescript
|
|
461
|
+
* const result = fetchData().orElse(error => {
|
|
462
|
+
* console.warn("Primary failed, trying backup");
|
|
463
|
+
* return fetchBackup();
|
|
464
|
+
* });
|
|
465
|
+
* ```
|
|
466
|
+
*/
|
|
467
|
+
orElse<U, F extends BaseError>(fn: (error: E) => Result<U, F>): Result<T | U, F>;
|
|
468
|
+
/**
|
|
469
|
+
* Performs a side effect on the Ok value without changing the Result.
|
|
470
|
+
*
|
|
471
|
+
* @param fn - Function to call with the Ok value (if Ok)
|
|
472
|
+
* @returns This Result, unchanged
|
|
473
|
+
*
|
|
474
|
+
* @example
|
|
475
|
+
* ```typescript
|
|
476
|
+
* const result = fetchUser("123")
|
|
477
|
+
* .inspect(user => console.log("Fetched:", user))
|
|
478
|
+
* .map(user => user.name);
|
|
479
|
+
* ```
|
|
480
|
+
*/
|
|
481
|
+
inspect(fn: (value: T) => void): Result<T, E>;
|
|
482
|
+
/**
|
|
483
|
+
* Performs a side effect on the Err value without changing the Result.
|
|
484
|
+
*
|
|
485
|
+
* @param fn - Function to call with the error value (if Err)
|
|
486
|
+
* @returns This Result, unchanged
|
|
487
|
+
*
|
|
488
|
+
* @example
|
|
489
|
+
* ```typescript
|
|
490
|
+
* const result = fetchUser("123")
|
|
491
|
+
* .inspectErr(error => console.error("Failed:", error))
|
|
492
|
+
* .map(user => user.name);
|
|
493
|
+
* ```
|
|
494
|
+
*/
|
|
495
|
+
inspectErr(fn: (error: E) => void): Result<T, E>;
|
|
496
|
+
/**
|
|
497
|
+
* Gets the error from an Err Result.
|
|
498
|
+
*
|
|
499
|
+
* Only call this after checking `isErr()`. If called on Ok, throws an error.
|
|
500
|
+
*
|
|
501
|
+
* @returns The error value
|
|
502
|
+
*
|
|
503
|
+
* @example
|
|
504
|
+
* ```typescript
|
|
505
|
+
* const result = err(new ValidationError("Failed"));
|
|
506
|
+
* if (result.isErr()) {
|
|
507
|
+
* console.log(result.error.message); // "Failed"
|
|
508
|
+
* }
|
|
509
|
+
* ```
|
|
510
|
+
*/
|
|
511
|
+
get error(): E;
|
|
512
|
+
/**
|
|
513
|
+
* Internal method to get the raw value (for testing/debugging).
|
|
514
|
+
* Not recommended for general use - prefer take() instead.
|
|
515
|
+
*/
|
|
516
|
+
_unsafeValue(): ResultValue<T, E>;
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* An asynchronous Result class that represents a Promise of Result<T, E>.
|
|
520
|
+
*
|
|
521
|
+
* Implements PromiseLike to be awaitable, and provides async versions of
|
|
522
|
+
* all Result methods that return AsyncResult for seamless chaining.
|
|
523
|
+
*
|
|
524
|
+
* @template T - The type of the success value
|
|
525
|
+
* @template E - The type of the error (must extend BaseError)
|
|
526
|
+
*
|
|
527
|
+
* @example
|
|
528
|
+
* ```typescript
|
|
529
|
+
* async function fetchUser(id: string): AsyncResult<User, NetworkError> {
|
|
530
|
+
* return AsyncResult.wrap(async () => {
|
|
531
|
+
* const response = await fetch(`/api/users/${id}`);
|
|
532
|
+
* return await response.json();
|
|
533
|
+
* });
|
|
534
|
+
* }
|
|
535
|
+
*
|
|
536
|
+
* const result = fetchUser("123")
|
|
537
|
+
* .map(user => user.name)
|
|
538
|
+
* .map(name => name.toUpperCase());
|
|
539
|
+
*
|
|
540
|
+
* const value = await result.take();
|
|
541
|
+
* if (isErr(value)) return value;
|
|
542
|
+
* console.log(value); // "ALICE"
|
|
543
|
+
* ```
|
|
544
|
+
*/
|
|
545
|
+
export declare class AsyncResult<T, E extends BaseError> implements PromiseLike<Result<T, E>> {
|
|
546
|
+
private readonly promise;
|
|
547
|
+
constructor(promise: Promise<Result<T, E>>);
|
|
548
|
+
/**
|
|
549
|
+
* Creates an AsyncResult from a Promise of Result.
|
|
550
|
+
*
|
|
551
|
+
* @template T - The type of the success value
|
|
552
|
+
* @template E - The type of the error
|
|
553
|
+
* @param promise - The promise that resolves to a Result
|
|
554
|
+
* @returns An AsyncResult wrapping the promise
|
|
555
|
+
*
|
|
556
|
+
* @example
|
|
557
|
+
* ```typescript
|
|
558
|
+
* const asyncResult = AsyncResult.from(fetchData());
|
|
559
|
+
* ```
|
|
560
|
+
*/
|
|
561
|
+
static from<T, E extends BaseError>(promise: Promise<Result<T, E>>): AsyncResult<T, E>;
|
|
562
|
+
/**
|
|
563
|
+
* Creates a successful AsyncResult with the given value.
|
|
564
|
+
*
|
|
565
|
+
* @template T - The type of the Ok value
|
|
566
|
+
* @template E - The type of the error (defaults to never)
|
|
567
|
+
* @param value - The value to wrap in an Ok AsyncResult
|
|
568
|
+
* @returns AsyncResult in the Ok state
|
|
569
|
+
*
|
|
570
|
+
* @example
|
|
571
|
+
* ```typescript
|
|
572
|
+
* const result = AsyncResult.ok(42);
|
|
573
|
+
* const value = await result.take();
|
|
574
|
+
* console.log(value); // 42
|
|
575
|
+
* ```
|
|
576
|
+
*/
|
|
577
|
+
static ok<T, E extends BaseError = never>(value: T): AsyncResult<T, E>;
|
|
578
|
+
/**
|
|
579
|
+
* Creates a failed AsyncResult with the given error.
|
|
580
|
+
*
|
|
581
|
+
* @template E - The type of the error
|
|
582
|
+
* @template T - The type of the Ok value (defaults to never)
|
|
583
|
+
* @param error - The error to wrap in an Err AsyncResult
|
|
584
|
+
* @returns AsyncResult in the Err state
|
|
585
|
+
*
|
|
586
|
+
* @example
|
|
587
|
+
* ```typescript
|
|
588
|
+
* const result = AsyncResult.err(new ValidationError("Invalid input"));
|
|
589
|
+
* const value = await result.take();
|
|
590
|
+
* if (Result.isErr(value)) {
|
|
591
|
+
* console.error(value.error.message); // "Invalid input"
|
|
592
|
+
* }
|
|
593
|
+
* ```
|
|
594
|
+
*/
|
|
595
|
+
static err<E extends BaseError, T = never>(error: E): AsyncResult<T, E>;
|
|
596
|
+
/**
|
|
597
|
+
* Creates an AsyncResult from a Result, AsyncResult, or Promise<Result>.
|
|
598
|
+
*
|
|
599
|
+
* This is the key method for working with MaybeAsync types - it normalizes
|
|
600
|
+
* both synchronous Results and asynchronous AsyncResults into AsyncResults.
|
|
601
|
+
*
|
|
602
|
+
* @template T - The type of the success value
|
|
603
|
+
* @template E - The type of the error
|
|
604
|
+
* @param value - A Result, AsyncResult, or Promise<Result>
|
|
605
|
+
* @returns An AsyncResult
|
|
606
|
+
*
|
|
607
|
+
* @example
|
|
608
|
+
* ```typescript
|
|
609
|
+
* const asyncResult = AsyncResult.lift(Result.ok(42));
|
|
610
|
+
* const asyncResult2 = AsyncResult.lift(Promise.resolve(Result.ok(42)));
|
|
611
|
+
* const asyncResult3 = AsyncResult.lift(existingAsyncResult); // Pass-through
|
|
612
|
+
* ```
|
|
613
|
+
*/
|
|
614
|
+
static lift<T, E extends BaseError>(value: Result<T, E> | AsyncResult<T, E> | Promise<Result<T, E>>): AsyncResult<T, E>;
|
|
615
|
+
/**
|
|
616
|
+
* Wraps an async function that might throw into an AsyncResult.
|
|
617
|
+
*
|
|
618
|
+
* Catches any exceptions and wraps them in UnexpectedError.
|
|
619
|
+
*
|
|
620
|
+
* @template T - The type of the return value
|
|
621
|
+
* @param fn - Async function that might throw
|
|
622
|
+
* @param context - Optional context to add to the error
|
|
623
|
+
* @returns AsyncResult with the return value or UnexpectedError
|
|
624
|
+
*
|
|
625
|
+
* @example
|
|
626
|
+
* ```typescript
|
|
627
|
+
* const user = AsyncResult.try(async () => {
|
|
628
|
+
* const response = await fetch("/api/user");
|
|
629
|
+
* return await response.json();
|
|
630
|
+
* });
|
|
631
|
+
*
|
|
632
|
+
* const value = await user.take();
|
|
633
|
+
* if (isErr(value)) {
|
|
634
|
+
* console.error("Fetch failed:", value.error);
|
|
635
|
+
* return;
|
|
636
|
+
* }
|
|
637
|
+
* console.log(value); // user object
|
|
638
|
+
* ```
|
|
639
|
+
*/
|
|
640
|
+
static try<T>(fn: () => Promise<T>, context?: Record<string, unknown>): AsyncResult<T, UnexpectedError>;
|
|
641
|
+
/**
|
|
642
|
+
* Combines multiple AsyncResults into a single AsyncResult containing an array.
|
|
643
|
+
*
|
|
644
|
+
* If all Results are Ok, returns Ok with an array of all values.
|
|
645
|
+
* If any Result is Err, returns the first Err encountered.
|
|
646
|
+
*
|
|
647
|
+
* @template T - The type of the Ok values
|
|
648
|
+
* @template E - The type of the errors
|
|
649
|
+
* @param results - Array of AsyncResults or Promises to combine
|
|
650
|
+
* @returns AsyncResult with array of values, or the first Err
|
|
651
|
+
*
|
|
652
|
+
* @example
|
|
653
|
+
* ```typescript
|
|
654
|
+
* const users = await AsyncResult.all([
|
|
655
|
+
* fetchUser("1"),
|
|
656
|
+
* fetchUser("2"),
|
|
657
|
+
* fetchUser("3")
|
|
658
|
+
* ]).take();
|
|
659
|
+
*
|
|
660
|
+
* if (Result.isErr(users)) {
|
|
661
|
+
* console.error("Failed to fetch users");
|
|
662
|
+
* } else {
|
|
663
|
+
* console.log(users); // [user1, user2, user3]
|
|
664
|
+
* }
|
|
665
|
+
* ```
|
|
666
|
+
*/
|
|
667
|
+
static all<T, E extends BaseError>(results: readonly (AsyncResult<T, E> | Promise<Result<T, E>>)[]): AsyncResult<T[], E>;
|
|
668
|
+
/**
|
|
669
|
+
* Returns the first Ok result from an array of AsyncResults.
|
|
670
|
+
*
|
|
671
|
+
* If any Result is Ok, returns that Ok result.
|
|
672
|
+
* If all Results are Err, returns the last Err.
|
|
673
|
+
*
|
|
674
|
+
* @template T - The type of the Ok values
|
|
675
|
+
* @template E - The type of the errors
|
|
676
|
+
* @param results - Array of AsyncResults or Promises to check
|
|
677
|
+
* @returns AsyncResult with the first Ok, or the last Err
|
|
678
|
+
*
|
|
679
|
+
* @example
|
|
680
|
+
* ```typescript
|
|
681
|
+
* const data = await AsyncResult.any([
|
|
682
|
+
* fetchFromPrimary(),
|
|
683
|
+
* fetchFromSecondary(),
|
|
684
|
+
* fetchFromBackup()
|
|
685
|
+
* ]).take();
|
|
686
|
+
*
|
|
687
|
+
* if (Result.isErr(data)) {
|
|
688
|
+
* console.error("All sources failed");
|
|
689
|
+
* } else {
|
|
690
|
+
* console.log(data); // First successful result
|
|
691
|
+
* }
|
|
692
|
+
* ```
|
|
693
|
+
*/
|
|
694
|
+
static any<T, E extends BaseError>(results: readonly (AsyncResult<T, E> | Promise<Result<T, E>>)[]): AsyncResult<T, E>;
|
|
695
|
+
/**
|
|
696
|
+
* Implements PromiseLike to make AsyncResult awaitable.
|
|
697
|
+
*
|
|
698
|
+
* @template TResult1 - The type when fulfilled
|
|
699
|
+
* @template TResult2 - The type when rejected
|
|
700
|
+
* @param onfulfilled - Callback for when the promise is fulfilled
|
|
701
|
+
* @param onrejected - Callback for when the promise is rejected
|
|
702
|
+
* @returns A Promise of the result
|
|
703
|
+
*/
|
|
704
|
+
then<TResult1 = Result<T, E>, TResult2 = never>(onfulfilled?: ((value: Result<T, E>) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
|
|
705
|
+
/**
|
|
706
|
+
* Transforms the Ok value using a mapper function, leaving Err untouched.
|
|
707
|
+
*
|
|
708
|
+
* @template U - The type of the transformed value
|
|
709
|
+
* @param fn - Function to transform the Ok value
|
|
710
|
+
* @returns A new AsyncResult with the transformed value
|
|
711
|
+
*
|
|
712
|
+
* @example
|
|
713
|
+
* ```typescript
|
|
714
|
+
* const result = fetchUser("123")
|
|
715
|
+
* .map(user => user.name)
|
|
716
|
+
* .map(name => name.toUpperCase());
|
|
717
|
+
* ```
|
|
718
|
+
*/
|
|
719
|
+
map<U>(fn: (value: T) => U): AsyncResult<U, E>;
|
|
720
|
+
/**
|
|
721
|
+
* Transforms the Err value using a mapper function, leaving Ok untouched.
|
|
722
|
+
*
|
|
723
|
+
* @template F - The type of the transformed error
|
|
724
|
+
* @param fn - Function to transform the Err value
|
|
725
|
+
* @returns A new AsyncResult with the transformed error
|
|
726
|
+
*
|
|
727
|
+
* @example
|
|
728
|
+
* ```typescript
|
|
729
|
+
* const result = fetchUser("123")
|
|
730
|
+
* .mapErr(e => new NetworkError({ cause: e }));
|
|
731
|
+
* ```
|
|
732
|
+
*/
|
|
733
|
+
mapErr<F extends BaseError>(fn: (error: E) => F): AsyncResult<T, F>;
|
|
734
|
+
/**
|
|
735
|
+
* Chains operations that return Results.
|
|
736
|
+
*
|
|
737
|
+
* @template R - The Result type returned by the function
|
|
738
|
+
* @param fn - Function that takes the Ok value and returns a Result, AsyncResult, or Promise
|
|
739
|
+
* @returns A new AsyncResult from the chained operation
|
|
740
|
+
*
|
|
741
|
+
* @example
|
|
742
|
+
* ```typescript
|
|
743
|
+
* const result = fetchUser("123")
|
|
744
|
+
* .andThen(user => fetchPermissions(user.id));
|
|
745
|
+
* ```
|
|
746
|
+
*/
|
|
747
|
+
andThen<U, F extends BaseError>(fn: (value: T) => Result<U, F> | AsyncResult<U, F> | Promise<Result<U, F>>): AsyncResult<U, E | F>;
|
|
748
|
+
/**
|
|
749
|
+
* Extracts the value from Ok or returns the Err for early returns.
|
|
750
|
+
*
|
|
751
|
+
* This is the async version of Result.take(). It returns a Promise that
|
|
752
|
+
* resolves to either the unwrapped value T or an Err Result.
|
|
753
|
+
*
|
|
754
|
+
* @returns Promise of the unwrapped value or Err Result
|
|
755
|
+
*
|
|
756
|
+
* @example
|
|
757
|
+
* ```typescript
|
|
758
|
+
* async function processUser(id: string): Promise<Result<string, AppError>> {
|
|
759
|
+
* const user = await fetchUser(id).take();
|
|
760
|
+
* if (isErr(user)) return user;
|
|
761
|
+
*
|
|
762
|
+
* const perms = await fetchPermissions(user.id).take();
|
|
763
|
+
* if (isErr(perms)) return perms;
|
|
764
|
+
*
|
|
765
|
+
* return Result.ok(perms.join(", "));
|
|
766
|
+
* }
|
|
767
|
+
* ```
|
|
768
|
+
*/
|
|
769
|
+
take(): Promise<T | Result<never, E>>;
|
|
770
|
+
/**
|
|
771
|
+
* Adds context to an Err result for early returns.
|
|
772
|
+
* Async version - can be chained before take().
|
|
773
|
+
*
|
|
774
|
+
* @param message - Context message describing the operation that failed
|
|
775
|
+
* @param extra - Optional additional context data
|
|
776
|
+
* @returns AsyncResult with context added to any error
|
|
777
|
+
*
|
|
778
|
+
* @example
|
|
779
|
+
* ```typescript
|
|
780
|
+
* const user = await fetchUser(id).context("failed to fetch user").take();
|
|
781
|
+
* if (isErr(user)) return user;
|
|
782
|
+
* ```
|
|
783
|
+
*/
|
|
784
|
+
context(message: string, extra?: Record<string, unknown>): AsyncResult<T, E>;
|
|
785
|
+
/**
|
|
786
|
+
* Pattern matching for async Results.
|
|
787
|
+
*
|
|
788
|
+
* @template U - The type of the return value
|
|
789
|
+
* @param pattern - Object with ok and err handler functions
|
|
790
|
+
* @returns Promise of the result from calling either handler
|
|
791
|
+
*
|
|
792
|
+
* @example
|
|
793
|
+
* ```typescript
|
|
794
|
+
* const message = await fetchUser("123").match({
|
|
795
|
+
* ok: (user) => `Welcome, ${user.name}`,
|
|
796
|
+
* err: (error) => `Error: ${error.message}`
|
|
797
|
+
* });
|
|
798
|
+
* ```
|
|
799
|
+
*/
|
|
800
|
+
match<U>(pattern: {
|
|
801
|
+
ok: (value: T) => U;
|
|
802
|
+
err: (error: E) => U;
|
|
803
|
+
}): Promise<U>;
|
|
804
|
+
/**
|
|
805
|
+
* Returns the Ok value or a default value if Err.
|
|
806
|
+
*
|
|
807
|
+
* @template U - The type of the default value
|
|
808
|
+
* @param defaultValue - The value to return if the result is Err
|
|
809
|
+
* @returns Promise of the Ok value or the default value
|
|
810
|
+
*/
|
|
811
|
+
unwrapOr<U>(defaultValue: U): Promise<T | U>;
|
|
812
|
+
/**
|
|
813
|
+
* Returns the Ok value or computes a default from the error.
|
|
814
|
+
*
|
|
815
|
+
* @template U - The type of the default value
|
|
816
|
+
* @param fn - Function to compute the default value from the error
|
|
817
|
+
* @returns Promise of the Ok value or the computed default value
|
|
818
|
+
*/
|
|
819
|
+
unwrapOrElse<U>(fn: (error: E) => U): Promise<T | U>;
|
|
820
|
+
/**
|
|
821
|
+
* Returns this result if Ok, otherwise returns the fallback.
|
|
822
|
+
*
|
|
823
|
+
* @template U - The type of the fallback Ok value
|
|
824
|
+
* @param other - The fallback Result or AsyncResult
|
|
825
|
+
* @returns AsyncResult of this or the fallback
|
|
826
|
+
*/
|
|
827
|
+
or<U>(other: Result<U, E> | AsyncResult<U, E> | Promise<Result<U, E>>): AsyncResult<T | U, E>;
|
|
828
|
+
/**
|
|
829
|
+
* Returns this result if Ok, otherwise computes a fallback from the error.
|
|
830
|
+
*
|
|
831
|
+
* @template R - The Result or AsyncResult type returned by the fallback function
|
|
832
|
+
* @param fn - Function to compute a fallback Result from the error
|
|
833
|
+
* @returns AsyncResult of this or the computed fallback
|
|
834
|
+
*/
|
|
835
|
+
orElse<U, F extends BaseError>(fn: (error: E) => Result<U, F> | AsyncResult<U, F> | Promise<Result<U, F>>): AsyncResult<T | U, F>;
|
|
836
|
+
/**
|
|
837
|
+
* Performs a side effect on the Ok value without changing the result.
|
|
838
|
+
*
|
|
839
|
+
* @param fn - Function to call with the Ok value (if Ok)
|
|
840
|
+
* @returns This AsyncResult, unchanged
|
|
841
|
+
*/
|
|
842
|
+
inspect(fn: (value: T) => void | Promise<void>): AsyncResult<T, E>;
|
|
843
|
+
/**
|
|
844
|
+
* Performs a side effect on the Err value without changing the result.
|
|
845
|
+
*
|
|
846
|
+
* @param fn - Function to call with the error value (if Err)
|
|
847
|
+
* @returns This AsyncResult, unchanged
|
|
848
|
+
*/
|
|
849
|
+
inspectErr(fn: (error: E) => void | Promise<void>): AsyncResult<T, E>;
|
|
850
|
+
}
|
|
851
|
+
export {};
|
|
852
|
+
//# sourceMappingURL=result.d.ts.map
|