retuple 1.0.0-next.23 → 1.0.0-next.25

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.cjs CHANGED
@@ -12,7 +12,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
12
12
  };
13
13
  var _ResultAsync_inner, _a, _ResultRetry_f, _ResultRetry_promise, _ResultRetry_times, _ResultRetry_attempt, _ResultRetry_aborted, _ResultRetry_abort, _ResultRetry_getDelay, _ResultRetry_handler;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.RetupleInvalidUnionError = exports.RetupleCaughtValueError = exports.RetupleExpectFailed = exports.RetupleUnwrapErrFailed = exports.RetupleUnwrapFailed = void 0;
15
+ exports.RetupleCheckFailedError = exports.RetupleInvalidUnionError = exports.RetupleCaughtValueError = exports.RetupleExpectFailed = exports.RetupleUnwrapErrFailed = exports.RetupleUnwrapFailed = void 0;
16
16
  exports.Result = Result;
17
17
  exports.Ok = Ok;
18
18
  exports.Err = Err;
@@ -84,6 +84,19 @@ class RetupleInvalidUnionError extends Error {
84
84
  }
85
85
  }
86
86
  exports.RetupleInvalidUnionError = RetupleInvalidUnionError;
87
+ /**
88
+ * ## Retuple Check Failed Error
89
+ *
90
+ * This error is used as the error type of a `Result` when using $andAssert
91
+ * or $andCheck, when no custom error handler is provided.
92
+ */
93
+ class RetupleCheckFailedError extends Error {
94
+ constructor(value) {
95
+ super("Check failed");
96
+ this.value = value;
97
+ }
98
+ }
99
+ exports.RetupleCheckFailedError = RetupleCheckFailedError;
87
100
  /**
88
101
  * ## Result
89
102
  *
@@ -110,6 +123,8 @@ Result.$any = $any;
110
123
  Result.$anyPromised = $anyPromised;
111
124
  Result.$collect = $collect;
112
125
  Result.$collectPromised = $collectPromised;
126
+ Result.$pipe = $pipe;
127
+ Result.$pipeAsync = $pipeAsync;
113
128
  Object.freeze(Result);
114
129
  function Ok(val) {
115
130
  return new ResultOk(val);
@@ -476,6 +491,38 @@ function $collectPromised(results) {
476
491
  }))).then((values) => resolve(Ok(Object.fromEntries(values))), (err) => resolve(Err(err)));
477
492
  }));
478
493
  }
494
+ function $pipe(f0, ...fnx) {
495
+ const first = asResult(f0());
496
+ if (first instanceof ResultErr) {
497
+ return first;
498
+ }
499
+ let current = first[1];
500
+ for (const fn of fnx) {
501
+ const result = asResult(fn(current));
502
+ if (result instanceof ResultErr) {
503
+ return result;
504
+ }
505
+ current = result[1];
506
+ }
507
+ return Ok(current);
508
+ }
509
+ function $pipeAsync(f0, ...fnx) {
510
+ return new ResultAsync((async () => {
511
+ const first = asResult(await f0());
512
+ if (first instanceof ResultErr) {
513
+ return first;
514
+ }
515
+ let current = first[1];
516
+ for (const fn of fnx) {
517
+ const result = asResult(await fn(current));
518
+ if (result instanceof ResultErr) {
519
+ return result;
520
+ }
521
+ current = result[1];
522
+ }
523
+ return Ok(current);
524
+ })());
525
+ }
479
526
  /**
480
527
  * ## ResultOk
481
528
  *
@@ -532,11 +579,19 @@ class ResultOk extends Array {
532
579
  $mapOrElse(_def, f) {
533
580
  return Ok(f(this[1]));
534
581
  }
535
- $andAssertOr(def, condition = isTruthy) {
536
- return condition(this[1]) ? this : asResult(def);
582
+ $assert(mapError = mapCheckError) {
583
+ return this[1] ? this : Err(mapError(this[1]));
584
+ }
585
+ $check(check, mapError = mapCheckError) {
586
+ return check(this[1]) ? this : Err(mapError(this[1]));
537
587
  }
538
- $andAssertOrElse(def, condition = isTruthy) {
539
- return condition(this[1]) ? this : asResult(def(this[1]));
588
+ $atIndex(index, mapError = mapCheckError) {
589
+ const element = this[1][index];
590
+ return element ? Ok(element) : Err(mapError(this[1]));
591
+ }
592
+ $firstIndex(mapError = mapCheckError) {
593
+ const first = this[1][0];
594
+ return first ? Ok(first) : Err(mapError(this[1]));
540
595
  }
541
596
  $or() {
542
597
  return this;
@@ -592,6 +647,12 @@ class ResultOk extends Array {
592
647
  $andSafePromise(promise, mapError = ensureError) {
593
648
  return this.$async().$andSafePromise(promise, mapError);
594
649
  }
650
+ $andPipe(f0, ...fx) {
651
+ return Result.$pipe(() => f0(this[1]), ...fx);
652
+ }
653
+ $andPipeAsync(f0, ...fx) {
654
+ return Result.$pipeAsync(() => f0(this[1]), ...fx);
655
+ }
595
656
  $peek(f) {
596
657
  f(this);
597
658
  return this;
@@ -675,10 +736,16 @@ class ResultErr extends Array {
675
736
  $mapOrElse(def) {
676
737
  return Ok(def(this[0]));
677
738
  }
678
- $andAssertOr() {
739
+ $assert() {
740
+ return this;
741
+ }
742
+ $check() {
743
+ return this;
744
+ }
745
+ $atIndex() {
679
746
  return this;
680
747
  }
681
- $andAssertOrElse() {
748
+ $firstIndex() {
682
749
  return this;
683
750
  }
684
751
  $or(or) {
@@ -734,6 +801,12 @@ class ResultErr extends Array {
734
801
  $andSafePromise() {
735
802
  return this.$async();
736
803
  }
804
+ $andPipe() {
805
+ return this;
806
+ }
807
+ $andPipeAsync() {
808
+ return this.$async();
809
+ }
737
810
  $peek(f) {
738
811
  f(this);
739
812
  return this;
@@ -849,20 +922,40 @@ class ResultAsync {
849
922
  : new ResultOk(def(res[0]));
850
923
  }));
851
924
  }
852
- $andAssertOr(def, condition = isTruthy) {
925
+ $assert(mapError = mapCheckError) {
853
926
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
854
- if (res instanceof ResultErr || condition(res[1])) {
927
+ if (res instanceof ResultErr) {
855
928
  return res;
856
929
  }
857
- return asResult(await def);
930
+ return res[1]
931
+ ? res
932
+ : Err(mapError(res[1]));
858
933
  }));
859
934
  }
860
- $andAssertOrElse(def, condition = isTruthy) {
935
+ $check(check, mapError = mapCheckError) {
861
936
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
862
- if (res instanceof ResultErr || condition(res[1])) {
937
+ if (res instanceof ResultErr) {
863
938
  return res;
864
939
  }
865
- return asResult(await def(res[1]));
940
+ return check(res[1]) ? res : Err(mapError(res[1]));
941
+ }));
942
+ }
943
+ $atIndex(index, mapError = mapCheckError) {
944
+ return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then((res) => {
945
+ if (res instanceof ResultErr) {
946
+ return res;
947
+ }
948
+ const element = res[1][index];
949
+ return element ? Ok(element) : Err(mapError(res[1]));
950
+ }));
951
+ }
952
+ $firstIndex(mapError = mapCheckError) {
953
+ return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then((res) => {
954
+ if (res instanceof ResultErr) {
955
+ return res;
956
+ }
957
+ const first = res[1][0];
958
+ return first ? Ok(first) : Err(mapError(res[1]));
866
959
  }));
867
960
  }
868
961
  $or(or) {
@@ -956,6 +1049,22 @@ class ResultAsync {
956
1049
  }
957
1050
  }));
958
1051
  }
1052
+ $andPipe(...fx) {
1053
+ return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
1054
+ if (res instanceof ResultErr) {
1055
+ return res;
1056
+ }
1057
+ let current = res[1];
1058
+ for (const f of fx) {
1059
+ const result = asResult(await f(current));
1060
+ if (result instanceof ResultErr) {
1061
+ return result;
1062
+ }
1063
+ current = result[1];
1064
+ }
1065
+ return Ok(current);
1066
+ }));
1067
+ }
959
1068
  /**
960
1069
  * The same as {@link Retuple.$peek|$peek}, except it:
961
1070
  *
@@ -1163,6 +1272,6 @@ function ensureError(err) {
1163
1272
  function mapTrue() {
1164
1273
  return true;
1165
1274
  }
1166
- function isTruthy(val) {
1167
- return !!val;
1275
+ function mapCheckError(value) {
1276
+ return new RetupleCheckFailedError(value);
1168
1277
  }
package/dist/index.d.cts CHANGED
@@ -59,6 +59,16 @@ export declare class RetupleInvalidUnionError extends Error {
59
59
  value: unknown;
60
60
  constructor(value: unknown);
61
61
  }
62
+ /**
63
+ * ## Retuple Check Failed Error
64
+ *
65
+ * This error is used as the error type of a `Result` when using $andAssert
66
+ * or $andCheck, when no custom error handler is provided.
67
+ */
68
+ export declare class RetupleCheckFailedError<const T = unknown> extends Error {
69
+ value: T;
70
+ constructor(value: T);
71
+ }
62
72
  /**
63
73
  * ## Result
64
74
  *
@@ -102,6 +112,24 @@ export declare namespace Result {
102
112
  var $anyPromised: <const TResults extends ResultLikeAwaitable<any, any>[]>(results: TResults) => ResultAsync<AnyOk<TResults>, AnyErr<TResults>>;
103
113
  var $collect: <TResults extends Record<string, ResultLike<any, any>>>(results: TResults) => Result<CollectOk<TResults>, CollectErr<TResults>>;
104
114
  var $collectPromised: <TResults extends Record<string, ResultLikeAwaitable<any, any>>>(results: TResults) => ResultAsync<CollectOk<TResults>, CollectErr<TResults>>;
115
+ var $pipe: {
116
+ <T0, E0, T1, E1>(f0: () => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>): Result<T1, E0 | E1>;
117
+ <T0, E0, T1, E1, T2, E2>(f0: () => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>): Result<T2, E0 | E1 | E2>;
118
+ <T0, E0, T1, E1, T2, E2, T3, E3>(f0: () => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>): Result<T3, E0 | E1 | E2 | E3>;
119
+ <T0, E0, T1, E1, T2, E2, T3, E3, T4, E4>(f0: () => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>, f4: (val3: T3) => ResultLike<T4, E4>): Result<T4, E0 | E1 | E2 | E3 | E4>;
120
+ <T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5>(f0: () => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>, f4: (val3: T3) => ResultLike<T4, E4>, f5: (val4: T4) => ResultLike<T5, E5>): Result<T5, E0 | E1 | E2 | E3 | E4 | E5>;
121
+ <T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6>(f0: () => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>, f4: (val3: T3) => ResultLike<T4, E4>, f5: (val4: T4) => ResultLike<T5, E5>, f6: (val5: T5) => ResultLike<T6, E6>): Result<T6, E0 | E1 | E2 | E3 | E4 | E5 | E6>;
122
+ <T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7>(f0: () => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>, f4: (val3: T3) => ResultLike<T4, E4>, f5: (val4: T4) => ResultLike<T5, E5>, f6: (val5: T5) => ResultLike<T6, E6>, f7: (val6: T6) => ResultLike<T7, E7>): Result<T7, E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7>;
123
+ };
124
+ var $pipeAsync: {
125
+ <T0, E0, T1, E1>(f0: () => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>): ResultAsync<T1, E0 | E1>;
126
+ <T0, E0, T1, E1, T2, E2>(f0: () => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>): ResultAsync<T2, E0 | E1 | E2>;
127
+ <T0, E0, T1, E1, T2, E2, T3, E3>(f0: () => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>): ResultAsync<T3, E0 | E1 | E2 | E3>;
128
+ <T0, E0, T1, E1, T2, E2, T3, E3, T4, E4>(f0: () => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>): ResultAsync<T4, E0 | E1 | E2 | E3 | E4>;
129
+ <T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5>(f0: () => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>): ResultAsync<T5, E0 | E1 | E2 | E3 | E4 | E5>;
130
+ <T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6>(f0: () => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>, f6: (val5: T5) => ResultLikeAwaitable<T6, E6>): ResultAsync<T6, E0 | E1 | E2 | E3 | E4 | E5 | E6>;
131
+ <T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7>(f0: () => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>, f6: (val5: T5) => ResultLikeAwaitable<T6, E6>, f7: (val6: T6) => ResultLikeAwaitable<T7, E7>): ResultAsync<T7, E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7>;
132
+ };
105
133
  }
106
134
  /**
107
135
  * Create a new {@link Result} with the `Ok` variant. When called without
@@ -198,23 +226,31 @@ declare class ResultAsync<T, E> {
198
226
  */
