retuple 1.0.0-next.2 → 1.0.0-next.21

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/dist/index.d.cts CHANGED
@@ -1,75 +1,144 @@
1
- export type Ok<T> = OkTuple<T> & Retuple<T, never>;
2
- export type Err<E> = ErrTuple<E> & Retuple<never, E>;
1
+ import { type ResultLike } from "retuple-symbols";
2
+ export type Ok = typeof Ok;
3
+ export type Err = typeof Err;
3
4
  export type Result<T, E> = (OkTuple<T> | ErrTuple<E>) & Retuple<T, E>;
4
- export { type ResultAsync };
5
- export declare class RetupleUnwrapFailed<E = unknown> extends Error {
5
+ export { type ResultAsync, type ResultRetry };
6
+ export interface ResultRetryController<E> {
7
+ error: E;
8
+ attempt: number;
9
+ abort: () => void;
10
+ }
11
+ /**
12
+ * ## Retuple Unwrap Failed
13
+ *
14
+ * An error which occurs when calling `$unwrap` on `Err`.
15
+ */
16
+ export declare class RetupleUnwrapFailed<const E = unknown> extends Error {
6
17
  value: E;
7
18
  constructor(value: E, msg?: string);
8
19
  }
9
- export declare class RetupleUnwrapErrFailed<T = unknown> extends Error {
20
+ /**
21
+ * ## Retuple Unwrap Err Failed
22
+ *
23
+ * An error which occurs when calling `$unwrapErr` on `Ok`.
24
+ */
25
+ export declare class RetupleUnwrapErrFailed<const T = unknown> extends Error {
10
26
  value: T;
11
27
  constructor(value: T, msg?: string);
12
28
  }
13
- export declare class RetupleExpectFailed<E = unknown> extends Error {
29
+ /**
30
+ * ## Retuple Expect Failed
31
+ *
32
+ * An error which occurs when calling `$expect` on `Err`, when the value
33
+ * contained in the `Err` is not an instance of `Error`.
34
+ */
35
+ export declare class RetupleExpectFailed<const E = unknown> extends Error {
14
36
  value: E;
15
37
  constructor(value: E);
16
38
  }
17
- export declare class RetupleThrownValueError extends Error {
39
+ /**
40
+ * ## Retuple Thrown Value Error
41
+ *
42
+ * An error constructed when a safe function call throws or rejects, when the
43
+ * thrown error or rejected value is not an instance of `Error`, and when no
44
+ * map error function is provided.
45
+ */
46
+ export declare class RetupleCaughtValueError extends Error {
18
47
  value: unknown;
19
48
  constructor(value: unknown);
20
49
  }
21
50
  /**
22
- * ## Result
51
+ * ## Retuple Invalid Union Error
23
52
  *
24
- * @TODO
53
+ * This error is thrown when attempting to construct a `Result` from a
54
+ * discriminated union, when the 'success' property is not boolean. In this
55
+ * case, it is impossible to determine whether the result should be `Ok` or
56
+ * `Err`.
25
57
  */
26
- export declare const Result: {
27
- Ok: typeof Ok;
28
- Err: typeof Err;
29
- from: typeof from;
30
- safe: typeof safe;
31
- safeAsync: typeof safeAsync;
32
- safePromise: typeof safePromise;
33
- };
34
- export default Result;
58
+ export declare class RetupleInvalidUnionError extends Error {
59
+ value: unknown;
60
+ constructor(value: unknown);
61
+ }
35
62
  /**
36
- * ## Ok
63
+ * ## Result
37
64
  *
38
65
  * @TODO
39
66
  */
40
- export declare function Ok(): Ok<void>;
41
- export declare function Ok<T>(val: T): Ok<T>;
67
+ export declare function Result<T, E>(resultLike: ResultLike<T, E>): Result<T, E>;
68
+ export declare namespace Result {
69
+ var Ok: typeof import(".").Ok;
70
+ var Err: typeof import(".").Err;
71
+ var $from: <T, E>(result: ResultLike<T, E>) => Result<T, E>;
72
+ var $resolve: <T, E>(result: ResultLikeAwaitable<T, E>) => ResultAsync<T, E>;
73
+ var $nonNullable: {
74
+ <const T>(value: T): Result<NonNullable<T>, true>;
75
+ <const T, E>(value: T, error: () => E): Result<NonNullable<T>, E>;
76
+ };
77
+ var $truthy: {
78
+ <const T>(value: T): Result<Truthy<T>, true>;
79
+ <const T, E>(value: T, error: () => E): Result<Truthy<T>, E>;
80
+ };
81
+ var $fromUnion: <U extends ObjectUnionOk<any> | ObjectUnionErr<any>>(union: U) => Result<U extends ObjectUnionOk<infer T> ? T : never, U extends ObjectUnionErr<infer E> ? E : never>;
82
+ var $safe: {
83
+ <T>(f: () => Awaited<T>): Result<T, Error>;
84
+ <T, E>(f: () => Awaited<T>, mapError: (err: unknown) => E): Result<T, E>;
85
+ };
86
+ var $safeAsync: {
87
+ <T>(f: () => T | PromiseLike<T>): ResultAsync<T, Error>;
88
+ <T, E>(f: () => T | PromiseLike<T>, mapError: (err: unknown) => E): ResultAsync<T, E>;
89
+ };
90
+ var $safePromise: {
91
+ <T>(promise: PromiseLike<T>): ResultAsync<T, Error>;
92
+ <T, E>(promise: PromiseLike<T>, mapError: (err: unknown) => E): ResultAsync<T, E>;
93
+ };
94
+ var $retry: <T, E>(f: () => ResultLike<T, E> | PromiseLike<ResultLike<T, E>>) => ResultRetry<T, E>;
95
+ var $safeRetry: {
96
+ <T>(f: () => T | PromiseLike<T>): ResultRetry<T, Error>;
97
+ <T, E>(f: () => T | PromiseLike<T>, mapError: (err: unknown) => E): ResultRetry<T, E>;
98
+ };
99
+ }
42
100
  /**
43
- * ## Err
101
+ * Create a new {@link Result} with the `Ok` variant. When called without
102
+ * arguments the `T` type is `void`.
44
103
  *
45
- * @TODO
46
- */
47
- export declare function Err(): Err<void>;
48
- export declare function Err<E>(err: E): Err<E>;
49
- /**
50
- * Construct a {@link Result} from a value. If the value is truthy, the result
51
- * is `Ok`.
52
- */
53
- export declare function from<T>(value: T): Result<Truthy<T>, true>;
54
- export declare function from<T, E>(value: T, error: () => E): Result<Truthy<T>, E>;
55
- /**
56
- * Construct a {@link Result} from a synchronous function call. If the function
57
- * returns without throwing, the result is `Ok`.
58
- */
59
- export declare function safe<T>(f: () => Awaited<T>): Result<T, Error>;
60
- export declare function safe<T, E>(f: () => Awaited<T>, mapError: (err: unknown) => E): Result<T, E>;
61
- /**
62
- * Construct a {@link ResultAsync} from a function call. If the function returns
63
- * without throwing, and any promise returned resolves, the result is `Ok`.
104
+ * @example
105
+ *
106
+ * ```ts
107
+ * const [err, value] = Ok("test");
108
+ *
109
+ * assert.equal(err, undefined);
110
+ * assert.equal(value, "test");
111
+ * ```
112
+ *
113
+ * @example
114
+ *
115
+ * ```ts
116
+ * const result: Result<void, never> = Ok();
117
+ * ```
64
118
  */
65
- export declare function safeAsync<T>(f: () => T | PromiseLike<T>): ResultAsync<T, Error>;
66
- export declare function safeAsync<T, E>(f: () => T | PromiseLike<T>, mapError: (err: unknown) => E): ResultAsync<T, E>;
119
+ export declare function Ok(): Result<void, never>;
120
+ export declare function Ok<const T>(val: T): Result<T, never>;
67
121
  /**
68
- * Construct a {@link Result} from a promise. If the promise resolves, the
69
- * result is `Ok`.
122
+ * Create a new {@link Result} with the `Err` variant. When called without
123
+ * arguments the `E` type is `void`.
124
+ *
125
+ * @example
126
+ *
127
+ * ```ts
128
+ * const [err, value] = Err("test");
129
+ *
130
+ * assert.equal(err, "test");
131
+ * assert.equal(value, undefined);
132
+ * ```
133
+ *
134
+ * @example
135
+ *
136
+ * ```ts
137
+ * const result: Result<never, void> = Err();
138
+ * ```
70
139
  */
71
- export declare function safePromise<T>(promise: PromiseLike<T>): ResultAsync<T, Error>;
72
- export declare function safePromise<T, E>(promise: PromiseLike<T>, mapError: (err: unknown) => E): ResultAsync<T, E>;
140
+ export declare function Err(): Result<never, void>;
141
+ export declare function Err<const E>(err: E): Result<never, E>;
73
142
  /**
74
143
  * ## ResultAsync
75
144
  *
@@ -78,340 +147,1317 @@ export declare function safePromise<T, E>(promise: PromiseLike<T>, mapError: (er
78
147
  declare class ResultAsync<T, E> {
79
148
  #private;
80
149
  constructor(inner: PromiseLike<Result<T, E>>);
81
- then<TResult1 = Result<T, E>, TResult2 = never>(onfulfilled?: ((result: Result<T, E>) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>): PromiseLike<TResult1 | TResult2>;
82
- /**
83
- * @TODO
84
- */
85
- $value(this: ResultAsync<T, E>): Promise<T | E>;
150
+ then<U = Result<T, E>, F = never>(onfulfilled?: ((value: Result<T, E>) => U | PromiseLike<U>) | null | undefined, onrejected?: ((reason: any) => F | PromiseLike<F>) | null | undefined): PromiseLike<U | F>;
86
151
  /**
87
- * @TODO
152
+ * The same as {@link Retuple.$expect|$expect}, except it returns a `Promise`.
88
153
  */
89
154
  $expect(this: ResultAsync<T, Error>): Promise<T>;
90
155
  /**
91
- * @TODO
156
+ * The same as {@link Retuple.$unwrap|$unwrap}, except it returns a `Promise`.
92
157
  */
93
158
  $unwrap(this: ResultAsync<T, E>, msg?: string): Promise<T>;
94
159
  /**
95
- * @TODO
160
+ * The same as {@link Retuple.$unwrapErr|$unwrapErr}, except it returns
161
+ * a `Promise`.
96
162
  */
97
163
  $unwrapErr(this: ResultAsync<T, E>, msg?: string): Promise<E>;
98
164
  /**
99
- * @TODO
165
+ * The same as {@link Retuple.$unwrapOr|$unwrapOr}, except it returns
166
+ * a `Promise`.
100
167
  */
101
- $unwrapOr<U>(this: ResultAsync<T, E>, def: U): Promise<T | U>;
168
+ $unwrapOr<const U = T>(this: ResultAsync<T, E>, def: U): Promise<T | U>;
102
169
  /**
103
- * @TODO
170
+ * The same as {@link Retuple.$unwrapOrElse|$unwrapOrElse}, except it returns
171
+ * a `Promise`.
104
172
  */
105
173
  $unwrapOrElse<U = T>(this: ResultAsync<T, E>, f: () => U): Promise<T | U>;
106
174
  /**
107
- * @TODO
175
+ * The same as {@link Retuple.$map|$map}, except it returns
176
+ * {@link ResultAsync}.
108
177
  */
109
178
  $map<U>(this: ResultAsync<T, E>, f: (val: T) => U): ResultAsync<U, E>;
110
179
  /**
111
- * @TODO
180
+ * The same as {@link Retuple.$mapErr|$mapErr}, except it returns
181
+ * {@link ResultAsync}.
112
182
  */
113
- $mapErr<F>(this: ResultAsync<T, E>, f: (err: E) => F): ResultAsync<T, F>;
183
+ $mapErr<F = E>(this: ResultAsync<T, E>, f: (err: E) => F): ResultAsync<T, F>;
114
184
  /**
115
- * @TODO
185
+ * The same as {@link Retuple.$mapOr|$mapOr}, except it returns
186
+ * {@link ResultAsync}.
116
187
  */
117
- $mapOr<U>(this: ResultAsync<T, E>, def: U, f: (val: T) => U): ResultAsync<U, E>;
188
+ $mapOr<U, V = U>(this: ResultAsync<T, E>, def: U, f: (val: T) => V): ResultAsync<U | V, never>;
118
189
  /**
119
- * @TODO
190
+ * The same as {@link Retuple.$mapOrElse|$mapOrElse}, except it returns
191
+ * {@link ResultAsync}.
120
192
  */
121
- $mapOrElse<U>(this: ResultAsync<T, E>, def: (err: E) => U, f: (val: T) => U): ResultAsync<U, E>;
193
+ $mapOrElse<U, V = U>(this: ResultAsync<T, E>, def: (err: E) => U, f: (val: T) => V): ResultAsync<U | V, never>;
122
194
  /**
123
- * @TODO
195
+ * The same as {@link Retuple.$andAssertOr|$andAssertOr}, except it:
196
+ *
197
+ * - can also accept a `PromiseLike` default value;
198
+ * - returns {@link ResultAsync}.
124
199
  */
125
- $or<U = T, F = E>(this: ResultAsync<T, E>, or: Result<U, F> | PromiseLike<Result<U, F>>): ResultAsync<T | U, E | F>;
200
+ $andAssertOr<U = T, F = E>(this: ResultAsync<T, E>, def: ResultLikeAwaitable<U, F>): ResultAsync<Truthy<T> | U, E | F>;
201
+ $andAssertOr<U = T, F = E, A extends T = T>(this: ResultAsync<T, E>, def: ResultLikeAwaitable<U, F>, predicate: (val: T) => val is A): ResultAsync<U | A, E | F>;
202
+ $andAssertOr<U = T, F = E>(this: ResultAsync<T, E>, def: ResultLikeAwaitable<U, F>, condition: (val: T) => unknown): ResultAsync<T | U, E | F>;
126
203
  /**
127
- * @TODO
204
+ * The same as {@link Retuple.$andAssertOrElse|$andAssertOrElse}, except it:
205
+ *
206
+ * - can also accept an `async` default function;
207
+ * - returns {@link ResultAsync}.
128
208
  */
129
- $orElse<U = T, F = E>(this: ResultAsync<T, E>, f: (err: E) => Result<U, F> | PromiseLike<Result<U, F>>): ResultAsync<T | U, E | F>;
209
+ $andAssertOrElse<U = T, F = E>(this: ResultAsync<T, E>, def: (val: T) => ResultLikeAwaitable<U, F>): ResultAsync<Truthy<T> | U, E | F>;
210
+ $andAssertOrElse<U = T, F = E, A extends T = T>(this: ResultAsync<T, E>, def: (val: T) => ResultLikeAwaitable<U, F>, predicate: (val: T) => val is A): ResultAsync<U | A, E | F>;
211
+ $andAssertOrElse<U = T, F = E>(this: ResultAsync<T, E>, def: (val: T) => ResultLikeAwaitable<U, F>, condition: (val: T) => unknown): ResultAsync<T | U, E | F>;
130
212
  /**
131
- * @TODO
213
+ * The same as {@link Retuple.$or|$or}, except it:
214
+ *
215
+ * - can also accept a `PromiseLike` or value;
216
+ * - returns {@link ResultAsync}.
132
217
  */
133
- $orSafe<U = T, F = Error>(this: ResultAsync<T, E>, f: (err: E) => U | PromiseLike<U>, mapError?: (err: unknown) => F): ResultAsync<T | U, E | F>;
218
+ $or<U = T, F = E>(this: ResultAsync<T, E>, or: ResultLikeAwaitable<U, F>): ResultAsync<T | U, F>;
134
219
  /**
135
- * @TODO
220
+ * The same as {@link Retuple.$orElse|$orElse}, except it:
221
+ *
222
+ * - can also accept an `async` or function;
223
+ * - returns {@link ResultAsync}.
136
224
  */
137
- $and<U = T, F = E>(this: ResultAsync<T, E>, and: Result<U, F> | PromiseLike<Result<U, F>>): ResultAsync<U, E | F>;
225
+ $orElse<U = T, F = E>(this: ResultAsync<T, E>, f: (err: E) => ResultLikeAwaitable<U, F>): ResultAsync<T | U, F>;
138
226
  /**
139
- * @TODO
227
+ * The same as {@link Retuple.$orSafe|$orSafe}, except it:
228
+ *
229
+ * - can also accept an `async` safe function;
230
+ * - returns {@link ResultAsync}.
140
231
  */
141
- $andThen<U = T, F = E>(this: ResultAsync<T, E>, f: (val: T) => Result<U, F> | PromiseLike<Result<U, F>>): ResultAsync<U, E | F>;
232
+ $orSafe<U = T>(this: ResultAsync<T, E>, f: (err: E) => U | PromiseLike<U>): ResultAsync<T | U, Error>;
233
+ $orSafe<U = T, F = E>(this: ResultAsync<T, E>, f: (err: E) => U | PromiseLike<U>, mapError: (err: unknown) => F): ResultAsync<T | U, F>;
142
234
  /**
143
- * @TODO
235
+ * Returns {@link ResultAsync} based on the outcome of the promise when this
236
+ * result is `Err`.
237
+ *
238
+ * Otherwise, returns `Ok` containing the current contained value.
239
+ *
240
+ * Uses the same strategy as {@link Result.$safePromise}, equivalent to
241
+ * calling:
242
+ *
243
+ * ```ts
244
+ * resultAsync.$orElse(() => Result.$safePromise(...))
245
+ * ```
144
246
  */
145
- $andThrough<F = E>(this: ResultAsync<T, E>, f: (val: T) => Result<any, F> | PromiseLike<Result<any, F>>): ResultAsync<T, E | F>;
247
+ $orSafePromise<U = T>(this: ResultAsync<T, E>, promise: PromiseLike<U>): ResultAsync<T | U, Error>;
248
+ $orSafePromise<U = T, F = E>(this: ResultAsync<T, E>, promise: PromiseLike<U>, mapError: (err: unknown) => F): ResultAsync<T | U, F>;
146
249
  /**
147
- * @TODO
250
+ * The same as {@link Retuple.$and|$and}, except it:
251
+ *
252
+ * - can also accept a `PromiseLike` and value;
253
+ * - returns {@link ResultAsync}.
148
254
  */
149
- $andSafe<U = T, F = Error>(this: ResultAsync<T, E>, f: (val: T) => U | PromiseLike<U>, mapError?: (err: unknown) => F): ResultAsync<U, E | F>;
255
+ $and<U = T, F = E>(this: ResultAsync<T, E>, and: ResultLikeAwaitable<U, F>): ResultAsync<U, E | F>;
150
256
  /**
151
- * @TODO
257
+ * The same as {@link Retuple.$andThen|$andThen}, except it:
258
+ *
259
+ * - can also accept an `async` and function;
260
+ * - returns {@link ResultAsync}.
152
261
  */
153
- $peek(this: ResultAsync<T, E>, f: (res: Result<T, E>) => any): ResultAsync<T, E>;
262
+ $andThen<U = T, F = E>(this: ResultAsync<T, E>, f: (val: T) => ResultLikeAwaitable<U, F>): ResultAsync<U, E | F>;
154
263
  /**
155
- * @TODO
264
+ * The same as {@link Retuple.$andThrough|$andThrough}, except it:
265
+ *
266
+ * - can also accept an `async` through function;
267
+ * - returns {@link ResultAsync}.
156
268
  */
157
- $tap(this: ResultAsync<T, E>, f: (val: T) => any): ResultAsync<T, E>;
269
+ $andThrough<F = E>(this: ResultAsync<T, E>, f: (val: T) => ResultLikeAwaitable<any, F>): ResultAsync<T, E | F>;
158
270
  /**
159
- * @TODO
271
+ * The same as {@link Retuple.$andSafe|$andSafe}, except it:
272
+ *
273
+ * - can also accept an `async` safe function;
274
+ * - returns {@link ResultAsync}.
160
275
  */
161
- $tapErr(this: ResultAsync<T, E>, f: (err: E) => any): ResultAsync<T, E>;
276
+ $andSafe<U = T>(this: ResultAsync<T, E>, f: (val: T) => U | PromiseLike<U>): ResultAsync<U, E | Error>;
277
+ $andSafe<U = T, F = E>(this: ResultAsync<T, E>, f: (val: T) => U | PromiseLike<U>, mapError: (err: unknown) => F): ResultAsync<U, E | F>;
162
278
  /**
163
- * @TODO
279
+ * Returns {@link ResultAsync} based on the outcome of the promise when this
280
+ * result is `Ok`.
281
+ *
282
+ * Otherwise, returns `Err` containing the current error value.
283
+ *
284
+ * Uses the same strategy as {@link Result.$safePromise}, equivalent to
285
+ * calling:
286
+ *
287
+ * ```ts
288
+ * resultAsync.$andThen(() => Result.$safePromise(...))
289
+ * ```
290
+ */
291
+ $andSafePromise<U = T>(this: ResultAsync<T, E>, promise: PromiseLike<U>): ResultAsync<U, E | Error>;
292
+ $andSafePromise<U = T, F = E>(this: ResultAsync<T, E>, promise: PromiseLike<U>, mapError: (err: unknown) => F): ResultAsync<U, E | F>;
293
+ /**
294
+ * The same as {@link Retuple.$peek|$peek}, except it:
295
+ *
296
+ * - awaits the peek function;
297
+ * - returns {@link ResultAsync}.
164
298
  */
165
- $promise(this: ResultAsync<T, E>): Promise<Result<T, E>>;
166
- }
167
- type OkTuple<T> = [err: undefined, value: T];
168
- type ErrTuple<E> = [err: E, value: undefined];
169
- type Truthy<T> = Exclude<T, false | null | undefined | 0 | 0n | "">;
170
- /**
171
- * @TODO - Result.all / Result.any
172
- */
173
- interface Retuple<T, E> {
174
- /**
175
- * @TODO
176
- */
177
- $isOk(this: Result<T, E>): this is Ok<T>;
299
+ $peek(this: ResultAsync<T, E>, f: (res: Result<T, E>) => any): ResultAsync<T, E>;
178
300
  /**
179
- * @TODO
301
+ * The same as {@link Retuple.$tap|$tap}, except it:
302
+ *
303
+ * - awaits the tap function;
304
+ * - returns {@link ResultAsync}.
180
305
  */
181
- $isOkAnd<U extends T = T>(this: Result<T, E>, f: ((val: T) => val is U) | ((val: T) => boolean)): this is Ok<U>;
306
+ $tap(this: ResultAsync<T, E>, f: (val: T) => any): ResultAsync<T, E>;
182
307
  /**
183
- * @TODO
308
+ * The same as {@link Retuple.$tapErr|$tapErr}, except it:
309
+ *
310
+ * - awaits the tap error function;
311
+ * - returns {@link ResultAsync}.
184
312
  */
185
- $isErr(this: Result<T, E>): this is Err<E>;
313
+ $tapErr(this: ResultAsync<T, E>, f: (err: E) => any): ResultAsync<T, E>;
186
314
  /**
187
- * @TODO
315
+ * The same as {@link Retuple.$promise|$promise}.
188
316
  */
189
- $isErrAnd<F extends E = E>(this: Result<T, E>, f: ((err: E) => err is F) | ((err: E) => boolean)): this is Err<F>;
317
+ $promise(this: ResultAsync<T, E>): Promise<Result<T, E>>;
190
318
  /**
191
- * @TODO
319
+ * The same as {@link Retuple.$iter|$iter}, except it returns a `Promise`.
192
320
  */
193
- $value(this: Result<T, E>): T | E;
194
- /**
195
- * @TODO
321
+ $iter<U>(this: ResultAsync<Iterable<U>, E>): Promise<IterableIterator<U, undefined, unknown>>;
322
+ }
323
+ /**
324
+ * ## ResultRetry
325
+ */
326
+ declare class ResultRetry<T, E> extends ResultAsync<T, E> implements PromiseLike<Result<T, E>> {
327
+ #private;
328
+ private static MAX_TIMEOUT;
329
+ private static MAX_RETRY;
330
+ private static zero;
331
+ private static delay;
332
+ private static integer;
333
+ constructor(f: () => ResultLikeAwaitable<T, E>);
334
+ then<U = Result<T, E>, F = never>(this: ResultRetry<T, E>, onfulfilled?: ((value: Result<T, E>) => U | PromiseLike<U>) | null | undefined, onrejected?: ((reason: any) => F | PromiseLike<F>) | null | undefined): PromiseLike<U | F>;
335
+ /**
336
+ * Sets the maximum number of times the retry function can be executed,
337
+ * mutating this `ResultRetry` instance.
338
+ *
339
+ * **The default value is 1 - meaning that unless set, no retries will be
340
+ * attempted.**
341
+ *
342
+ * The retry function can be called up to the maximum number of times until
343
+ * it returns `Ok`. If it never returns `Ok`, the most recent `Err` is
344
+ * returned.
345
+ *
346
+ * This function accepts a positive integer between 1 and 100:
347
+ *
348
+ * - Integers outside of this range are clamped to the nearest valid value;
349
+ * - Any other value (NaN, Infinity, fractions, strings) are treated as 1.
350
+ *
351
+ * @example
352
+ *
353
+ * ```ts
354
+ * // Retry someResultFn up to 3 times until Ok is returned:
355
+ * const result = await Result.$retry(someResultFn).$times(3);
356
+ * ```
357
+ */
358
+ $times<N extends number>(this: ResultRetry<T, E>, times: NonZero<N> & NonNegativeOrDecimal<N>): ResultRetry<T, E>;
359
+ /**
360
+ * Sets the delay between each retry attempt, mutating this `ResultRetry`
361
+ * instance.
362
+ *
363
+ * - Provide a number of milliseconds to introduce a static delay between
364
+ * attempts;
365
+ * - Provide a function to compute the delay dynamically for each attempt;
366
+ * - If the maximum number of retries is 1, this setting as no effect.
367
+ *
368
+ * **The default value is 0 - meaning that unless set, there will be no delay
369
+ * between attempts.**
370
+ *
371
+ * This function accepts an integer between 0 and 3600000:
372
+ *
373
+ * - Integers outside of this range are clamped to the nearest valid value;
374
+ * - Any other value (NaN, Infinity, fractions, strings) are treated as 0.
375
+ *
376
+ * @example
377
+ *
378
+ * ```ts
379
+ * // Retry someResultFn up to 3 times until Ok is returned,
380
+ * // with a 1 second delay between each invocation:
381
+ * const result = await Result.$retry(someResultFn).$times(3).$delay(1000);
382
+ * ```
383
+ */
384
+ $delay<N extends number>(this: ResultRetry<T, E>, f: (attempt: number) => NonNegativeOrDecimal<N>): ResultRetry<T, E>;
385
+ $delay<N extends number>(this: ResultRetry<T, E>, ms: NonNegativeOrDecimal<N>): ResultRetry<T, E>;
386
+ /**
387
+ * Sets a handler to be called when an attempt returns `Err`, mutating this
388
+ * `ResultRetry` instance. The handler can be used to capture information
389
+ * about each failure, and to abort early and prevent further retries.
390
+ *
391
+ * The handler function is called with `ResultRetryHandleState`, containing:
392
+ *
393
+ * - **error** - The error value from the last failed attempt;
394
+ * - **attempt** - The attempt number;
395
+ * - **abort** - A function which when called, prevents further retries.
396
+ *
397
+ * @example
398
+ *
399
+ * ```ts
400
+ * // Retry someResultFn up to 3 times until Ok is returned, logging each
401
+ * // attempt and aborting early if the error code is "UNAUTHORIZED".
402
+ * const result = await Result.$retry(someResultFn)
403
+ * .$times(3)
404
+ * .$handle(({ error, attempt, abort }) => {
405
+ * console.info(`Attempt ${attempt} failed: ${error}`);
406
+ * if (error === "UNAUTHORIZED") {
407
+ * abort();
408
+ * }
409
+ * });
410
+ * ```
411
+ */
412
+ $handle(f: (controller: ResultRetryController<E>) => void): ResultRetry<T, E>;
413
+ private drain;
414
+ }
415
+ interface Retuple<T, E> extends ResultLike<T, E> {
416
+ /**
417
+ * Returns true when this result is `Ok`. Acts as a type guard.
418
+ *
419
+ * @example
420
+ *
421
+ * ```ts
422
+ * const result = Ok("test");
423
+ * assert.equal(result.$isOk(), true);
424
+ * ```
425
+ *
426
+ * @example
427
+ *
428
+ * ```ts
429
+ * const result = Err("test");
430
+ * assert.equal(result.$isOk(), false);
431
+ * ```
432
+ *
433
+ * @example
434
+ *
435
+ * ```ts
436
+ * const result: Result<string, Error> = someResultFn();
437
+ *
438
+ * if (result.$isOk()) {
439
+ * result satisfies Result<string, never>;
440
+ * }
441
+ * ```
442
+ */
443
+ $isOk(this: Result<T, E>): this is Result<T, never>;
444
+ /**
445
+ * Returns true when this result is `Ok`, and when the predicate/condition
446
+ * function returns true. Acts as a type guard.
447
+ *
448
+ * @example
449
+ *
450
+ * ```ts
451
+ * const result = Ok("test");
452
+ * assert.equal(result.$isOkAnd((val) => val === "test"), true);
453
+ * ```
454
+ *
455
+ * @example
456
+ *
457
+ * ```ts
458
+ * const result = Ok<string>("test");
459
+ * assert.equal(result.$isOkAnd((val) => val !== "test"), false);
460
+ * ```
461
+ *
462
+ * @example
463
+ *
464
+ * ```ts
465
+ * const result = Err("test");
466
+ * assert.equal(result.$isOkAnd((err) => err === "test"), false);
467
+ * ```
468
+ *
469
+ * @example
470
+ *
471
+ * ```ts
472
+ * const result: Result<string | number, Error> = someResultFn();
473
+ *
474
+ * if (result.$isOkAnd((val): val is number => typeof val === "number")) {
475
+ * result satisfies Result<number, never>;
476
+ * }
477
+ * ```
478
+ */
479
+ $isOkAnd<U extends T = T>(this: Result<T, E>, predicate: (val: T) => val is U): this is Result<U, never>;
480
+ $isOkAnd(this: Result<T, E>, predicate: (val: T) => unknown): this is Result<T, never>;
481
+ /**
482
+ * Returns true when this result is `Err`. Acts as a type guard.
483
+ *
484
+ * @example
485
+ *
486
+ * ```ts
487
+ * const result = Err("test");
488
+ * assert.equal(result.$isErr(), true);
489
+ * ```
490
+ *
491
+ * @example
492
+ *
493
+ * ```ts
494
+ * const result = Ok("test");
495
+ * assert.equal(result.$isErr(), false);
496
+ * ```
497
+ *
498
+ * @example
499
+ *
500
+ * ```ts
501
+ * const result: Result<string, Error> = someResultFn();
502
+ *
503
+ * if (result.$isErr()) {
504
+ * result satisfies Result<never, Error>;
505
+ * }
506
+ * ```
507
+ */
508
+ $isErr(this: Result<T, E>): this is Result<never, E>;
509
+ /**
510
+ * Returns true when this result is `Err`, and when the predicate/condition
511
+ * function returns true. Acts as a type guard.
512
+ *
513
+ * @example
514
+ *
515
+ * ```ts
516
+ * const result = Err("test");
517
+ * assert.equal(result.$isErrAnd((err) => err === "test"), true);
518
+ * ```
519
+ *
520
+ * @example
521
+ *
522
+ * ```ts
523
+ * const result = Err<string>("test");
524
+ * assert.equal(result.$isErrAnd((err) => err !== "test"), false);
525
+ * ```
526
+ *
527
+ * @example
528
+ *
529
+ * ```ts
530
+ * const result = Ok("test");
531
+ * assert.equal(result.$isErrAnd((val) => val === "test"), false);
532
+ * ```
533
+ *
534
+ * @example
535
+ *
536
+ * ```ts
537
+ * const result: Result<string, Error | number> = someResultFn();
538
+ *
539
+ * if (result.$isErrAnd((err): err is number => typeof err === "number")) {
540
+ * result satisfies Result<never, number>;
541
+ * }
542
+ * ```
543
+ */
544
+ $isErrAnd<F extends E = E>(this: Result<T, E>, prediacte: (val: E) => val is F): this is Result<never, F>;
545
+ $isErrAnd(this: Result<T, E>, predicate: (val: E) => unknown): this is Result<never, E>;
546
+ /**
547
+ * Returns the ok value when this result is `Ok`.
548
+ *
549
+ * Otherwise, the error value is thrown.
550
+ *
551
+ * This method should only be called when the `E` type extends `Error`. This
552
+ * is enforced with a type constraint. If the error value is not an instance
553
+ * of Error, `RetupleExpectFailed` is thrown. Use
554
+ * {@link Retuple.$unwrap|$unwrap} When the `E` type does not extend Error.
555
+ *
556
+ * @example
557
+ *
558
+ * ```ts
559
+ * const result = Ok("test");
560
+ * assert.equal(result.$expect(), "test");
561
+ * ```
562
+ *
563
+ * @example
564
+ *
565
+ * ```ts
566
+ * const error = new Error("test");
567
+ * const result = Err(error);
568
+ *
569
+ * try {
570
+ * const value = result.$expect(); // throws
571
+ * } catch (e) {
572
+ * assert.equal(e, error);
573
+ * }
574
+ * ```
575
+ *
576
+ * @example
577
+ *
578
+ * ```ts
579
+ * const result = Err("test");
580
+ *
581
+ * try {
582
+ * // This is a type error - the E type does not extend Error
583
+ * const value = result.$expect(); // throws
584
+ * } catch (e) {
585
+ * assert(e instanceof RetupleExpectFailed && e.value === "test");
586
+ * }
587
+ * ```
196
588
  */
197
589
  $expect(this: Result<T, Error>): T;
198
590
  /**
199
- * @TODO
591
+ * Returns the ok value when this result is `Ok`.
592
+ *
593
+ * Otherwise, `RetupleUnwrapFailed` is thrown. A custom error message can be
594
+ * provided.
595
+ *
596
+ * @example
597
+ *
598
+ * ```ts
599
+ * const result = Ok("test");
600
+ * assert.equal(result.$unwrap(), "test");
601
+ * ```
602
+ *
603
+ * @example
604
+ *
605
+ * ```ts
606
+ * const result = Err("test");
607
+ *
608
+ * try {
609
+ * const value = result.$unwrap(); // throws
610
+ * } catch (e) {
611
+ * assert(e instanceof RetupleUnwrapFailed && e.value === "test");
612
+ * }
613
+ * ```
614
+ *
615
+ * @example
616
+ *
617
+ * ```ts
618
+ * const error = new Error("test");
619
+ * const result = Err(error);
620
+ *
621
+ * try {
622
+ * const value = result.$unwrap("error-message"); // throws
623
+ * } catch (e) {
624
+ * assert(
625
+ * e instanceof RetupleUnwrapFailed &&
626
+ * e.message === "error-message" &&
627
+ * e.value === error &&
628
+ * e.cause === error, // set when error value was an instance of `Error`
629
+ * );
630
+ * }
631
+ * ```
200
632
  */
201
633
  $unwrap(this: Result<T, E>, msg?: string): T;
202
634
  /**
203
- * @TODO
635
+ * Returns the error value when this result is `Err`.
636
+ *
637
+ * Otherwise, `RetupleUnwrapErrFailed` is thrown. A custom error message can
638
+ * be provided.
639
+ *
640
+ * @example
641
+ *
642
+ * ```ts
643
+ * const result = Err("test");
644
+ * assert.equal(result.$unwrapErr(), "test");
645
+ * ```
646
+ *
647
+ * @example
648
+ *
649
+ * ```ts
650
+ * const result = Ok("test");
651
+ *
652
+ * try {
653
+ * const value = result.$unwrapErr(); // throws
654
+ * } catch (e) {
655
+ * assert(e instanceof RetupleUnwrapErrFailed && e.value === "test");
656
+ * }
657
+ * ```
658
+ *
659
+ * @example
660
+ *
661
+ * ```ts
662
+ * const result = Ok("test");
663
+ *
664
+ * try {
665
+ * const value = result.$unwrapErr("error-message"); // throws
666
+ * } catch (e) {
667
+ * assert(
668
+ * e instanceof RetupleUnwrapErrFailed &&
669
+ * e.message === "error-message" &&
670
+ * e.value === "test",
671
+ * );
672
+ * }
673
+ * ```
204
674
  */
205
675
  $unwrapErr(this: Result<T, E>, msg?: string): E;
206
676
  /**
207
- * @TODO
208
- */
209
- $unwrapOr<U = T>(this: Result<T, E>, def: U): T | U;
210
- /**
211
- * @TODO
677
+ * Returns the ok value when this result is `Ok`.
678
+ *
679
+ * Otherwise, returns the default value.
680
+ *
681
+ * @example
682
+ *
683
+ * ```ts
684
+ * const result = Ok("test");
685
+ * assert.equal(result.$unwrapOr("default"), "test");
686
+ * ```
687
+ *
688
+ * @example
689
+ *
690
+ * ```ts
691
+ * const result = Err("test");
692
+ * assert.equal(result.$unwrapOr("default"), "default");
693
+ * ```
694
+ */
695
+ $unwrapOr<const U = T>(this: Result<T, E>, def: U): T | U;
696
+ /**
697
+ * Returns the ok value when this result is `Ok`.
698
+ *
699
+ * Otherwise, returns the value returned by the default function.
700
+ *
701
+ * @example
702
+ *
703
+ * ```ts
704
+ * const result = Ok("test");
705
+ * assert.equal(result.$unwrapOrElse(() => "default"), "test");
706
+ * ```
707
+ *
708
+ * @example
709
+ *
710
+ * ```ts
711
+ * const result = Err("test");
712
+ * assert.equal(result.$unwrapOrElse(() => "default"), "default");
713
+ * ```
212
714
  */
213
715
  $unwrapOrElse<U = T>(this: Result<T, E>, f: () => U): T | U;
214
716
  /**
215
- * @TODO
717
+ * Performs an assertion when this result is `Ok`:
718
+ *
719
+ * - returning `Ok` containing the current ok value when it is truthy, and
720
+ * when no predicate/condition function is provided. Narrows the `T` type
721
+ * to include only truthy values;
722
+ * - returning `Ok` containing the current ok value when a
723
+ * predicate/condition function is provided and it returns a truthy value.
724
+ * Narrows the `T` type to the predicate type (if any);
725
+ * - returning the default result when no predicate/condition function is
726
+ * provided and the current ok value is falsey;
727
+ * - returning the default result when a predicate/condition function is
728
+ * provided and it returns a falsey value.
729
+ *
730
+ * Otherwise returns `Err` containing the current error value.
731
+ *
732
+ * @example
733
+ *
734
+ * ```ts
735
+ * const result: Result<string | null, string> = Ok("test");
736
+ * const asserted = result.$andAssertOr(Ok("ok-default"));
737
+ *
738
+ * asserted satisfies Result<string, string>;
739
+ * assert.equal(asserted.$unwrap(), "test");
740
+ * ```
741
+ *
742
+ * @example
743
+ *
744
+ * ```ts
745
+ * const result: Result<string | null, string> = Ok("test");
746
+ * const asserted = result.$andAssertOr(
747
+ * Err("err-default"),
748
+ * (val): val is "test" => val === "test",
749
+ * );
750
+ *
751
+ * asserted satisfies Result<"test", string>;
752
+ * assert.equal(asserted.$unwrap(), "test");
753
+ * ```
754
+ *
755
+ * @example
756
+ *
757
+ * ```ts
758
+ * const result: Result<string | null, string> = Ok(null);
759
+ * const asserted = result.$andAssertOr(Ok("ok-default"));
760
+ *
761
+ * asserted satisfies Result<string, string>;
762
+ * assert.equal(asserted.$unwrap(), "ok-default");
763
+ * ```
764
+ *
765
+ * @example
766
+ *
767
+ * ```ts
768
+ * const result: Result<string | null, string> = Ok("value");
769
+ * const asserted = result.$andAssertOr(
770
+ * Err("err-default"),
771
+ * (val): val is "test" => val === "test",
772
+ * );
773
+ *
774
+ * asserted satisfies Result<"test", string>;
775
+ * assert.equal(asserted.$unwrapErr(), "err-default");
776
+ * ```
777
+ *
778
+ * @example
779
+ *
780
+ * ```ts
781
+ * const result: Result<string | null, string> = Err("test");
782
+ * const asserted = result.$andAssertOr(
783
+ * Err("err-default"),
784
+ * (val): val is "test" => val === "test",
785
+ * );
786
+ *
787
+ * asserted satisfies Result<"test", string>;
788
+ * assert.equal(asserted.$unwrapErr(), "test");
789
+ * ```
790
+ */
791
+ $andAssertOr<U = T, F = E>(this: Result<T, E>, def: ResultLike<U, F>): Result<Truthy<T> | U, E | F>;
792
+ $andAssertOr<U = T, F = E, A extends T = T>(this: Result<T, E>, def: ResultLike<U, F>, predicate: (val: T) => val is A): Result<U | A, E | F>;
793
+ $andAssertOr<U = T, F = E>(this: Result<T, E>, def: ResultLike<U, F>, condition: (val: T) => unknown): Result<T | U, E | F>;
794
+ /**
795
+ * Performs an assertion when this result is `Ok`:
796
+ *
797
+ * - returning `Ok` containing the current ok value when it is truthy, and
798
+ * when no predicate/condition function is provided. Narrows the `T` type
799
+ * to include only truthy values;
800
+ * - returning `Ok` containing the current ok value when a
801
+ * predicate/condition function is provided and it returns a truthy value.
802
+ * Narrows the `T` type to the predicate type (if any);
803
+ * - returning the result returned by the default function when no
804
+ * predicate/condition function is provided and the current ok value is
805
+ * falsey;
806
+ * - returning the result returned by the default function when a
807
+ * predicate/condition function is provided and it returns a falsey value.
808
+ *
809
+ * Otherwise returns `Err` containing the current error value.
810
+ *
811
+ * @example
812
+ *
813
+ * ```ts
814
+ * const result: Result<string | null, string> = Ok("test");
815
+ * const asserted = result.$andAssertOrElse(
816
+ * (val) => Ok(`ok-default:${val}`),
817
+ * );
818
+ *
819
+ * asserted satisfies Result<string, string>;
820
+ * assert.equal(asserted.$unwrap(), "test");
821
+ * ```
822
+ *
823
+ * @example
824
+ *
825
+ * ```ts
826
+ * const result: Result<string | null, string> = Ok("test");
827
+ * const asserted = result.$andAssertOrElse(
828
+ * (val) => Err(`err-default:${val}`),
829
+ * (val): val is "test" => val === "test",
830
+ * );
831
+ *
832
+ * asserted satisfies Result<"test", string>;
833
+ * assert.equal(asserted.$unwrap(), "test");
834
+ * ```
835
+ *
836
+ * @example
837
+ *
838
+ * ```ts
839
+ * const result: Result<string | null, string> = Ok(null);
840
+ * const asserted = result.$andAssertOrElse(
841
+ * (val) => Ok(`ok-default:${val}`),
842
+ * );
843
+ *
844
+ * asserted satisfies Result<string, string>;
845
+ * assert.equal(asserted.$unwrap(), "ok-default:null");
846
+ * ```
847
+ *
848
+ * @example
849
+ *
850
+ * ```ts
851
+ * const result: Result<string | null, string> = Ok("value");
852
+ * const asserted = result.$andAssertOrElse(
853
+ * (val) => Err(`err-default:${val}`),
854
+ * (val): val is "test" => val === "test",
855
+ * );
856
+ *
857
+ * asserted satisfies Result<"test", string>;
858
+ * assert.equal(asserted.$unwrapErr(), "err-default:value");
859
+ * ```
860
+ *
861
+ * @example
862
+ *
863
+ * ```ts
864
+ * const result: Result<string | null, string> = Err("test");
865
+ * const asserted = result.$andAssertOrElse(
866
+ * (val) => Err(`err-default:${val}`),
867
+ * (val): val is "test" => val === "test",
868
+ * );
869
+ *
870
+ * asserted satisfies Result<"test", string>;
871
+ * assert.equal(asserted.$unwrapErr(), "test");
872
+ * ```
873
+ */
874
+ $andAssertOrElse<U = T, F = E>(this: Result<T, E>, def: (val: T) => ResultLike<U, F>): Result<Truthy<T> | U, E | F>;
875
+ $andAssertOrElse<U = T, F = E, A extends T = T>(this: Result<T, E>, def: (val: T) => ResultLike<U, F>, predicate: (val: T) => val is A): Result<U | A, E | F>;
876
+ $andAssertOrElse<U = T, F = E>(this: Result<T, E>, def: (val: T) => ResultLike<U, F>, condition: (val: T) => unknown): Result<T | U, E | F>;
877
+ /**
878
+ * Returns `Ok` containing the return value of the map function when this
879
+ * result is `Ok`.
880
+ *
881
+ * Otherwise, returns `Err` containing the current error value.
882
+ *
883
+ * @example
884
+ *
885
+ * ```ts
886
+ * const result = Ok("test");
887
+ * assert.equal(
888
+ * result.$map((val) => `map:${val}`).$unwrap(),
889
+ * "map:test",
890
+ * );
891
+ * ```
892
+ *
893
+ * @example
894
+ *
895
+ * ```ts
896
+ * const result: Result<string, string> = Err("test");
897
+ * assert.equal(
898
+ * result.$map((val) => `map:${val}`).$unwrapErr(),
899
+ * "test",
900
+ * );
901
+ * ```
216
902
  */
217
903
  $map<U>(this: Result<T, E>, f: (value: T) => U): Result<U, E>;
218
904
  /**
219
- * @TODO
220
- */
221
- $mapErr<F>(this: Result<T, E>, f: (err: E) => F): Result<T, F>;
222
- /**
223
- * @TODO
224
- */
225
- $mapOr<U>(this: Result<T, E>, def: U, f: (val: T) => U): Result<U, E>;
226
- /**
227
- * @TODO
228
- */
229
- $mapOrElse<U>(this: Result<T, E>, def: (err: E) => U, f: (val: T) => U): Result<U, E>;
230
- /**
231
- * @TODO
232
- */
233
- $or<U = T, F = E>(this: Result<T, E>, or: Result<U, F>): Result<T | U, E | F>;
234
- /**
235
- * @TODO
236
- */
237
- $orElse<U = never, F = never>(this: Result<T, E>, f: (err: E) => Result<U, F>): Result<T | U, E | F>;
238
- /**
239
- * @TODO
240
- */
241
- $orSafe<U = T>(this: Result<T, E>, f: (err: E) => U): Result<T | U, E | Error>;
242
- $orSafe<U = T, F = E>(this: Result<T, E>, f: (err: E) => U, mapError: (err: unknown) => F): Result<T | U, E | F>;
243
- $orSafe<U = T, F = Error>(this: Result<T, E>, f: (err: E) => U, mapError: (err: unknown) => F): Result<T | U, E | F>;
244
- /**
245
- * @TODO
246
- */
247
- $and<U = T, F = E>(this: Result<T, E>, and: Result<U, F>): Result<U, E | F>;
248
- /**
249
- * @TODO
250
- */
251
- $andThen<U = never, F = never>(this: Result<T, E>, f: (val: T) => Result<U, F>): Result<U, E | F>;
252
- /**
253
- * @TODO
254
- */
255
- $andThrough<F = never>(this: Result<T, E>, f: (val: T) => Result<any, F>): Result<T, E | F>;
256
- /**
257
- * @TODO
258
- */
259
- $andSafe<U = T>(this: Result<T, E>, f: (val: T) => U): Result<T | U, E | Error>;
260
- $andSafe<U = T, F = E>(this: Result<T, E>, f: (val: T) => U, mapError: (err: unknown) => F): Result<T | U, E | F>;
261
- $andSafe<U, F = Error>(this: Result<T, E>, f: (val: T) => U, mapError: (err: unknown) => F): Result<T | U, E | F>;
262
- /**
263
- * @TODO
905
+ * Returns `Err` containing the return value of the map function when this
906
+ * result is `Err`.
907
+ *
908
+ * Otherwise, returns `Ok` containing the current ok value.
909
+ *
910
+ * @example
911
+ *
912
+ * ```ts
913
+ * const result = Err("test");
914
+ * assert.equal(
915
+ * result.$mapErr((err) => `map-err:${err}`).$unwrapErr(),
916
+ * "map-err:test",
917
+ * );
918
+ * ```
919
+ *
920
+ * @example
921
+ *
922
+ * ```ts
923
+ * const result: Result<string, string> = Ok("test");
924
+ * assert.equal(
925
+ * result.$mapErr((err) => `map-err:${err}`).$unwrap(),
926
+ * "test",
927
+ * );
928
+ * ```
929
+ */
930
+ $mapErr<F = E>(this: Result<T, E>, f: (err: E) => F): Result<T, F>;
931
+ /**
932
+ * Returns `Ok` containing the return value of the map function when this
933
+ * result is `Ok`.
934
+ *
935
+ * Otherwise, returns `Ok` containing the default value.
936
+ *
937
+ * @example
938
+ *
939
+ * ```ts
940
+ * const result: Result<string, string> = Ok("test");
941
+ * assert.equal(
942
+ * result.$mapOr("default", (val) => `map:${val}`).$unwrap(),
943
+ * "map:test",
944
+ * );
945
+ * ```
946
+ *
947
+ * @example
948
+ *
949
+ * ```ts
950
+ * const result: Result<string, string> = Err("test");
951
+ * assert.equal(
952
+ * result.$mapOr("default", (val) => `map:${val}`).$unwrap(),
953
+ * "default",
954
+ * );
955
+ * ```
956
+ */
957
+ $mapOr<U, V = U>(this: Result<T, E>, def: U, f: (val: T) => V): Result<U | V, never>;
958
+ /**
959
+ * Returns `Ok` containing the return value of the map function when this
960
+ * result is `Ok`.
961
+ *
962
+ * Otherwise, returns `Ok` containing the return value of the default
963
+ * function.
964
+ *
965
+ * @example
966
+ *
967
+ * ```ts
968
+ * const result: Result<string, string> = Ok("test");
969
+ * assert.equal(
970
+ * result.$mapOrElse(
971
+ * (err) => `default:${err}`,
972
+ * (val) => `map:${val}`,
973
+ * ).$unwrap(),
974
+ * "map:test",
975
+ * );
976
+ * ```
977
+ *
978
+ * @example
979
+ *
980
+ * ```ts
981
+ * const result: Result<string, string> = Err("test");
982
+ * assert.equal(
983
+ * result.$mapOrElse(
984
+ * (err) => `default:${err}`,
985
+ * (val) => `map:${val}`,
986
+ * ).$unwrap(),
987
+ * "default:test",
988
+ * );
989
+ * ```
990
+ */
991
+ $mapOrElse<U, V = U>(this: Result<T, E>, def: (err: E) => U, f: (val: T) => V): Result<U | V, never>;
992
+ /**
993
+ * Returns the or result, when this result is `Err`.
994
+ *
995
+ * Otherwise, returns `Ok` containing the current ok value.
996
+ *
997
+ * @example
998
+ *
999
+ * ```ts
1000
+ * const result = Err("test");
1001
+ * assert.equal(
1002
+ * result.$or(Ok("or-ok")).$unwrap(),
1003
+ * "or-ok",
1004
+ * );
1005
+ * ```
1006
+ *
1007
+ * @example
1008
+ *
1009
+ * ```ts
1010
+ * const result = Err("test");
1011
+ * assert.equal(
1012
+ * result.$or(Err("or-err")).$unwrapErr(),
1013
+ * "or-err",
1014
+ * );
1015
+ * ```
1016
+ *
1017
+ * @example
1018
+ *
1019
+ * ```ts
1020
+ * const result = Ok("test");
1021
+ * assert.equal(
1022
+ * result.$or(Ok("or-ok")).$unwrap(),
1023
+ * "test",
1024
+ * );
1025
+ * ```
1026
+ */
1027
+ $or<U = T, F = E>(this: Result<T, E>, or: ResultLike<U, F>): Result<T | U, F>;
1028
+ /**
1029
+ * Shorthand for `result.$async().$or(...)`
1030
+ */
1031
+ $orAsync<U = T, F = E>(this: Result<T, E>, or: ResultLikeAwaitable<U, F>): ResultAsync<T | U, F>;
1032
+ /**
1033
+ * Returns the result returned by the or function, when this result is `Err`.
1034
+ *
1035
+ * Otherwise, returns `Ok` containing the current ok value.
1036
+ *
1037
+ * @example
1038
+ *
1039
+ * ```ts
1040
+ * const result = Err("test");
1041
+ * assert.equal(
1042
+ * result.$orElse((err) => Ok(`or-ok:${err}`)).$unwrap(),
1043
+ * "or-ok:test",
1044
+ * );
1045
+ * ```
1046
+ *
1047
+ * @example
1048
+ *
1049
+ * ```ts
1050
+ * const result = Err("test");
1051
+ * assert.equal(
1052
+ * result.$orElse((err) => Err(`or-err:${err}`)).$unwrapErr(),
1053
+ * "or-err:test",
1054
+ * );
1055
+ * ```
1056
+ *
1057
+ * @example
1058
+ *
1059
+ * ```ts
1060
+ * const result: Result<string, string> = Ok("test");
1061
+ * assert.equal(
1062
+ * result.$orElse((err) => Ok(`or-ok:${err}`)).$unwrap(),
1063
+ * "test",
1064
+ * );
1065
+ * ```
1066
+ */
1067
+ $orElse<U = T, F = E>(this: Result<T, E>, f: (err: E) => ResultLike<U, F>): Result<T | U, F>;
1068
+ /**
1069
+ * Shorthand for `result.$async().$orElse(...)`
1070
+ */
1071
+ $orElseAsync<U = T, F = E>(this: Result<T, E>, f: (err: E) => ResultLikeAwaitable<U, F>): ResultAsync<T | U, F>;
1072
+ /**
1073
+ * Returns a {@link Result} based on the outcome of the safe function when
1074
+ * this result is `Err`.
1075
+ *
1076
+ * Otherwise, returns `Ok` containing the current ok value.
1077
+ *
1078
+ * Uses the same strategy as {@link Result.$safe}, equivalent to calling
1079
+ * `result.$or(Result.$safe(...))`.
1080
+ */
1081
+ $orSafe<U = T>(this: Result<T, E>, f: (err: E) => U): Result<T | U, Error>;
1082
+ $orSafe<U = T, F = E>(this: Result<T, E>, f: (err: E) => U, mapError: (err: unknown) => F): Result<T | U, F>;
1083
+ /**
1084
+ * Shorthand for `result.$async().$orSafe(...)`
1085
+ */
1086
+ $orSafeAsync<U = T>(this: Result<T, E>, f: (err: E) => U | PromiseLike<U>): ResultAsync<T | U, Error>;
1087
+ $orSafeAsync<U = T, F = E>(this: Result<T, E>, f: (err: E) => U | PromiseLike<U>, mapError: (err: unknown) => F): ResultAsync<T | U, F>;
1088
+ /**
1089
+ * Shorthand for `result.$async().$orSafePromise(...)`
1090
+ */
1091
+ $orSafePromise<U = T>(this: Result<T, E>, promise: PromiseLike<U>): ResultAsync<T | U, Error>;
1092
+ $orSafePromise<U = T, F = E>(this: Result<T, E>, promise: PromiseLike<U>, mapError: (err: unknown) => F): ResultAsync<T | U, F>;
1093
+ /**
1094
+ * Returns the and result, when this result is `Ok`.
1095
+ *
1096
+ * Otherwise, returns `Err` containing the current error value.
1097
+ *
1098
+ * @example
1099
+ *
1100
+ * ```ts
1101
+ * const result = Ok("test");
1102
+ * assert.equal(
1103
+ * result.$and(Ok("and-ok")).$unwrap(),
1104
+ * "and-ok",
1105
+ * );
1106
+ * ```
1107
+ *
1108
+ * @example
1109
+ *
1110
+ * ```ts
1111
+ * const result = Ok("test");
1112
+ * assert.equal(
1113
+ * result.$and(Err("and-err")).$unwrapErr(),
1114
+ * "and-err",
1115
+ * );
1116
+ * ```
1117
+ *
1118
+ * @example
1119
+ *
1120
+ * ```ts
1121
+ * const result = Err("test");
1122
+ * assert.equal(
1123
+ * result.$and(Ok("and-ok")).$unwrapErr(),
1124
+ * "test",
1125
+ * );
1126
+ * ```
1127
+ */
1128
+ $and<U = T, F = E>(this: Result<T, E>, and: ResultLike<U, F>): Result<U, E | F>;
1129
+ /**
1130
+ * Shorthand for `result.$async().$and(...)`
1131
+ */
1132
+ $andAsync<U = T, F = E>(this: Result<T, E>, and: ResultLikeAwaitable<U, F>): ResultAsync<U, E | F>;
1133
+ /**
1134
+ * Returns the and result, when this result is `Ok`.
1135
+ *
1136
+ * Otherwise, returns `Err` containing the current error value.
1137
+ *
1138
+ * @example
1139
+ *
1140
+ * ```ts
1141
+ * const result = Ok("test");
1142
+ * assert.equal(
1143
+ * result.$and((val) => Ok(`and-ok:${val}`)).$unwrap(),
1144
+ * "and-ok:test",
1145
+ * );
1146
+ * ```
1147
+ *
1148
+ * @example
1149
+ *
1150
+ * ```ts
1151
+ * const result = Ok("test");
1152
+ * assert.equal(
1153
+ * result.$and((val) => Err(`and-err:${val}`)).$unwrapErr(),
1154
+ * "and-err:test",
1155
+ * );
1156
+ * ```
1157
+ *
1158
+ * @example
1159
+ *
1160
+ * ```ts
1161
+ * const result: Result<string, string> = Err("test");
1162
+ * assert.equal(
1163
+ * result.$and((val) => Ok(`and-ok:${val}`)).$unwrapErr(),
1164
+ * "test",
1165
+ * );
1166
+ * ```
1167
+ */
1168
+ $andThen<U = T, F = E>(this: Result<T, E>, f: (val: T) => ResultLike<U, F>): Result<U, E | F>;
1169
+ /**
1170
+ * Shorthand for `result.$async().$andThen(...)`
1171
+ */
1172
+ $andThenAsync<U = T, F = E>(this: Result<T, E>, f: (val: T) => ResultLikeAwaitable<U, F>): ResultAsync<U, E | F>;
1173
+ /**
1174
+ * Calls the through function when this result is `Ok` and returns:
1175
+ *
1176
+ * - `Ok` containing the original ok value when the through function
1177
+ * returns `Ok`;
1178
+ * - the `Err` returned by the through function when it returns `Err`.
1179
+ *
1180
+ * Otherwise, returns `Err` containing the current error value.
1181
+ *
1182
+ * @example
1183
+ *
1184
+ * ```ts
1185
+ * const result = Ok("test");
1186
+ * assert.equal(
1187
+ * result.$andThrough((val) => Ok(`ok-through:${val}`)).$unwrap(),
1188
+ * "test",
1189
+ * );
1190
+ * ```
1191
+ *
1192
+ * @example
1193
+ *
1194
+ * ```ts
1195
+ * const result = Ok("test");
1196
+ * assert.equal(
1197
+ * result.$andThrough((val) => Err(`err-through:${val}`)).$unwrapErr(),
1198
+ * "err-through:test",
1199
+ * );
1200
+ * ```
1201
+ *
1202
+ * @example
1203
+ *
1204
+ * ```ts
1205
+ * const result: Result<string, string> = Err("test");
1206
+ * assert.equal(
1207
+ * result.$andThrough((val) => Ok(`ok-through:${val}`)).$unwrapErr(),
1208
+ * "test",
1209
+ * );
1210
+ * ```
1211
+ */
1212
+ $andThrough<F = E>(this: Result<T, E>, f: (val: T) => ResultLike<any, F>): Result<T, E | F>;
1213
+ /**
1214
+ * Shorthand for `result.$async().$andThrough(...)`
1215
+ */
1216
+ $andThroughAsync<F = E>(this: Result<T, E>, f: (val: T) => ResultLikeAwaitable<any, F>): ResultAsync<T, E | F>;
1217
+ /**
1218
+ * Returns a result based on the outcome of the safe function when this
1219
+ * result is `Ok`.
1220
+ *
1221
+ * Otherwise, returns `Err` containing the current error value.
1222
+ *
1223
+ * Uses the same strategy as {@link Result.$safe}, equivalent to calling:
1224
+ *
1225
+ * ```ts
1226
+ * result.$andThen(() => Result.$safe(...))
1227
+ * ```
1228
+ */
1229
+ $andSafe<U = T>(this: Result<T, E>, f: (val: T) => U): Result<U, E | Error>;
1230
+ $andSafe<U = T, F = E>(this: Result<T, E>, f: (val: T) => U, mapError: (err: unknown) => F): Result<U, E | F>;
1231
+ /**
1232
+ * Shorthand for `result.$async().$andSafe(...)`
1233
+ */
1234
+ $andSafeAsync<U = T>(this: Result<T, E>, f: (val: T) => U | PromiseLike<U>): ResultAsync<U, E | Error>;
1235
+ $andSafeAsync<U = T, F = E>(this: Result<T, E>, f: (val: T) => U | PromiseLike<U>, mapError: (err: unknown) => F): ResultAsync<U, E | F>;
1236
+ /**
1237
+ * Shorthand for `result.$async().$andSafePromise(...)`
1238
+ */
1239
+ $andSafePromise<U = T>(this: Result<T, E>, promise: PromiseLike<U>): ResultAsync<U, E | Error>;
1240
+ $andSafePromise<U = T, F = E>(this: Result<T, E>, promise: PromiseLike<U>, mapError: (err: unknown) => F): ResultAsync<U, E | F>;
1241
+ /**
1242
+ * Calls the peek function and returns {@link Result} equivalent to this
1243
+ * result.
1244
+ *
1245
+ * @example
1246
+ *
1247
+ * ```ts
1248
+ * const result: Result<string, string> = Ok("test");
1249
+ * assert.equal(
1250
+ * result
1251
+ * .$peek((res) => {
1252
+ * const [err, value] = res;
1253
+ *
1254
+ * console.log("Err:", err); // Err: undefined
1255
+ * console.log("Value:", value); // Value: test
1256
+ * })
1257
+ * .$unwrap(),
1258
+ * "test",
1259
+ * );
1260
+ * ```
1261
+ *
1262
+ * @example
1263
+ *
1264
+ * ```ts
1265
+ * const result: Result<string, string> = Err("test");
1266
+ * assert.equal(
1267
+ * result
1268
+ * .$peek((res) => {
1269
+ * const [err, value] = res;
1270
+ *
1271
+ * console.log("Err:", err); // Err: test
1272
+ * console.log("Value:", value); // Value: undefined
1273
+ * })
1274
+ * .$unwrapErr(),
1275
+ * "test",
1276
+ * );
1277
+ * ```
264
1278
  */
265
1279
  $peek(this: Result<T, E>, f: (res: Result<T, E>) => void): Result<T, E>;
266
1280
  /**
267
- * @TODO
1281
+ * Calls the tap function when this result is `Ok`, and returns `Ok`
1282
+ * containing the current ok value.
1283
+ *
1284
+ * @example
1285
+ *
1286
+ * ```ts
1287
+ * const result = Ok("test");
1288
+ * assert.equal(
1289
+ * result
1290
+ * .$tap((val) => console.log("Value:", val)) // Value: test
1291
+ * .$unwrap(),
1292
+ * "test",
1293
+ * );
1294
+ * ```
1295
+ *
1296
+ * @example
1297
+ *
1298
+ * ```ts
1299
+ * const result: Record<string, string> = Err("test");
1300
+ * assert.equal(
1301
+ * result
1302
+ * .$tap((val) => console.log("Value:", val)) // not executed
1303
+ * .$unwrapErr(),
1304
+ * "test",
1305
+ * );
1306
+ * ```
268
1307
  */
269
1308
  $tap(this: Result<T, E>, f: (val: T) => any): Result<T, E>;
270
1309
  /**
271
- * @TODO
1310
+ * Calls the tap error function when this result is `Err`, and returns `Err`
1311
+ * containing the current error value.
1312
+ *
1313
+ * @example
1314
+ *
1315
+ * ```ts
1316
+ * const result = Err("test");
1317
+ * assert.equal(
1318
+ * result
1319
+ * .$tapErr((err) => console.log("Err:", err)) // Err: test
1320
+ * .$unwrapErr(),
1321
+ * "test",
1322
+ * );
1323
+ * ```
1324
+ *
1325
+ * @example
1326
+ *
1327
+ * ```ts
1328
+ * const result: Record<string, string> = Ok("test");
1329
+ * assert.equal(
1330
+ * result
1331
+ * .$tapErr((err) => console.log("Err:", err)) // not executed
1332
+ * .$unwrap(),
1333
+ * "test",
1334
+ * );
1335
+ * ```
272
1336
  */
273
1337
  $tapErr(this: Result<T, E>, f: (err: E) => void): Result<T, E>;
274
1338
  /**
275
- * @TODO
1339
+ * Returns the contained {@link Result} when this result is `Ok`.
1340
+ *
1341
+ * Otherwise returns `Err` containing the current error value.
1342
+ *
1343
+ * This method should only be called when the `T` type is `Result`. This
1344
+ * is enforced with a type constraint. If the ok value is not
1345
+ * a result, `RetupleFlattenFailed` is thrown.
1346
+ *
1347
+ * @example
1348
+ *
1349
+ * ```ts
1350
+ * const result = Ok(Ok("test"));
1351
+ * assert.equal(result.$flatten().$unwrap(), "test");
1352
+ * ```
1353
+ *
1354
+ * @example
1355
+ *
1356
+ * ```ts
1357
+ * const result = Ok(Err("test"));
1358
+ * assert.equal(result.$flatten().$unwrapErr(), "test");
1359
+ * ```
1360
+ *
1361
+ * @example
1362
+ *
1363
+ * ```ts
1364
+ * const result = Err("test");
1365
+ * assert.equal(result.$flatten().$unwrapErr(), "test");
1366
+ * ```
276
1367
  */
277
1368
  $flatten<U, F>(this: Result<Result<U, F>, E>): Result<U, E | F>;
278
1369
  /**
279
- * @TODO
1370
+ * Returns an equivalent {@link ResultAsync}.
1371
+ *
1372
+ * @example
1373
+ *
1374
+ * ```ts
1375
+ * const result = Ok("test").$async();
1376
+ * assert.equal(await result.$unwrap(), "test");
1377
+ * ```
1378
+ * @example
1379
+ *
1380
+ * ```ts
1381
+ * const result = Err("test").$async();
1382
+ * assert.equal(await result.$unwrapErr(), "test");
1383
+ * ```
280
1384
  */
281
1385
  $async(this: Result<T, E>): ResultAsync<T, E>;
282
1386
  /**
283
- * @TODO
1387
+ * Returns a `Promise` which resolves to this result.
1388
+ *
1389
+ * @example
1390
+ *
1391
+ * ```ts
1392
+ * const result = Ok("test").$promise();
1393
+ * assert.equal(await result, result);
1394
+ * ```
1395
+ *
1396
+ * @example
1397
+ *
1398
+ * ```ts
1399
+ * const result = Err("test").$promise();
1400
+ * assert.equal(await result, result);
1401
+ * ```
284
1402
  */
285
1403
  $promise(this: Result<T, E>): Promise<Result<T, E>>;
286
1404
  /**
287
- * Mark standard array methods as deprecated, to assist with type hinting.
288
- */
289
- /**
290
- * @deprecated
291
- */
292
- at(...args: unknown[]): unknown;
293
- /**
294
- * @deprecated
295
- */
296
- concat(...args: unknown[]): unknown;
297
- /**
298
- * @deprecated
299
- */
300
- copyWithin(...args: unknown[]): unknown;
301
- /**
302
- * @deprecated
303
- */
304
- entries(...args: unknown[]): unknown;
305
- /**
306
- * @deprecated
307
- */
308
- every(...args: unknown[]): unknown;
309
- /**
310
- * @deprecated
311
- */
312
- fill(...args: unknown[]): unknown;
313
- /**
314
- * @deprecated
315
- */
316
- filter(...args: unknown[]): unknown;
317
- /**
318
- * @deprecated
319
- */
320
- find(...args: unknown[]): unknown;
321
- /**
322
- * @deprecated
323
- */
324
- findIndex(...args: unknown[]): unknown;
325
- /**
326
- * @deprecated
327
- */
328
- flat(...args: unknown[]): unknown;
329
- /**
330
- * @deprecated
331
- */
332
- flatMap(...args: unknown[]): unknown;
333
- /**
334
- * @deprecated
335
- */
336
- forEach(...args: unknown[]): unknown;
337
- /**
338
- * @deprecated
339
- */
340
- includes(...args: unknown[]): unknown;
341
- /**
342
- * @deprecated
343
- */
344
- indexOf(...args: unknown[]): unknown;
345
- /**
346
- * @deprecated
347
- */
348
- join(...args: unknown[]): unknown;
349
- /**
350
- * @deprecated
351
- */
352
- keys(...args: unknown[]): unknown;
353
- /**
354
- * @deprecated
355
- */
356
- lastIndexOf(...args: unknown[]): unknown;
357
- /**
358
- * @deprecated
359
- */
360
- map(...args: unknown[]): unknown;
361
- /**
362
- * @deprecated
363
- */
364
- pop(...args: unknown[]): any;
365
- /**
366
- * @deprecated
367
- */
368
- push(...args: unknown[]): unknown;
369
- /**
370
- * @deprecated
371
- */
372
- reduce(...args: unknown[]): unknown;
373
- /**
374
- * @deprecated
375
- */
376
- reduceRight(...args: unknown[]): unknown;
377
- /**
378
- * @deprecated
379
- */
380
- reverse(...args: unknown[]): unknown;
381
- /**
382
- * @deprecated
383
- */
384
- shift(...args: unknown[]): unknown;
385
- /**
386
- * @deprecated
387
- */
388
- slice(...args: unknown[]): unknown;
389
- /**
390
- * @deprecated
391
- */
392
- some(...args: unknown[]): unknown;
393
- /**
394
- * @deprecated
395
- */
396
- sort(...args: unknown[]): unknown;
397
- /**
398
- * @deprecated
399
- */
400
- splice(...args: unknown[]): unknown;
401
- /**
402
- * @deprecated
403
- */
404
- toString(...args: unknown[]): unknown;
405
- /**
406
- * @deprecated
407
- */
408
- toLocaleString(...args: unknown[]): unknown;
409
- /**
410
- * @deprecated
411
- */
412
- unshift(...args: unknown[]): unknown;
413
- /**
414
- * @deprecated
415
- */
416
- values(...args: unknown[]): unknown;
1405
+ * Returns an `IterableIterator` over the contained ok value, when this
1406
+ * result is `Ok`.
1407
+ *
1408
+ * Otherwise, returns an empty `IterableIterator`.
1409
+ *
1410
+ * This method should only be called when the `T` type is `Iterable`. This
1411
+ * is enforced with a type constraint. If the ok value is not iterable,
1412
+ * attempting to iterate over it will throw the built-in error.
1413
+ *
1414
+ * @example
1415
+ *
1416
+ * ```ts
1417
+ * const result = Ok([1, 2, 3]);
1418
+ *
1419
+ * for (const n of result.$iter()) {
1420
+ * console.log(n); // 1.. 2.. 3
1421
+ * }
1422
+ * ```
1423
+ *
1424
+ * @example
1425
+ *
1426
+ * ```ts
1427
+ * const result = Err([1, 2, 3]);
1428
+ *
1429
+ * for (const n of result.$iter()) {
1430
+ * console.log(n); // not executed, iterator is empty
1431
+ * }
1432
+ * ```
1433
+ *
1434
+ * @example
1435
+ *
1436
+ * ```ts
1437
+ * const result = Ok<any>(1);
1438
+ *
1439
+ * try {
1440
+ * for (const n of result.$iter()) {}
1441
+ * } catch (err) {
1442
+ * // err is 'TypeError: number 1 is not iterable' in V8
1443
+ * }
1444
+ * ```
1445
+ */
1446
+ $iter<U>(this: Result<Iterable<U>, E>): IterableIterator<U, undefined, unknown>;
417
1447
  }
1448
+ type OkTuple<T> = [err: undefined, value: T];
1449
+ type ErrTuple<E> = [err: E, value: undefined];
1450
+ type ResultLikeAwaitable<T, E> = ResultLike<T, E> | PromiseLike<ResultLike<T, E>>;
1451
+ type ObjectUnionOk<T> = {
1452
+ success: true;
1453
+ data: T;
1454
+ error?: never | undefined;
1455
+ };
1456
+ type ObjectUnionErr<E> = {
1457
+ success: false;
1458
+ data?: never | undefined;
1459
+ error: E;
1460
+ };
1461
+ type Truthy<T> = Exclude<T, false | null | undefined | 0 | 0n | "">;
1462
+ type NonZero<N extends number> = N & (`${N}` extends "0" ? never : N);
1463
+ type NonNegativeOrDecimal<N extends number> = N & (`${N}` extends `-${string}` | `${string}.${string}` ? never : N);