t-tasks 1.2.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/either.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * Either data type specialization representing a correct value
5
5
  *
6
6
  * @template R underlying value type
7
- * @template L underlying error type (needed for type merging, in fact alwas considered to be never)
7
+ * @template L underlying error type (needed for type merging, in fact always considered to be never)
8
8
  */
9
9
  export interface Right<R, L> {
10
10
  readonly right: R;
@@ -64,6 +64,7 @@ export interface Right<R, L> {
64
64
  * Applied to 'right value' returns self without invoking transformer
65
65
  * Applied to 'left error' returns 'right op(error)'
66
66
  *
67
+ * @template R2 transformer function's return type
67
68
  * @param op transformer to be invoked with underlying error
68
69
  * @returns 'right value' or 'right op(error)'
69
70
  */
@@ -72,6 +73,23 @@ export interface Right<R, L> {
72
73
  // General case
73
74
  orMap<R2>(this: Either<R, L>, op: (error: L) => R2): Right<R | R2, never>;
74
75
 
76
+ /**
77
+ * Either pattern matching extractor function
78
+ *
79
+ * Applied to 'right value' returns op.right(value)
80
+ * Applied to 'left error' returns op.left(error)
81
+ *
82
+ * @template R2 right extractor function's return type
83
+ * @template R3 left extractor function's return type
84
+ * @param op.right extractor to be invoked with underlying value in case of 'right'
85
+ * @param op.left extractor to be invoked with underlying error in case of 'left'
86
+ * @returns op.right(value) or op.left(error)
87
+ */
88
+ // Right case
89
+ match<R2, R3 = R2>(this: Right<R, L>, op: { right: (value: R) => R2; left: (error: L) => R3 }): R2;
90
+ // General case
91
+ match<R2, R3 = R2>(this: Either<R, L>, op: { right: (value: R) => R2; left: (error: L) => R3 }): R2 | R3;
92
+
75
93
  /**
76
94
  * Either pattern matching transformer function
77
95
  *
@@ -110,14 +128,14 @@ export interface Right<R, L> {
110
128
  chain<R2, L2>(this: Either<R, L>, op: (value: R) => Either<R2, L2>): Either<R2, L | L2>;
111
129
 
112
130
  /**
113
- * Either composition function
131
+ * Either fallback composition function
114
132
  *
115
133
  * Applied to 'right value' returns self without invoking composition function
116
134
  * Applied to 'left error' returns 'op(error)'
117
135
  *
118
136
  * @template R2 transformer function result's underlying value type
119
137
  * @template L2 transformer function result's underlying error type
120
- * @param op transformer to be invoked with underlying value
138
+ * @param op transformer to be invoked with underlying error
121
139
  * @returns 'right value' or 'op(error)'
122
140
  */
123
141
  // Right cases
@@ -141,7 +159,7 @@ export interface Right<R, L> {
141
159
  * @template L3 left transformer function result's underlying error type
142
160
  * @param op.right transformer to be invoked with underlying value in case of 'right'
143
161
  * @param op.left transformer to be invoked with underlying error in case of 'left'
144
- * @returns 'op(value)' or 'op(error)'
162
+ * @returns 'op.right(value)' or 'op.left(error)'
145
163
  */
146
164
  // Right cases
147
165
  matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: L) => Right<R3, L3> }): Right<R2, never>;
@@ -193,13 +211,13 @@ export interface Right<R, L> {
193
211
  isLeft(): this is Left<R, L>;
194
212
 
195
213
  /**
196
- * Wrap Maybe to singleton generator
214
+ * Wrap Either to singleton generator
197
215
  *
198
- * Userful in order to avoid ambiguous yied types
216
+ * Useful in order to avoid ambiguous yield types
199
217
  *
200
- * @returns generator of Maybe wrapping this
218
+ * @returns generator of Either wrapping this
201
219
  */
202
- generator: EitherGeneratorFunction<[], R, Right<R, L>, R>
220
+ generator: EitherGeneratorFunction<[], R, Right<R, L>, R>
203
221
  }
204
222
 
205
223
  /**
@@ -207,7 +225,7 @@ export interface Right<R, L> {
207
225
  *
208
226
  * Either data type specialization representing an erroneous value
209
227
  *
210
- * @remplate R underlying value type (needed for type merging, in fact alwas considered to be never)
228
+ * @template R underlying value type (needed for type merging, in fact always considered to be never)
211
229
  * @template L underlying error type
212
230
  */
213
231
  export interface Left<R, L> {
@@ -230,7 +248,7 @@ export interface Left<R, L> {
230
248
  * Applied to 'right value' returns self without invoking callback
231
249
  * Applied to 'left error' returns self invoking op(error) in process
232
250
  *
233
- * @param op function to be invoked with underlying value
251
+ * @param op function to be invoked with underlying error
234
252
  * @returns self
235
253
  */
236
254
  orTap(op: (error: L) => void): this;
@@ -268,6 +286,7 @@ export interface Left<R, L> {
268
286
  * Applied to 'right value' returns self without invoking transformer
269
287
  * Applied to 'left error' returns 'right op(error)'
270
288
  *
289
+ * @template R2 transformer function's return type
271
290
  * @param op transformer to be invoked with underlying error
272
291
  * @returns 'right value' or 'right op(error)'
273
292
  */
@@ -276,6 +295,23 @@ export interface Left<R, L> {
276
295
  // General case
277
296
  orMap<R2>(this: Either<R, L>, op: (error: L) => R2): Right<R | R2, never>;
278
297
 
298
+ /**
299
+ * Either pattern matching extractor function
300
+ *
301
+ * Applied to 'right value' returns op.right(value)
302
+ * Applied to 'left error' returns op.left(error)
303
+ *
304
+ * @template R2 right extractor function's return type
305
+ * @template R3 left extractor function's return type
306
+ * @param op.right extractor to be invoked with underlying value in case of 'right'
307
+ * @param op.left extractor to be invoked with underlying error in case of 'left'
308
+ * @returns op.right(value) or op.left(error)
309
+ */
310
+ // Left case
311
+ match<R2, R3 = R2>(this: Left<R, L>, op: { right: (value: R) => R2; left: (error: L) => R3 }): R3;
312
+ // General case
313
+ match<R2, R3 = R2>(this: Either<R, L>, op: { right: (value: R) => R2; left: (error: L) => R3 }): R2 | R3;
314
+
279
315
  /**
280
316
  * Either pattern matching transformer function
281
317
  *
@@ -304,7 +340,7 @@ export interface Left<R, L> {
304
340
  * @param op transformer to be invoked with underlying value
305
341
  * @returns 'op(value)' or 'left error'
306
342
  */
307
- // Right cases
343
+ // Left cases
308
344
  chain<R2, L2>(this: Left<R, L>, op: (value: R) => Right<R2, L2>): Left<never, L>;
309
345
  chain<R2, L2>(this: Left<R, L>, op: (value: R) => Left<R2, L2>): Left<never, L>;
310
346
  chain<R2, L2>(this: Left<R, L>, op: (value: R) => Either<R2, L2>): Left<never, L>;
@@ -321,7 +357,7 @@ export interface Left<R, L> {
321
357
  *
322
358
  * @template R2 transformer function result's underlying value type
323
359
  * @template L2 transformer function result's underlying error type
324
- * @param op transformer to be invoked with underlying value
360
+ * @param op transformer to be invoked with underlying error
325
361
  * @returns 'right value' or 'op(error)'
326
362
  */
327
363
  // Left cases
@@ -345,7 +381,7 @@ export interface Left<R, L> {
345
381
  * @template L3 left transformer function result's underlying error type
346
382
  * @param op.right transformer to be invoked with underlying value in case of 'right'
347
383
  * @param op.left transformer to be invoked with underlying error in case of 'left'
348
- * @returns 'op(value)' or 'op(error)'
384
+ * @returns 'op.right(value)' or 'op.left(error)'
349
385
  */
350
386
  // Left cases
351
387
  matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: L) => Right<R3, L3> }): Right<R3, never>;
@@ -397,19 +433,19 @@ export interface Left<R, L> {
397
433
  isLeft(): this is Left<R, L>;
398
434
 
399
435
  /**
400
- * Wrap Maybe to singleton generator
436
+ * Wrap Either to singleton generator
401
437
  *
402
- * Userful in order to avoid ambiguous yied types
438
+ * Useful in order to avoid ambiguous yield types
403
439
  *
404
- * @returns generator of Maybe wrapping this
440
+ * @returns generator of Either wrapping this
405
441
  */
406
- generator: EitherGeneratorFunction<[], R, Left<R, L>, R>
442
+ generator: EitherGeneratorFunction<[], R, Left<R, L>, R>
407
443
  }
408
444
 
409
445
  /**
410
446
  * Either data type: either Right value of type R or Left value of type L
411
447
  *
412
- * As per classic Either monad implementation can eithr contain a right (correct) value or a left (erroneous) value
448
+ * As per classic Either monad implementation can either contain a right (correct) value or a left (erroneous) value
413
449
  * Used throughout the library to represent the result of failable operations, namely failed tasks
414
450
  *
415
451
  * @template R underlying value type
@@ -421,7 +457,7 @@ export namespace Right {
421
457
  /**
422
458
  * Standalone Right value extractor
423
459
  *
424
- * Userful for passing as a function to collection transformers
460
+ * Useful for passing as a function to collection transformers
425
461
  *
426
462
  * @template R underlying value type
427
463
  * @template L underlying error type
@@ -437,7 +473,7 @@ export namespace Left {
437
473
  /**
438
474
  * Standalone Left error extractor
439
475
  *
440
- * Userful for passing as a function to collection transformers
476
+ * Useful for passing as a function to collection transformers
441
477
  *
442
478
  * @template R underlying value type
443
479
  * @template L underlying error type
@@ -449,7 +485,23 @@ export namespace Left {
449
485
  }
450
486
  }
451
487
 
488
+ /**
489
+ * Either generator
490
+ *
491
+ * @template T yielded underlying type
492
+ * @template TT yielded Either type
493
+ * @template R returned underlying type
494
+ */
452
495
  export type EitherGenerator<T, TT extends Either<T, any>, R> = Generator<TT, R, T>;
496
+
497
+ /**
498
+ * Function returning Either generator (generator function)
499
+ *
500
+ * @template A argument types
501
+ * @template T yielded underlying type
502
+ * @template TT yielded Either type
503
+ * @template R returned underlying type
504
+ */
453
505
  export type EitherGeneratorFunction<A extends unknown[], T, TT extends Either<T, any>, R> = (...args: A) => EitherGenerator<T, TT, R>;
454
506
 
455
507
  export namespace Either {
@@ -480,6 +532,8 @@ export namespace Either {
480
532
  *
481
533
  * Resolves to 'left error' in case of undefined value and 'right value' otherwise
482
534
  *
535
+ * @template R underlying value type
536
+ * @template L underlying error type
483
537
  * @param value possibly undefined value
484
538
  * @param error error to use in case of undefined value
485
539
  * @returns either 'right value' or 'left error'
@@ -496,8 +550,10 @@ export namespace Either {
496
550
  *
497
551
  * Resolves to 'left error' in case of undefined or null value and 'right value' otherwise
498
552
  *
499
- * @param value possibly undefined or nullable value
500
- * @param error error to use in case of undefined or nullable value
553
+ * @template R underlying value type
554
+ * @template L underlying error type
555
+ * @param value possibly undefined or null value
556
+ * @param error error to use in case of undefined or null value
501
557
  * @returns either 'right value' or 'left error'
502
558
  */
503
559
  export function fromNullable<L>(value: undefined, error: L): Left<never, L>;
@@ -508,12 +564,33 @@ export namespace Either {
508
564
  return Either.fromOptional(value, error).chain((v) => (v !== null ? Either.right(value) : Either.left(error)));
509
565
  }
510
566
 
567
+ /**
568
+ * Standalone Either value extractor
569
+ *
570
+ * Applied to 'right value' returns underlying value without using fallback
571
+ * Applied to 'left error' returns fallback
572
+ *
573
+ * @template R underlying value type
574
+ * @template L underlying error type
575
+ * @template R2 fallback value type
576
+ * @param either Either instance
577
+ * @param fallback value to be returned in case of 'left error'
578
+ * @returns underlying value or fallback
579
+ */
580
+ export function fromEither<R, L>(either: Right<R, L>, fallback: unknown): R;
581
+ export function fromEither<R, L, R2>(either: Left<R, L>, fallback: R2): R2;
582
+ export function fromEither<R, L, R2>(either: Either<R, L>, fallback: R2): R | R2;
583
+ export function fromEither<R, L, R2>(either: Either<R, L>, fallback: R2) {
584
+ return either.match({ right: (value) => value, left: () => fallback });
585
+ }
586
+
511
587
  /**
512
588
  * Standalone type guard for 'right'
513
589
  *
514
- * Userful for passing as a predicate to collection transformers
590
+ * Useful for passing as a predicate to collection transformers
515
591
  *
516
592
  * @template R underlying value type
593
+ * @template L underlying error type
517
594
  * @param either Either instance
518
595
  * @returns 'true' in case argument is 'right value' (and resolves type to be 'right')
519
596
  */
@@ -524,9 +601,10 @@ export namespace Either {
524
601
  /**
525
602
  * Standalone type guard for 'left'
526
603
  *
527
- * Userful for passing as a predicate to collection transformers
604
+ * Useful for passing as a predicate to collection transformers
528
605
  *
529
606
  * @template R underlying value type
607
+ * @template L underlying error type
530
608
  * @param either Either instance
531
609
  * @returns 'true' in case argument is 'left error' (and resolves type to be 'left')
532
610
  */
@@ -537,6 +615,8 @@ export namespace Either {
537
615
  /**
538
616
  * Standalone list predicate
539
617
  *
618
+ * @template R underlying value type
619
+ * @template L underlying error type
540
620
  * @param eithers a list of Either
541
621
  * @returns true in case every list element is Right
542
622
  */
@@ -547,6 +627,8 @@ export namespace Either {
547
627
  /**
548
628
  * Standalone list predicate
549
629
  *
630
+ * @template R underlying value type
631
+ * @template L underlying error type
550
632
  * @param eithers a list of Either
551
633
  * @returns true in case at least one list element is Right
552
634
  */
@@ -557,6 +639,8 @@ export namespace Either {
557
639
  /**
558
640
  * Standalone list predicate
559
641
  *
642
+ * @template R underlying value type
643
+ * @template L underlying error type
560
644
  * @param eithers a list of Either
561
645
  * @returns true in case every list element is Left
562
646
  */
@@ -567,6 +651,8 @@ export namespace Either {
567
651
  /**
568
652
  * Standalone list predicate
569
653
  *
654
+ * @template R underlying value type
655
+ * @template L underlying error type
570
656
  * @param eithers a list of Either
571
657
  * @returns true in case at least one list element is Left
572
658
  */
@@ -577,30 +663,28 @@ export namespace Either {
577
663
  /**
578
664
  * Create compound Either from generator function
579
665
  *
580
- * Applying yield to a Maybe within the generator function unwraps the Maybe and returns underlying value in case of success
581
- * However the convinient option for typescript is to use ```yield* maybe.generator()``` as othervise one may have to deal with union types
666
+ * Applying yield to an Either within the generator function unwraps the Either and returns underlying value in case of success
667
+ * However the convenient option for typescript is to use ```yield* either.generator()``` as otherwise one may have to deal with union types
582
668
  *
583
- * @template TT yielded Maybe type
669
+ * @template T yielded underlying type
670
+ * @template TT yielded Either type
584
671
  * @template R returned underlying type
585
- * @param maybeGeneratorFunction Maybe generator function
586
- * @returns Just wrapping the result of generator function or Nothing
587
- * ```
672
+ * @param eitherGeneratorFunction Either generator function
673
+ * @returns Right wrapping the result of generator function or Left
588
674
  */
589
675
  export function generate<T, TT extends Either<T, any>, R>(eitherGeneratorFunction: EitherGeneratorFunction<[], T, TT, R>): Either<R, any> {
590
676
  const generator = eitherGeneratorFunction();
677
+ let next = generator.next();
591
678
 
592
- const sequentor = (next: IteratorResult<TT, R>): Either<R, any> => {
593
- return next.done ? (
594
- Either.right(next.value)
595
- ) : (
596
- next.value.matchChain<R, any>({
597
- right: (value) => sequentor(generator.next(value)),
598
- left: Either.left,
599
- })
600
- );
601
- };
679
+ while (!next.done) {
680
+ if (next.value.isLeft()) {
681
+ return Either.left(next.value.left);
682
+ }
602
683
 
603
- return Either.right(undefined).chain(() => sequentor(generator.next()));
684
+ next = generator.next(next.value.right);
685
+ }
686
+
687
+ return Either.right(next.value);
604
688
  }
605
689
  }
606
690
 
@@ -625,7 +709,7 @@ class RightClass<R> implements Right<R, never> {
625
709
  orMap() {
626
710
  return this;
627
711
  }
628
- chain<TT extends Either<unknown, unknown>>(op: (value: R) => TT) {
712
+ chain<RR extends Either<unknown, unknown>>(op: (value: R) => RR) {
629
713
  return op(this.right);
630
714
  }
631
715
  orChain() {
@@ -637,13 +721,16 @@ class RightClass<R> implements Right<R, never> {
637
721
  isLeft(): this is Left<R, never> {
638
722
  return false;
639
723
  }
724
+ match<R2>(op: { right: (value: R) => R2 }) {
725
+ return op.right(this.right);
726
+ }
640
727
  matchTap(op: { right: (value: R) => void }) {
641
728
  return this.tap(op.right);
642
729
  }
643
730
  matchMap<R2>(op: { right: (value: R) => R2 }) {
644
731
  return this.map(op.right);
645
732
  }
646
- matchChain<TT extends Either<unknown, unknown>>(op: { right: (value: R) => TT }) {
733
+ matchChain<RR extends Either<unknown, unknown>>(op: { right: (value: R) => RR }) {
647
734
  return this.chain(op.right);
648
735
  }
649
736
  generator() {
@@ -673,7 +760,7 @@ class LeftClass<L> implements Left<never, L> {
673
760
  chain() {
674
761
  return this;
675
762
  }
676
- orChain<TT extends Either<unknown, unknown>>(op: (error: L) => TT) {
763
+ orChain<RR extends Either<unknown, unknown>>(op: (error: L) => RR) {
677
764
  return op(this.left);
678
765
  }
679
766
  isRight(): this is Right<never, L> {
@@ -682,13 +769,16 @@ class LeftClass<L> implements Left<never, L> {
682
769
  isLeft(): this is Left<never, L> {
683
770
  return true;
684
771
  }
772
+ match<R2>(op: { left: (error: L) => R2 }) {
773
+ return op.left(this.left);
774
+ }
685
775
  matchTap(op: { left: (error: L) => void }) {
686
776
  return this.orTap(op.left);
687
777
  }
688
778
  matchMap<R2>(op: { left: (error: L) => R2 }) {
689
779
  return this.orMap(op.left);
690
780
  }
691
- matchChain<TT extends Either<unknown, unknown>>(op: { left: (error: L) => TT }) {
781
+ matchChain<RR extends Either<unknown, unknown>>(op: { left: (error: L) => RR }) {
692
782
  return this.orChain(op.left);
693
783
  }
694
784
  generator() {