199
227
  $mapOrElse<U, V = U>(this: ResultAsync<T, E>, def: (err: E) => U, f: (val: T) => V): ResultAsync<U | V, never>;
200
228
  /**
201
- * The same as {@link Retuple.$andAssertOr|$andAssertOr}, except it:
202
- *
203
- * - can also accept a `PromiseLike` default value;
204
- * - returns {@link ResultAsync}.
229
+ * The same as {@link Retuple.$check|$andAssert}, except it returns
230
+ * {@link ResultAsync}.
205
231
  */
206
- $andAssertOr<U = T, F = E>(this: ResultAsync<T, E>, def: ResultLikeAwaitable<U, F>): ResultAsync<Truthy<T> | U, E | F>;
207
- $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>;
208
- $andAssertOr<U = T, F = E>(this: ResultAsync<T, E>, def: ResultLikeAwaitable<U, F>, condition: (val: T) => unknown): ResultAsync<T | U, E | F>;
232
+ $assert(this: ResultAsync<T, E>): ResultAsync<Truthy<T>, E | RetupleCheckFailedError<T>>;
233
+ $assert<F = E>(this: ResultAsync<T, E>, mapError: (val: T) => F): ResultAsync<Truthy<T>, E | F>;
209
234
  /**
210
- * The same as {@link Retuple.$andAssertOrElse|$andAssertOrElse}, except it:
211
- *
212
- * - can also accept an `async` default function;
213
- * - returns {@link ResultAsync}.
235
+ * The same as {@link Retuple.$check|$andCheck}, except it returns
236
+ * {@link ResultAsync}.
237
+ */
238
+ $check<U extends T = T>(this: ResultAsync<T, E>, predicate: (val: T) => val is U): ResultAsync<U, E | RetupleCheckFailedError<T>>;
239
+ $check(this: ResultAsync<T, E>, check: (val: T) => unknown): ResultAsync<T, E | RetupleCheckFailedError<T>>;
240
+ $check<U extends T = T, F = E>(this: ResultAsync<T, E>, predicate: (val: T) => val is U, mapError: (val: T) => F): ResultAsync<U, E | F>;
241
+ $check<F = E>(this: ResultAsync<T, E>, check: (val: T) => unknown, mapError: (val: T) => F): ResultAsync<T, E | F>;
242
+ /**
243
+ * The same as {@link Retuple.$atIndex|$atIndex}, except it returns
244
+ * {@link ResultAsync}.
245
+ */
246
+ $atIndex<U>(this: ResultAsync<readonly U[], E>, index: number): ResultAsync<U, E | RetupleCheckFailedError<T>>;
247
+ $atIndex<U, F = E>(this: ResultAsync<readonly U[], E>, index: number, mapError: (val: T) => F): ResultAsync<U, E | F>;
248
+ /**
249
+ * The same as {@link Retuple.$firstIndex|$firstIndex}, except it returns
250
+ * {@link ResultAsync}.
214
251
  */
215
- $andAssertOrElse<U = T, F = E>(this: ResultAsync<T, E>, def: (val: T) => ResultLikeAwaitable<U, F>): ResultAsync<Truthy<T> | U, E | F>;
216
- $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>;
217
- $andAssertOrElse<U = T, F = E>(this: ResultAsync<T, E>, def: (val: T) => ResultLikeAwaitable<U, F>, condition: (val: T) => unknown): ResultAsync<T | U, E | F>;
252
+ $firstIndex<U>(this: ResultAsync<readonly U[], E>): ResultAsync<U, E | RetupleCheckFailedError<T>>;
253
+ $firstIndex<U, F = E>(this: ResultAsync<readonly U[], E>, mapError: (val: T) => F): ResultAsync<U, E | F>;
218
254
  /**
219
255
  * The same as {@link Retuple.$or|$or}, except it:
220
256
  *
@@ -296,6 +332,30 @@ declare class ResultAsync<T, E> {
296
332
  */
297
333
  $andSafePromise<U = T>(this: ResultAsync<T, E>, promise: PromiseLike<U>): ResultAsync<U, E | Error>;
298
334
  $andSafePromise<U = T, F = E>(this: ResultAsync<T, E>, promise: PromiseLike<U>, mapError: (err: unknown) => F): ResultAsync<U, E | F>;
335
+ /**
336
+ * Execute a pipeline starting with the resolved `Ok` value of this result,
337
+ * resolving to the `Ok` of the final function in the pipe or the first
338
+ * `Err` encountered. If you only need to execute a single function, use
339
+ * `$andThen`.
340
+ *
341
+ * Uses the same strategy as {@link Result.$pipeAsync}, equivalent to calling:
342
+ *
343
+ * ```ts
344
+ * resultAsync.$andThen(
345
+ * (val) => Result.$pipeAsync(
346
+ * () => fn1(val),
347
+ * async (val2) => fn2(val2),
348
+ * ),
349
+ * );
350
+ * ```
351
+ */
352
+ $andPipe<T0, E0, T1, E1>(this: ResultAsync<T, E>, f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>): ResultAsync<T1, E0 | E1>;
353
+ $andPipe<T0, E0, T1, E1, T2, E2>(this: ResultAsync<T, E>, f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>): ResultAsync<T2, E0 | E1 | E2>;
354
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3>(this: ResultAsync<T, E>, f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>): ResultAsync<T3, E0 | E1 | E2 | E3>;
355
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4>(this: ResultAsync<T, E>, f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>): ResultAsync<T4, E0 | E1 | E2 | E3 | E4>;
356
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5>(this: ResultAsync<T, E>, f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>): ResultAsync<T5, E0 | E1 | E2 | E3 | E4 | E5>;
357
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6>(this: ResultAsync<T, E>, f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>, f6: (val5: T5) => ResultLikeAwaitable<T6, E6>): ResultAsync<T6, E0 | E1 | E2 | E3 | E4 | E5 | E6>;
358
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7>(this: ResultAsync<T, E>, f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>, f6: (val5: T5) => ResultLikeAwaitable<T6, E6>, f7: (val6: T6) => ResultLikeAwaitable<T7, E7>): ResultAsync<T7, E | E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7>;
299
359
  /**
300
360
  * The same as {@link Retuple.$peek|$peek}, except it:
301
361
  *
@@ -727,164 +787,121 @@ interface Retuple<T, E> extends ResultLike<T, E> {
727
787
  /**
728
788
  * Performs an assertion when this result is `Ok`:
729
789
  *
730
- * - returning `Ok` containing the current ok value when it is truthy, and
731
- * when no predicate/condition function is provided. Narrows the `T` type
732
- * to include only truthy values;
733
- * - returning `Ok` containing the current ok value when a
734
- * predicate/condition function is provided and it returns a truthy value.
735
- * Narrows the `T` type to the predicate type (if any);
736
- * - returning the default result when no predicate/condition function is
737
- * provided and the current ok value is falsey;
738
- * - returning the default result when a predicate/condition function is
739
- * provided and it returns a falsey value.
790
+ * - returning `Ok` containing the current ok value when it is truthy.
791
+ * Narrows the `T` type to include only truthy values;
792
+ * - returning `Err` containing the return value of the map error function
793
+ * when the ok value is falsey;
794
+ * - returning `Err` containing {@link RetupleCheckFailedError} when the
795
+ * ok value is falsey, and when no map error function is provided.
740
796
  *
741
797
  * Otherwise returns `Err` containing the current error value.
742
798
  *
743
799
  * @example
744
800
  *
745
801
  * ```ts
746
- * const result: Result<string | null, string> = Ok("test");
747
- * const asserted = result.$andAssertOr(Ok("ok-default"));
802
+ * const result: Result<string | null, never> = Ok("test");
803
+ * const asserted = result.$andAssert();
748
804
  *
749
- * asserted satisfies Result<string, string>;
805
+ * asserted satisfies Result<string, RetupleCheckFailedError<string | null>>;
750
806
  * assert.equal(asserted.$unwrap(), "test");
751
807
  * ```
752
808
  *
753
809
  * @example
754
810
  *
755
811
  * ```ts
756
- * const result: Result<string | null, string> = Ok("test");
757
- * const asserted = result.$andAssertOr(
758
- * Err("err-default"),
759
- * (val): val is "test" => val === "test",
812
+ * const result: Result<string | null | undefined, never> = Ok(null);
813
+ * const asserted = result.$andAssert(
814
+ * (val) => val === null ? "value was null" : "value was undefined"
760
815
  * );
761
816
  *
762
- * asserted satisfies Result<"test", string>;
763
- * assert.equal(asserted.$unwrap(), "test");
764
- * ```
765
- *
766
- * @example
767
- *
768
- * ```ts
769
- * const result: Result<string | null, string> = Ok(null);
770
- * const asserted = result.$andAssertOr(Ok("ok-default"));
771
- *
772
817
  * asserted satisfies Result<string, string>;
773
- * assert.equal(asserted.$unwrap(), "ok-default");
774
- * ```
775
- *
776
- * @example
777
- *
778
- * ```ts
779
- * const result: Result<string | null, string> = Ok("value");
780
- * const asserted = result.$andAssertOr(
781
- * Err("err-default"),
782
- * (val): val is "test" => val === "test",
783
- * );
784
- *
785
- * asserted satisfies Result<"test", string>;
786
- * assert.equal(asserted.$unwrapErr(), "err-default");
787
- * ```
788
- *
789
- * @example
790
- *
791
- * ```ts
792
- * const result: Result<string | null, string> = Err("test");
793
- * const asserted = result.$andAssertOr(
794
- * Err("err-default"),
795
- * (val): val is "test" => val === "test",
796
- * );
797
- *
798
- * asserted satisfies Result<"test", string>;
799
- * assert.equal(asserted.$unwrapErr(), "test");
818
+ * assert.equal(asserted.$unwrapErr(), "value was null");
800
819
  * ```
801
820
  */
802
- $andAssertOr<U = T, F = E>(this: Result<T, E>, def: ResultLike<U, F>): Result<Truthy<T> | U, E | F>;
803
- $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>;
804
- $andAssertOr<U = T, F = E>(this: Result<T, E>, def: ResultLike<U, F>, condition: (val: T) => unknown): Result<T | U, E | F>;
821
+ $assert(this: Result<T, E>): Result<Truthy<T>, E | RetupleCheckFailedError<T>>;
822
+ $assert<F = E>(this: Result<T, E>, mapError: (val: T) => F): Result<Truthy<T>, E | F>;
805
823
  /**
806
- * Performs an assertion when this result is `Ok`:
824
+ * Performs a check when this result is `Ok`:
807
825
  *
808
- * - returning `Ok` containing the current ok value when it is truthy, and
809
- * when no predicate/condition function is provided. Narrows the `T` type
810
- * to include only truthy values;
811
- * - returning `Ok` containing the current ok value when a
812
- * predicate/condition function is provided and it returns a truthy value.
813
- * Narrows the `T` type to the predicate type (if any);
814
- * - returning the result returned by the default function when no
815
- * predicate/condition function is provided and the current ok value is
816
- * falsey;
817
- * - returning the result returned by the default function when a
818
- * predicate/condition function is provided and it returns a falsey value.
826
+ * - returning `Ok` containing the current ok value when the predicate/check
827
+ * function returns true. Narrows the `T` type based on the check function;
828
+ * - returning `Err` containing the return value of the map error function
829
+ * when the ok value fails the check;
830
+ * - returning `Err` containing {@link RetupleCheckFailedError} when the
831
+ * ok value fails the check, and when no map error function is provided.
819
832
  *
820
833
  * Otherwise returns `Err` containing the current error value.
821
834
  *
822
835
  * @example
823
836
  *
824
837
  * ```ts
825
- * const result: Result<string | null, string> = Ok("test");
826
- * const asserted = result.$andAssertOrElse(
827
- * (val) => Ok(`ok-default:${val}`),
828
- * );
838
+ * const result: Result<string, never> = Ok("test");
839
+ * const asserted = result.$andCheck((val) => val === "test");
829
840
  *
830
- * asserted satisfies Result<string, string>;
841
+ * asserted satisfies Result<string, RetupleCheckFailedError<string>>;
831
842
  * assert.equal(asserted.$unwrap(), "test");
832
843
  * ```
833
844
  *
834
845
  * @example
835
846
  *
836
847
  * ```ts
837
- * const result: Result<string | null, string> = Ok("test");
838
- * const asserted = result.$andAssertOrElse(
839
- * (val) => Err(`err-default:${val}`),
840
- * (val): val is "test" => val === "test",
848
+ * const result: Result<string, never> = Ok("test");
849
+ * const checked = result.$andCheck(
850
+ * (val) => val === "value",
851
+ * (val) => `value was ${val}`,
841
852
  * );
842
853
  *
843
- * asserted satisfies Result<"test", string>;
844
- * assert.equal(asserted.$unwrap(), "test");
854
+ * checked satisfies Result<"value", string>;
855
+ * assert.equal(checked.$unwrapErr(), "value was test");
845
856
  * ```
857
+ */
858
+ $check<U extends T = T>(this: Result<T, E>, predicate: (val: T) => val is U): Result<U, E | RetupleCheckFailedError<T>>;
859
+ $check(this: Result<T, E>, check: (val: T) => unknown): Result<T, E | RetupleCheckFailedError<T>>;
860
+ $check<U extends T = T, F = E>(this: Result<T, E>, predicate: (val: T) => val is U, mapError: (val: T) => F): Result<U, E | F>;
861
+ $check<F = E>(this: Result<T, E>, check: (val: T) => unknown, mapError: (val: T) => F): Result<T, E | F>;
862
+ /**
863
+ * Checks the specified element of the contained array when when this result
864
+ * is `Ok`:
846
865
  *
847
- * @example
848
- *
849
- * ```ts
850
- * const result: Result<string | null, string> = Ok(null);
851
- * const asserted = result.$andAssertOrElse(
852
- * (val) => Ok(`ok-default:${val}`),
853
- * );
866
+ * - returning `Ok` containing the specified element when it is truthy.
867
+ * Narrows the type to include only truthy values;
868
+ * - returning `Err` containing the return value of the map error function
869
+ * when the first array element fails the check;
870
+ * - returning `Err` containing {@link RetupleCheckFailedError} when the
871
+ * first array elemnt fails the check, and when no map error function is
872
+ * provided.
854
873
  *
855
- * asserted satisfies Result<string, string>;
856
- * assert.equal(asserted.$unwrap(), "ok-default:null");
857
- * ```
874
+ * Otherwise returns `Err` containing the current error value.
858
875
  *
859
876
  * @example
860
877
  *
861
878
  * ```ts
862
- * const result: Result<string | null, string> = Ok("value");
863
- * const asserted = result.$andAssertOrElse(
864
- * (val) => Err(`err-default:${val}`),
865
- * (val): val is "test" => val === "test",
866
- * );
879
+ * const result: Result<(string | null)[], never> = Ok(["test", null]);
880
+ * const first = result.$andFirst();
867
881
  *
868
- * asserted satisfies Result<"test", string>;
869
- * assert.equal(asserted.$unwrapErr(), "err-default:value");
882
+ * first satisfies Result<string, RetupleCheckFailedError<string | null>>;
883
+ * assert.equal(first.$unwrap(), "test");
870
884
  * ```
871
885
  *
872
886
  * @example
873
887
  *
874
888
  * ```ts
875
- * const result: Result<string | null, string> = Err("test");
876
- * const asserted = result.$andAssertOrElse(
877
- * (val) => Err(`err-default:${val}`),
878
- * (val): val is "test" => val === "test",
889
+ * const result: Result<(string | null | undefined)[], never> = Ok([null, "test"]);
890
+ * const first = result.$andFirst(
891
+ * (val) => val === null ? "value was null" : "value was undefined",
879
892
  * );
880
893
  *
881
- * asserted satisfies Result<"test", string>;
882
- * assert.equal(asserted.$unwrapErr(), "test");
894
+ * first satisfies Result<string, string>;
895
+ * assert.equal(first.$unwrapErr(), "value was null");
883
896
  * ```
884
897
  */
885
- $andAssertOrElse<U = T, F = E>(this: Result<T, E>, def: (val: T) => ResultLike<U, F>): Result<Truthy<T> | U, E | F>;
886
- $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>;
887
- $andAssertOrElse<U = T, F = E>(this: Result<T, E>, def: (val: T) => ResultLike<U, F>, condition: (val: T) => unknown): Result<T | U, E | F>;
898
+ $atIndex<U>(this: Result<readonly U[], E>, index: number): Result<Truthy<U>, E | RetupleCheckFailedError<T>>;
899
+ $atIndex<U, F = E>(this: Result<readonly U[], E>, index: number, mapError: (val: T) => F): Result<Truthy<U>, E | F>;
900
+ /**
901
+ * Equivalent to calling `result.$atIndex(0)`.
902
+ */
903
+ $firstIndex<U>(this: Result<readonly U[], E>): Result<Truthy<U>, E | RetupleCheckFailedError<T>>;
904
+ $firstIndex<U, F = E>(this: Result<readonly U[], E>, mapError: (val: T) => F): Result<Truthy<U>, E | F>;
888
905
  /**
889
906
  * Returns `Ok` containing the return value of the map function when this
890
907
  * result is `Ok`.
@@ -911,10 +928,10 @@ interface Retuple<T, E> extends ResultLike<T, E> {
911
928
  * );
912
929
  * ```
913
930
  */
914
- $map<U>(this: Result<T, E>, f: (value: T) => U): Result<U, E>;
931
+ $map<U>(this: Result<T, E>, f: (val: T) => U): Result<U, E>;
915
932
  /**
916
- * Returns `Err` containing the return value of the map function when this
917
- * result is `Err`.
933
+ * Returns `Err` containing the return value of the map error function
934
+ * when this result is `Err`.
918
935
  *
919
936
  * Otherwise, returns `Ok` containing the current ok value.
920
937
  *
@@ -1249,6 +1266,41 @@ interface Retuple<T, E> extends ResultLike<T, E> {
1249
1266
  */
1250
1267
  $andSafePromise<U = T>(this: Result<T, E>, promise: PromiseLike<U>): ResultAsync<U, E | Error>;
1251
1268
  $andSafePromise<U = T, F = E>(this: Result<T, E>, promise: PromiseLike<U>, mapError: (err: unknown) => F): ResultAsync<U, E | F>;
1269
+ /**
1270
+ * Execute a pipeline starting with the `Ok` value of this result, returning
1271
+ * the `Ok` of the final function in the pipe or the first `Err` encountered.
1272
+ * If you only need to execute a single function, use `$andThen`
1273
+ *
1274
+ * Uses the same strategy as {@link Result.$pipe}, equivalent to calling:
1275
+ *
1276
+ * ```ts
1277
+ * result.$andThen(
1278
+ * (val) => Result.$pipe(
1279
+ * () => fn1(val),
1280
+ * (val2) => fn2(val2),
1281
+ * ),
1282
+ * );
1283
+ * ```
1284
+ */
1285
+ $andPipe<T0, E0, T1, E1>(this: ResultLike<T, E>, f0: (val: T) => ResultLike<T0, E0>, f1: (val: T0) => ResultLike<T1, E1>): Result<T1, E | E0 | E1>;
1286
+ $andPipe<T0, E0, T1, E1, T2, E2>(f0: (val: T) => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>): Result<T2, E | E0 | E1 | E2>;
1287
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3>(f0: (val: T) => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>): Result<T3, E | E0 | E1 | E2 | E3>;
1288
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4>(f0: (val: T) => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>, f4: (val3: T3) => ResultLike<T4, E4>): Result<T4, E | E0 | E1 | E2 | E3 | E4>;
1289
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5>(f0: (val: T) => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>, f4: (val3: T3) => ResultLike<T4, E4>, f5: (val4: T4) => ResultLike<T5, E5>): Result<T5, E | E0 | E1 | E2 | E3 | E4 | E5>;
1290
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6>(f0: (val: T) => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>, f4: (val3: T3) => ResultLike<T4, E4>, f5: (val4: T4) => ResultLike<T5, E5>, f6: (val5: T5) => ResultLike<T6, E6>): Result<T6, E | E0 | E1 | E2 | E3 | E4 | E5 | E6>;
1291
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7>(f0: (val: T) => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>, f4: (val3: T3) => ResultLike<T4, E4>, f5: (val4: T4) => ResultLike<T5, E5>, f6: (val5: T5) => ResultLike<T6, E6>, f7: (val6: T6) => ResultLike<T7, E7>): Result<T7, E | E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7>;
1292
+ /**
1293
+ * Shorthand for `result.$async().$andPipe(...)`
1294
+ *
1295
+ * If you only need to execute a single function, use `$andThenAsync`
1296
+ */
1297
+ $andPipeAsync<T0, E0, T1, E1>(f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>): ResultAsync<T1, E0 | E1>;
1298
+ $andPipeAsync<T0, E0, T1, E1, T2, E2>(f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>): ResultAsync<T2, E0 | E1 | E2>;
1299
+ $andPipeAsync<T0, E0, T1, E1, T2, E2, T3, E3>(f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>): ResultAsync<T3, E0 | E1 | E2 | E3>;
1300
+ $andPipeAsync<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4>(f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>): ResultAsync<T4, E0 | E1 | E2 | E3 | E4>;
1301
+ $andPipeAsync<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5>(f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>): ResultAsync<T5, E0 | E1 | E2 | E3 | E4 | E5>;
1302
+ $andPipeAsync<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6>(f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>, f6: (val5: T5) => ResultLikeAwaitable<T6, E6>): ResultAsync<T6, E0 | E1 | E2 | E3 | E4 | E5 | E6>;
1303
+ $andPipeAsync<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7>(f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>, f6: (val5: T5) => ResultLikeAwaitable<T6, E6>, f7: (val6: T6) => ResultLikeAwaitable<T7, E7>): ResultAsync<T7, E | E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7>;
1252
1304
  /**
1253
1305
  * Calls the peek function and returns {@link Result} equivalent to this
1254
1306
  * result.
@@ -1351,10 +1403,6 @@ interface Retuple<T, E> extends ResultLike<T, E> {
1351
1403
  *
1352
1404
  * Otherwise returns `Err` containing the current error value.
1353
1405
  *
1354
- * This method should only be called when the `T` type is `Result`. This
1355
- * is enforced with a type constraint. If the ok value is not
1356
- * a result, `RetupleFlattenFailed` is thrown.
1357
- *
1358
1406
  * @example
1359
1407
  *
1360
1408
  * ```ts
package/dist/index.d.ts CHANGED
@@ -59,6 +59,16 @@ export declare class RetupleInvalidUnionError extends Error {
59
59
  value: unknown;
60
60
  constructor(value: unknown);
61
61
  }
62
+ /**
63
+ * ## Retuple Check Failed Error
64
+ *
65
+ * This error is used as the error type of a `Result` when using $andAssert
66
+ * or $andCheck, when no custom error handler is provided.
67
+ */
68
+ export declare class RetupleCheckFailedError<const T = unknown> extends Error {
69
+ value: T;
70
+ constructor(value: T);
71
+ }
62
72
  /**
63
73
  * ## Result
64
74
  *
@@ -102,6 +112,24 @@ export declare namespace Result {
102
112
  var $anyPromised: <const TResults extends ResultLikeAwaitable<any, any>[]>(results: TResults) => ResultAsync<AnyOk<TResults>, AnyErr<TResults>>;
103
113
  var $collect: <TResults extends Record<string, ResultLike<any, any>>>(results: TResults) => Result<CollectOk<TResults>, CollectErr<TResults>>;
104
114
  var $collectPromised: <TResults extends Record<string, ResultLikeAwaitable<any, any>>>(results: TResults) => ResultAsync<CollectOk<TResults>, CollectErr<TResults>>;
115
+ var $pipe: {
116
+ <T0, E0, T1, E1>(f0: () => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>): Result<T1, E0 | E1>;
117
+ <T0, E0, T1, E1, T2, E2>(f0: () => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>): Result<T2, E0 | E1 | E2>;
118
+ <T0, E0, T1, E1, T2, E2, T3, E3>(f0: () => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>): Result<T3, E0 | E1 | E2 | E3>;
119
+ <T0, E0, T1, E1, T2, E2, T3, E3, T4, E4>(f0: () => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>, f4: (val3: T3) => ResultLike<T4, E4>): Result<T4, E0 | E1 | E2 | E3 | E4>;
120
+ <T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5>(f0: () => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>, f4: (val3: T3) => ResultLike<T4, E4>, f5: (val4: T4) => ResultLike<T5, E5>): Result<T5, E0 | E1 | E2 | E3 | E4 | E5>;
121
+ <T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6>(f0: () => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>, f4: (val3: T3) => ResultLike<T4, E4>, f5: (val4: T4) => ResultLike<T5, E5>, f6: (val5: T5) => ResultLike<T6, E6>): Result<T6, E0 | E1 | E2 | E3 | E4 | E5 | E6>;
122
+ <T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7>(f0: () => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>, f4: (val3: T3) => ResultLike<T4, E4>, f5: (val4: T4) => ResultLike<T5, E5>, f6: (val5: T5) => ResultLike<T6, E6>, f7: (val6: T6) => ResultLike<T7, E7>): Result<T7, E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7>;
123
+ };
124
+ var $pipeAsync: {
125
+ <T0, E0, T1, E1>(f0: () => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>): ResultAsync<T1, E0 | E1>;
126
+ <T0, E0, T1, E1, T2, E2>(f0: () => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>): ResultAsync<T2, E0 | E1 | E2>;
127
+ <T0, E0, T1, E1, T2, E2, T3, E3>(f0: () => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>): ResultAsync<T3, E0 | E1 | E2 | E3>;
128
+ <T0, E0, T1, E1, T2, E2, T3, E3, T4, E4>(f0: () => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>): ResultAsync<T4, E0 | E1 | E2 | E3 | E4>;
129
+ <T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5>(f0: () => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>): ResultAsync<T5, E0 | E1 | E2 | E3 | E4 | E5>;
130
+ <T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6>(f0: () => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>, f6: (val5: T5) => ResultLikeAwaitable<T6, E6>): ResultAsync<T6, E0 | E1 | E2 | E3 | E4 | E5 | E6>;
131
+ <T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7>(f0: () => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>, f6: (val5: T5) => ResultLikeAwaitable<T6, E6>, f7: (val6: T6) => ResultLikeAwaitable<T7, E7>): ResultAsync<T7, E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7>;
132
+ };
105
133
  }
106
134
  /**
107
135
  * Create a new {@link Result} with the `Ok` variant. When called without
@@ -198,23 +226,31 @@ declare class ResultAsync<T, E> {
198
226
  */
199
227
  $mapOrElse<U, V = U>(this: ResultAsync<T, E>, def: (err: E) => U, f: (val: T) => V): ResultAsync<U | V, never>;
200
228
  /**
201
- * The same as {@link Retuple.$andAssertOr|$andAssertOr}, except it:
202
- *
203
- * - can also accept a `PromiseLike` default value;
204
- * - returns {@link ResultAsync}.
229
+ * The same as {@link Retuple.$check|$andAssert}, except it returns
230
+ * {@link ResultAsync}.
205
231
  */
206
- $andAssertOr<U = T, F = E>(this: ResultAsync<T, E>, def: ResultLikeAwaitable<U, F>): ResultAsync<Truthy<T> | U, E | F>;
207
- $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>;
208
- $andAssertOr<U = T, F = E>(this: ResultAsync<T, E>, def: ResultLikeAwaitable<U, F>, condition: (val: T) => unknown): ResultAsync<T | U, E | F>;
232
+ $assert(this: ResultAsync<T, E>): ResultAsync<Truthy<T>, E | RetupleCheckFailedError<T>>;
233
+ $assert<F = E>(this: ResultAsync<T, E>, mapError: (val: T) => F): ResultAsync<Truthy<T>, E | F>;
209
234
  /**
210
- * The same as {@link Retuple.$andAssertOrElse|$andAssertOrElse}, except it:
211
- *
212
- * - can also accept an `async` default function;
213
- * - returns {@link ResultAsync}.
235
+ * The same as {@link Retuple.$check|$andCheck}, except it returns
236
+ * {@link ResultAsync}.
237
+ */
238
+ $check<U extends T = T>(this: ResultAsync<T, E>, predicate: (val: T) => val is U): ResultAsync<U, E | RetupleCheckFailedError<T>>;
239
+ $check(this: ResultAsync<T, E>, check: (val: T) => unknown): ResultAsync<T, E | RetupleCheckFailedError<T>>;
240
+ $check<U extends T = T, F = E>(this: ResultAsync<T, E>, predicate: (val: T) => val is U, mapError: (val: T) => F): ResultAsync<U, E | F>;
241
+ $check<F = E>(this: ResultAsync<T, E>, check: (val: T) => unknown, mapError: (val: T) => F): ResultAsync<T, E | F>;
242
+ /**
243
+ * The same as {@link Retuple.$atIndex|$atIndex}, except it returns
244
+ * {@link ResultAsync}.
245
+ */
246
+ $atIndex<U>(this: ResultAsync<readonly U[], E>, index: number): ResultAsync<U, E | RetupleCheckFailedError<T>>;
247
+ $atIndex<U, F = E>(this: ResultAsync<readonly U[], E>, index: number, mapError: (val: T) => F): ResultAsync<U, E | F>;
248
+ /**
249
+ * The same as {@link Retuple.$firstIndex|$firstIndex}, except it returns
250
+ * {@link ResultAsync}.
214
251
  */
215
- $andAssertOrElse<U = T, F = E>(this: ResultAsync<T, E>, def: (val: T) => ResultLikeAwaitable<U, F>): ResultAsync<Truthy<T> | U, E | F>;
216
- $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>;
217
- $andAssertOrElse<U = T, F = E>(this: ResultAsync<T, E>, def: (val: T) => ResultLikeAwaitable<U, F>, condition: (val: T) => unknown): ResultAsync<T | U, E | F>;
252
+ $firstIndex<U>(this: ResultAsync<readonly U[], E>): ResultAsync<U, E | RetupleCheckFailedError<T>>;
253
+ $firstIndex<U, F = E>(this: ResultAsync<readonly U[], E>, mapError: (val: T) => F): ResultAsync<U, E | F>;
218
254
  /**
219
255
  * The same as {@link Retuple.$or|$or}, except it:
220
256
  *
@@ -296,6 +332,30 @@ declare class ResultAsync<T, E> {
296
332
  */
297
333
  $andSafePromise<U = T>(this: ResultAsync<T, E>, promise: PromiseLike<U>): ResultAsync<U, E | Error>;
298
334
  $andSafePromise<U = T, F = E>(this: ResultAsync<T, E>, promise: PromiseLike<U>, mapError: (err: unknown) => F): ResultAsync<U, E | F>;
335
+ /**
336
+ * Execute a pipeline starting with the resolved `Ok` value of this result,
337
+ * resolving to the `Ok` of the final function in the pipe or the first
338
+ * `Err` encountered. If you only need to execute a single function, use
339
+ * `$andThen`.
340
+ *
341
+ * Uses the same strategy as {@link Result.$pipeAsync}, equivalent to calling:
342
+ *
343
+ * ```ts
344
+ * resultAsync.$andThen(
345
+ * (val) => Result.$pipeAsync(
346
+ * () => fn1(val),
347
+ * async (val2) => fn2(val2),
348
+ * ),
349
+ * );
350
+ * ```
351
+ */
352
+ $andPipe<T0, E0, T1, E1>(this: ResultAsync<T, E>, f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>): ResultAsync<T1, E0 | E1>;
353
+ $andPipe<T0, E0, T1, E1, T2, E2>(this: ResultAsync<T, E>, f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>): ResultAsync<T2, E0 | E1 | E2>;
354
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3>(this: ResultAsync<T, E>, f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>): ResultAsync<T3, E0 | E1 | E2 | E3>;
355
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4>(this: ResultAsync<T, E>, f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>): ResultAsync<T4, E0 | E1 | E2 | E3 | E4>;
356
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5>(this: ResultAsync<T, E>, f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>): ResultAsync<T5, E0 | E1 | E2 | E3 | E4 | E5>;
357
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6>(this: ResultAsync<T, E>, f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>, f6: (val5: T5) => ResultLikeAwaitable<T6, E6>): ResultAsync<T6, E0 | E1 | E2 | E3 | E4 | E5 | E6>;
358
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7>(this: ResultAsync<T, E>, f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>, f6: (val5: T5) => ResultLikeAwaitable<T6, E6>, f7: (val6: T6) => ResultLikeAwaitable<T7, E7>): ResultAsync<T7, E | E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7>;
299
359
  /**
300
360
  * The same as {@link Retuple.$peek|$peek}, except it:
301
361
  *
@@ -727,164 +787,121 @@ interface Retuple<T, E> extends ResultLike<T, E> {
727
787
  /**
728
788
  * Performs an assertion when this result is `Ok`:
729
789
  *
730
- * - returning `Ok` containing the current ok value when it is truthy, and
731
- * when no predicate/condition function is provided. Narrows the `T` type
732
- * to include only truthy values;
733
- * - returning `Ok` containing the current ok value when a
734
- * predicate/condition function is provided and it returns a truthy value.
735
- * Narrows the `T` type to the predicate type (if any);
736
- * - returning the default result when no predicate/condition function is
737
- * provided and the current ok value is falsey;
738
- * - returning the default result when a predicate/condition function is
739
- * provided and it returns a falsey value.
790
+ * - returning `Ok` containing the current ok value when it is truthy.
791
+ * Narrows the `T` type to include only truthy values;
792
+ * - returning `Err` containing the return value of the map error function
793
+ * when the ok value is falsey;
794
+ * - returning `Err` containing {@link RetupleCheckFailedError} when the
795
+ * ok value is falsey, and when no map error function is provided.
740
796
  *
741
797
  * Otherwise returns `Err` containing the current error value.
742
798
  *
743
799
  * @example
744
800
  *
745
801
  * ```ts
746
- * const result: Result<string | null, string> = Ok("test");
747
- * const asserted = result.$andAssertOr(Ok("ok-default"));
802
+ * const result: Result<string | null, never> = Ok("test");
803
+ * const asserted = result.$andAssert();
748
804
  *
749
- * asserted satisfies Result<string, string>;
805
+ * asserted satisfies Result<string, RetupleCheckFailedError<string | null>>;
750
806
  * assert.equal(asserted.$unwrap(), "test");
751
807
  * ```
752
808
  *
753
809
  * @example
754
810
  *
755
811
  * ```ts
756
- * const result: Result<string | null, string> = Ok("test");
757
- * const asserted = result.$andAssertOr(
758
- * Err("err-default"),
759
- * (val): val is "test" => val === "test",
812
+ * const result: Result<string | null | undefined, never> = Ok(null);
813
+ * const asserted = result.$andAssert(
814
+ * (val) => val === null ? "value was null" : "value was undefined"
760
815
  * );
761
816
  *
762
- * asserted satisfies Result<"test", string>;
763
- * assert.equal(asserted.$unwrap(), "test");
764
- * ```
765
- *
766
- * @example
767
- *
768
- * ```ts
769
- * const result: Result<string | null, string> = Ok(null);
770
- * const asserted = result.$andAssertOr(Ok("ok-default"));
771
- *
772
817
  * asserted satisfies Result<string, string>;
773
- * assert.equal(asserted.$unwrap(), "ok-default");
774
- * ```
775
- *
776
- * @example
777
- *
778
- * ```ts
779
- * const result: Result<string | null, string> = Ok("value");
780
- * const asserted = result.$andAssertOr(
781
- * Err("err-default"),
782
- * (val): val is "test" => val === "test",
783
- * );
784
- *
785
- * asserted satisfies Result<"test", string>;
786
- * assert.equal(asserted.$unwrapErr(), "err-default");
787
- * ```
788
- *
789
- * @example
790
- *
791
- * ```ts
792
- * const result: Result<string | null, string> = Err("test");
793
- * const asserted = result.$andAssertOr(
794
- * Err("err-default"),
795
- * (val): val is "test" => val === "test",
796
- * );
797
- *
798
- * asserted satisfies Result<"test", string>;
799
- * assert.equal(asserted.$unwrapErr(), "test");
818
+ * assert.equal(asserted.$unwrapErr(), "value was null");
800
819
  * ```
801
820
  */
802
- $andAssertOr<U = T, F = E>(this: Result<T, E>, def: ResultLike<U, F>): Result<Truthy<T> | U, E | F>;
803
- $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>;
804
- $andAssertOr<U = T, F = E>(this: Result<T, E>, def: ResultLike<U, F>, condition: (val: T) => unknown): Result<T | U, E | F>;
821
+ $assert(this: Result<T, E>): Result<Truthy<T>, E | RetupleCheckFailedError<T>>;
822
+ $assert<F = E>(this: Result<T, E>, mapError: (val: T) => F): Result<Truthy<T>, E | F>;
805
823
  /**
806
- * Performs an assertion when this result is `Ok`:
824
+ * Performs a check when this result is `Ok`:
807
825
  *
808
- * - returning `Ok` containing the current ok value when it is truthy, and
809
- * when no predicate/condition function is provided. Narrows the `T` type
810
- * to include only truthy values;
811
- * - returning `Ok` containing the current ok value when a
812
- * predicate/condition function is provided and it returns a truthy value.
813
- * Narrows the `T` type to the predicate type (if any);
814
- * - returning the result returned by the default function when no
815
- * predicate/condition function is provided and the current ok value is
816
- * falsey;
817
- * - returning the result returned by the default function when a
818
- * predicate/condition function is provided and it returns a falsey value.
826
+ * - returning `Ok` containing the current ok value when the predicate/check
827
+ * function returns true. Narrows the `T` type based on the check function;
828
+ * - returning `Err` containing the return value of the map error function
829
+ * when the ok value fails the check;
830
+ * - returning `Err` containing {@link RetupleCheckFailedError} when the
831
+ * ok value fails the check, and when no map error function is provided.
819
832
  *
820
833
  * Otherwise returns `Err` containing the current error value.
821
834
  *
822
835
  * @example
823
836
  *
824
837
  * ```ts
825
- * const result: Result<string | null, string> = Ok("test");
826
- * const asserted = result.$andAssertOrElse(
827
- * (val) => Ok(`ok-default:${val}`),
828
- * );
838
+ * const result: Result<string, never> = Ok("test");
839
+ * const asserted = result.$andCheck((val) => val === "test");
829
840
  *
830
- * asserted satisfies Result<string, string>;
841
+ * asserted satisfies Result<string, RetupleCheckFailedError<string>>;
831
842
  * assert.equal(asserted.$unwrap(), "test");
832
843
  * ```
833
844
  *
834
845
  * @example
835
846
  *
836
847
  * ```ts
837
- * const result: Result<string | null, string> = Ok("test");
838
- * const asserted = result.$andAssertOrElse(
839
- * (val) => Err(`err-default:${val}`),
840
- * (val): val is "test" => val === "test",
848
+ * const result: Result<string, never> = Ok("test");
849
+ * const checked = result.$andCheck(
850
+ * (val) => val === "value",
851
+ * (val) => `value was ${val}`,
841
852
  * );
842
853
  *
843
- * asserted satisfies Result<"test", string>;
844
- * assert.equal(asserted.$unwrap(), "test");
854
+ * checked satisfies Result<"value", string>;
855
+ * assert.equal(checked.$unwrapErr(), "value was test");
845
856
  * ```
857
+ */
858
+ $check<U extends T = T>(this: Result<T, E>, predicate: (val: T) => val is U): Result<U, E | RetupleCheckFailedError<T>>;
859
+ $check(this: Result<T, E>, check: (val: T) => unknown): Result<T, E | RetupleCheckFailedError<T>>;
860
+ $check<U extends T = T, F = E>(this: Result<T, E>, predicate: (val: T) => val is U, mapError: (val: T) => F): Result<U, E | F>;
861
+ $check<F = E>(this: Result<T, E>, check: (val: T) => unknown, mapError: (val: T) => F): Result<T, E | F>;
862
+ /**
863
+ * Checks the specified element of the contained array when when this result
864
+ * is `Ok`:
846
865
  *
847
- * @example
848
- *
849
- * ```ts
850
- * const result: Result<string | null, string> = Ok(null);
851
- * const asserted = result.$andAssertOrElse(
852
- * (val) => Ok(`ok-default:${val}`),
853
- * );
866
+ * - returning `Ok` containing the specified element when it is truthy.
867
+ * Narrows the type to include only truthy values;
868
+ * - returning `Err` containing the return value of the map error function
869
+ * when the first array element fails the check;
870
+ * - returning `Err` containing {@link RetupleCheckFailedError} when the
871
+ * first array elemnt fails the check, and when no map error function is
872
+ * provided.
854
873
  *
855
- * asserted satisfies Result<string, string>;
856
- * assert.equal(asserted.$unwrap(), "ok-default:null");
857
- * ```
874
+ * Otherwise returns `Err` containing the current error value.
858
875
  *
859
876
  * @example
860
877
  *
861
878
  * ```ts
862
- * const result: Result<string | null, string> = Ok("value");
863
- * const asserted = result.$andAssertOrElse(
864
- * (val) => Err(`err-default:${val}`),
865
- * (val): val is "test" => val === "test",
866
- * );
879
+ * const result: Result<(string | null)[], never> = Ok(["test", null]);
880
+ * const first = result.$andFirst();
867
881
  *
868
- * asserted satisfies Result<"test", string>;
869
- * assert.equal(asserted.$unwrapErr(), "err-default:value");
882
+ * first satisfies Result<string, RetupleCheckFailedError<string | null>>;
883
+ * assert.equal(first.$unwrap(), "test");
870
884
  * ```
871
885
  *
872
886
  * @example
873
887
  *
874
888
  * ```ts
875
- * const result: Result<string | null, string> = Err("test");
876
- * const asserted = result.$andAssertOrElse(
877
- * (val) => Err(`err-default:${val}`),
878
- * (val): val is "test" => val === "test",
889
+ * const result: Result<(string | null | undefined)[], never> = Ok([null, "test"]);
890
+ * const first = result.$andFirst(
891
+ * (val) => val === null ? "value was null" : "value was undefined",
879
892
  * );
880
893
  *
881
- * asserted satisfies Result<"test", string>;
882
- * assert.equal(asserted.$unwrapErr(), "test");
894
+ * first satisfies Result<string, string>;
895
+ * assert.equal(first.$unwrapErr(), "value was null");
883
896
  * ```
884
897
  */
885
- $andAssertOrElse<U = T, F = E>(this: Result<T, E>, def: (val: T) => ResultLike<U, F>): Result<Truthy<T> | U, E | F>;
886
- $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>;
887
- $andAssertOrElse<U = T, F = E>(this: Result<T, E>, def: (val: T) => ResultLike<U, F>, condition: (val: T) => unknown): Result<T | U, E | F>;
898
+ $atIndex<U>(this: Result<readonly U[], E>, index: number): Result<Truthy<U>, E | RetupleCheckFailedError<T>>;
899
+ $atIndex<U, F = E>(this: Result<readonly U[], E>, index: number, mapError: (val: T) => F): Result<Truthy<U>, E | F>;
900
+ /**
901
+ * Equivalent to calling `result.$atIndex(0)`.
902
+ */
903
+ $firstIndex<U>(this: Result<readonly U[], E>): Result<Truthy<U>, E | RetupleCheckFailedError<T>>;
904
+ $firstIndex<U, F = E>(this: Result<readonly U[], E>, mapError: (val: T) => F): Result<Truthy<U>, E | F>;
888
905
  /**
889
906
  * Returns `Ok` containing the return value of the map function when this
890
907
  * result is `Ok`.
@@ -911,10 +928,10 @@ interface Retuple<T, E> extends ResultLike<T, E> {
911
928
  * );
912
929
  * ```
913
930
  */
914
- $map<U>(this: Result<T, E>, f: (value: T) => U): Result<U, E>;
931
+ $map<U>(this: Result<T, E>, f: (val: T) => U): Result<U, E>;
915
932
  /**
916
- * Returns `Err` containing the return value of the map function when this
917
- * result is `Err`.
933
+ * Returns `Err` containing the return value of the map error function
934
+ * when this result is `Err`.
918
935
  *
919
936
  * Otherwise, returns `Ok` containing the current ok value.
920
937
  *
@@ -1249,6 +1266,41 @@ interface Retuple<T, E> extends ResultLike<T, E> {
1249
1266
  */
1250
1267
  $andSafePromise<U = T>(this: Result<T, E>, promise: PromiseLike<U>): ResultAsync<U, E | Error>;
1251
1268
  $andSafePromise<U = T, F = E>(this: Result<T, E>, promise: PromiseLike<U>, mapError: (err: unknown) => F): ResultAsync<U, E | F>;
1269
+ /**
1270
+ * Execute a pipeline starting with the `Ok` value of this result, returning
1271
+ * the `Ok` of the final function in the pipe or the first `Err` encountered.
1272
+ * If you only need to execute a single function, use `$andThen`
1273
+ *
1274
+ * Uses the same strategy as {@link Result.$pipe}, equivalent to calling:
1275
+ *
1276
+ * ```ts
1277
+ * result.$andThen(
1278
+ * (val) => Result.$pipe(
1279
+ * () => fn1(val),
1280
+ * (val2) => fn2(val2),
1281
+ * ),
1282
+ * );
1283
+ * ```
1284
+ */
1285
+ $andPipe<T0, E0, T1, E1>(this: ResultLike<T, E>, f0: (val: T) => ResultLike<T0, E0>, f1: (val: T0) => ResultLike<T1, E1>): Result<T1, E | E0 | E1>;
1286
+ $andPipe<T0, E0, T1, E1, T2, E2>(f0: (val: T) => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>): Result<T2, E | E0 | E1 | E2>;
1287
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3>(f0: (val: T) => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>): Result<T3, E | E0 | E1 | E2 | E3>;
1288
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4>(f0: (val: T) => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>, f4: (val3: T3) => ResultLike<T4, E4>): Result<T4, E | E0 | E1 | E2 | E3 | E4>;
1289
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5>(f0: (val: T) => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>, f4: (val3: T3) => ResultLike<T4, E4>, f5: (val4: T4) => ResultLike<T5, E5>): Result<T5, E | E0 | E1 | E2 | E3 | E4 | E5>;
1290
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6>(f0: (val: T) => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>, f4: (val3: T3) => ResultLike<T4, E4>, f5: (val4: T4) => ResultLike<T5, E5>, f6: (val5: T5) => ResultLike<T6, E6>): Result<T6, E | E0 | E1 | E2 | E3 | E4 | E5 | E6>;
1291
+ $andPipe<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7>(f0: (val: T) => ResultLike<T0, E0>, f1: (val0: T0) => ResultLike<T1, E1>, f2: (val1: T1) => ResultLike<T2, E2>, f3: (val2: T2) => ResultLike<T3, E3>, f4: (val3: T3) => ResultLike<T4, E4>, f5: (val4: T4) => ResultLike<T5, E5>, f6: (val5: T5) => ResultLike<T6, E6>, f7: (val6: T6) => ResultLike<T7, E7>): Result<T7, E | E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7>;
1292
+ /**
1293
+ * Shorthand for `result.$async().$andPipe(...)`
1294
+ *
1295
+ * If you only need to execute a single function, use `$andThenAsync`
1296
+ */
1297
+ $andPipeAsync<T0, E0, T1, E1>(f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>): ResultAsync<T1, E0 | E1>;
1298
+ $andPipeAsync<T0, E0, T1, E1, T2, E2>(f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>): ResultAsync<T2, E0 | E1 | E2>;
1299
+ $andPipeAsync<T0, E0, T1, E1, T2, E2, T3, E3>(f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>): ResultAsync<T3, E0 | E1 | E2 | E3>;
1300
+ $andPipeAsync<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4>(f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>): ResultAsync<T4, E0 | E1 | E2 | E3 | E4>;
1301
+ $andPipeAsync<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5>(f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>): ResultAsync<T5, E0 | E1 | E2 | E3 | E4 | E5>;
1302
+ $andPipeAsync<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6>(f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>, f6: (val5: T5) => ResultLikeAwaitable<T6, E6>): ResultAsync<T6, E0 | E1 | E2 | E3 | E4 | E5 | E6>;
1303
+ $andPipeAsync<T0, E0, T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7>(f0: (val: T) => ResultLikeAwaitable<T0, E0>, f1: (val0: T0) => ResultLikeAwaitable<T1, E1>, f2: (val1: T1) => ResultLikeAwaitable<T2, E2>, f3: (val2: T2) => ResultLikeAwaitable<T3, E3>, f4: (val3: T3) => ResultLikeAwaitable<T4, E4>, f5: (val4: T4) => ResultLikeAwaitable<T5, E5>, f6: (val5: T5) => ResultLikeAwaitable<T6, E6>, f7: (val6: T6) => ResultLikeAwaitable<T7, E7>): ResultAsync<T7, E | E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7>;
1252
1304
  /**
1253
1305
  * Calls the peek function and returns {@link Result} equivalent to this
1254
1306
  * result.
@@ -1351,10 +1403,6 @@ interface Retuple<T, E> extends ResultLike<T, E> {
1351
1403
  *
1352
1404
  * Otherwise returns `Err` containing the current error value.
1353
1405
  *
1354
- * This method should only be called when the `T` type is `Result`. This
1355
- * is enforced with a type constraint. If the ok value is not
1356
- * a result, `RetupleFlattenFailed` is thrown.
1357
- *
1358
1406
  * @example
1359
1407
  *
1360
1408
  * ```ts
package/dist/index.js CHANGED
@@ -73,6 +73,18 @@ export class RetupleInvalidUnionError extends Error {
73
73
  this.value = value;
74
74
  }
75
75
  }
76
+ /**
77
+ * ## Retuple Check Failed Error
78
+ *
79
+ * This error is used as the error type of a `Result` when using $andAssert
80
+ * or $andCheck, when no custom error handler is provided.
81
+ */
82
+ export class RetupleCheckFailedError extends Error {
83
+ constructor(value) {
84
+ super("Check failed");
85
+ this.value = value;
86
+ }
87
+ }
76
88
  /**
77
89
  * ## Result
78
90
  *
@@ -99,6 +111,8 @@ Result.$any = $any;
99
111
  Result.$anyPromised = $anyPromised;
100
112
  Result.$collect = $collect;
101
113
  Result.$collectPromised = $collectPromised;
114
+ Result.$pipe = $pipe;
115
+ Result.$pipeAsync = $pipeAsync;
102
116
  Object.freeze(Result);
103
117
  export function Ok(val) {
104
118
  return new ResultOk(val);
@@ -465,6 +479,38 @@ function $collectPromised(results) {
465
479
  }))).then((values) => resolve(Ok(Object.fromEntries(values))), (err) => resolve(Err(err)));
466
480
  }));
467
481
  }
482
+ function $pipe(f0, ...fnx) {
483
+ const first = asResult(f0());
484
+ if (first instanceof ResultErr) {
485
+ return first;
486
+ }
487
+ let current = first[1];
488
+ for (const fn of fnx) {
489
+ const result = asResult(fn(current));
490
+ if (result instanceof ResultErr) {
491
+ return result;
492
+ }
493
+ current = result[1];
494
+ }
495
+ return Ok(current);
496
+ }
497
+ function $pipeAsync(f0, ...fnx) {
498
+ return new ResultAsync((async () => {
499
+ const first = asResult(await f0());
500
+ if (first instanceof ResultErr) {
501
+ return first;
502
+ }
503
+ let current = first[1];
504
+ for (const fn of fnx) {
505
+ const result = asResult(await fn(current));
506
+ if (result instanceof ResultErr) {
507
+ return result;
508
+ }
509
+ current = result[1];
510
+ }
511
+ return Ok(current);
512
+ })());
513
+ }
468
514
  /**
469
515
  * ## ResultOk
470
516
  *
@@ -521,11 +567,19 @@ class ResultOk extends Array {
521
567
  $mapOrElse(_def, f) {
522
568
  return Ok(f(this[1]));
523
569
  }
524
- $andAssertOr(def, condition = isTruthy) {
525
- return condition(this[1]) ? this : asResult(def);
570
+ $assert(mapError = mapCheckError) {
571
+ return this[1] ? this : Err(mapError(this[1]));
572
+ }
573
+ $check(check, mapError = mapCheckError) {
574
+ return check(this[1]) ? this : Err(mapError(this[1]));
526
575
  }
527
- $andAssertOrElse(def, condition = isTruthy) {
528
- return condition(this[1]) ? this : asResult(def(this[1]));
576
+ $atIndex(index, mapError = mapCheckError) {
577
+ const element = this[1][index];
578
+ return element ? Ok(element) : Err(mapError(this[1]));
579
+ }
580
+ $firstIndex(mapError = mapCheckError) {
581
+ const first = this[1][0];
582
+ return first ? Ok(first) : Err(mapError(this[1]));
529
583
  }
530
584
  $or() {
531
585
  return this;
@@ -581,6 +635,12 @@ class ResultOk extends Array {
581
635
  $andSafePromise(promise, mapError = ensureError) {
582
636
  return this.$async().$andSafePromise(promise, mapError);
583
637
  }
638
+ $andPipe(f0, ...fx) {
639
+ return Result.$pipe(() => f0(this[1]), ...fx);
640
+ }
641
+ $andPipeAsync(f0, ...fx) {
642
+ return Result.$pipeAsync(() => f0(this[1]), ...fx);
643
+ }
584
644
  $peek(f) {
585
645
  f(this);
586
646
  return this;
@@ -664,10 +724,16 @@ class ResultErr extends Array {
664
724
  $mapOrElse(def) {
665
725
  return Ok(def(this[0]));
666
726
  }
667
- $andAssertOr() {
727
+ $assert() {
728
+ return this;
729
+ }
730
+ $check() {
731
+ return this;
732
+ }
733
+ $atIndex() {
668
734
  return this;
669
735
  }
670
- $andAssertOrElse() {
736
+ $firstIndex() {
671
737
  return this;
672
738
  }
673
739
  $or(or) {
@@ -723,6 +789,12 @@ class ResultErr extends Array {
723
789
  $andSafePromise() {
724
790
  return this.$async();
725
791
  }
792
+ $andPipe() {
793
+ return this;
794
+ }
795
+ $andPipeAsync() {
796
+ return this.$async();
797
+ }
726
798
  $peek(f) {
727
799
  f(this);
728
800
  return this;
@@ -838,20 +910,40 @@ class ResultAsync {
838
910
  : new ResultOk(def(res[0]));
839
911
  }));
840
912
  }
841
- $andAssertOr(def, condition = isTruthy) {
913
+ $assert(mapError = mapCheckError) {
842
914
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
843
- if (res instanceof ResultErr || condition(res[1])) {
915
+ if (res instanceof ResultErr) {
844
916
  return res;
845
917
  }
846
- return asResult(await def);
918
+ return res[1]
919
+ ? res
920
+ : Err(mapError(res[1]));
847
921
  }));
848
922
  }
849
- $andAssertOrElse(def, condition = isTruthy) {
923
+ $check(check, mapError = mapCheckError) {
850
924
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
851
- if (res instanceof ResultErr || condition(res[1])) {
925
+ if (res instanceof ResultErr) {
852
926
  return res;
853
927
  }
854
- return asResult(await def(res[1]));
928
+ return check(res[1]) ? res : Err(mapError(res[1]));
929
+ }));
930
+ }
931
+ $atIndex(index, mapError = mapCheckError) {
932
+ return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then((res) => {
933
+ if (res instanceof ResultErr) {
934
+ return res;
935
+ }
936
+ const element = res[1][index];
937
+ return element ? Ok(element) : Err(mapError(res[1]));
938
+ }));
939
+ }
940
+ $firstIndex(mapError = mapCheckError) {
941
+ return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then((res) => {
942
+ if (res instanceof ResultErr) {
943
+ return res;
944
+ }
945
+ const first = res[1][0];
946
+ return first ? Ok(first) : Err(mapError(res[1]));
855
947
  }));
856
948
  }
857
949
  $or(or) {
@@ -945,6 +1037,22 @@ class ResultAsync {
945
1037
  }
946
1038
  }));
947
1039
  }
1040
+ $andPipe(...fx) {
1041
+ return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
1042
+ if (res instanceof ResultErr) {
1043
+ return res;
1044
+ }
1045
+ let current = res[1];
1046
+ for (const f of fx) {
1047
+ const result = asResult(await f(current));
1048
+ if (result instanceof ResultErr) {
1049
+ return result;
1050
+ }
1051
+ current = result[1];
1052
+ }
1053
+ return Ok(current);
1054
+ }));
1055
+ }
948
1056
  /**
949
1057
  * The same as {@link Retuple.$peek|$peek}, except it:
950
1058
  *
@@ -1152,6 +1260,6 @@ function ensureError(err) {
1152
1260
  function mapTrue() {
1153
1261
  return true;
1154
1262
  }
1155
- function isTruthy(val) {
1156
- return !!val;
1263
+ function mapCheckError(value) {
1264
+ return new RetupleCheckFailedError(value);
1157
1265
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "retuple",
3
- "version": "1.0.0-next.23",
3
+ "version": "1.0.0-next.25",
4
4
  "scripts": {
5
5
  "test": "vitest",
6
6
  "lint": "eslint . --ext .ts -c eslint.config.mjs --fix",