@jeengbe/prelude 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/either.d.mts +216 -0
- package/dist/either.d.mts.map +1 -0
- package/dist/either.mjs +326 -0
- package/dist/either.mjs.map +1 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +4 -0
- package/dist/maybe.d.mts +16 -0
- package/dist/maybe.d.mts.map +1 -0
- package/dist/maybe.mjs +32 -0
- package/dist/maybe.mjs.map +1 -0
- package/package.json +35 -0
- package/src/either.ts +477 -0
- package/src/index.ts +2 -0
- package/src/maybe.ts +45 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { Maybe } from "./maybe.mjs";
|
|
2
|
+
//#region src/either.d.ts
|
|
3
|
+
declare abstract class EitherBase<L, R> {
|
|
4
|
+
/**
|
|
5
|
+
* Maps the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
6
|
+
*/
|
|
7
|
+
map<R2>(fn: (t: R) => R2): Either<L, R2>;
|
|
8
|
+
mapAsync<R2>(fn: (t: R) => Promise<R2>): EitherP<L, R2>;
|
|
9
|
+
/**
|
|
10
|
+
* Flat maps the value of this Either if it is a Left, performs no operation if this is a Right.
|
|
11
|
+
*/
|
|
12
|
+
leftFlatMap<L2, R2>(fn: (t: L) => Either<L2, R2>): Either<L2, R | R2>;
|
|
13
|
+
leftFlatMapAsync<L2, R2>(fn: (t: L) => PromiseLike<Either<L2, R2>>): EitherP<L2, R | R2>;
|
|
14
|
+
/**
|
|
15
|
+
* Maps the value of this Either if it is a Left, performs no operation if this is a Right.
|
|
16
|
+
*/
|
|
17
|
+
leftMap<L2>(fn: (t: L) => L2): Either<L2, R>;
|
|
18
|
+
leftMapAsync<L2>(fn: (t: L) => Promise<L2>): EitherP<L2, R>;
|
|
19
|
+
/**
|
|
20
|
+
* Applies the provided functions to the value of this Either, depending on whether it is a Right or a Left and returns a new Either.
|
|
21
|
+
*/
|
|
22
|
+
bimap<L2, R2>(leftFn: (l: L) => L2, rightFn: (r: R) => R2): Either<L2, R2>;
|
|
23
|
+
bimapAsync<L2, R2>(leftFn: (l: L) => Promise<L2>, rightFn: (r: R) => Promise<R2>): EitherP<L2, R2>;
|
|
24
|
+
/**
|
|
25
|
+
* Runs the provided function with the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
26
|
+
*/
|
|
27
|
+
tap(fn: (t: R) => void): Either<L, R>;
|
|
28
|
+
tapAsync(fn: (t: R) => Promise<void>): EitherP<L, R>;
|
|
29
|
+
/**
|
|
30
|
+
* Runs the provided function with the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
31
|
+
* If the result of the function is a Left, it will be returned, otherwise the original Right value will be returned.
|
|
32
|
+
*/
|
|
33
|
+
flatTap<L2>(fn: (t: R) => Either<L2, void>): Either<L | L2, R>;
|
|
34
|
+
flatTapAsync<L2>(fn: (t: R) => PromiseLike<Either<L2, void>>): EitherP<L | L2, R>;
|
|
35
|
+
/**
|
|
36
|
+
* Flat maps the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
37
|
+
*/
|
|
38
|
+
flatMap<L2, R2>(fn: (t: R) => Either<L2, R2>): Either<L | L2, R2>;
|
|
39
|
+
flatMapAsync<L2, R2>(fn: (t: R) => PromiseLike<Either<L2, R2>>): EitherP<L | L2, R2>;
|
|
40
|
+
/**
|
|
41
|
+
* Applies the provided functions to the value of this Either, depending on whether it is a Right or a Left and returns the result.
|
|
42
|
+
*/
|
|
43
|
+
abstract fold<U1, U2>(leftFn: (l: L) => U1, rightFn: (r: R) => U2): U1 | U2;
|
|
44
|
+
/**
|
|
45
|
+
* Allows to deconstruct the Either using:
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
*
|
|
49
|
+
* ```ts
|
|
50
|
+
* declare const e: Either<string, number>;
|
|
51
|
+
*
|
|
52
|
+
* const [left, right] = e.pair();
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
*/
|
|
56
|
+
pair(): [Maybe<L>, Maybe<R>];
|
|
57
|
+
/**
|
|
58
|
+
* Returns true if this Either is a Right, false otherwise.
|
|
59
|
+
*/
|
|
60
|
+
isRight(): this is Right<R>;
|
|
61
|
+
/**
|
|
62
|
+
* Returns true if this Either is a Left, false otherwise.
|
|
63
|
+
*/
|
|
64
|
+
isLeft(): this is Left<L>;
|
|
65
|
+
/**
|
|
66
|
+
* Gets the right value if this is a Right or undefined if it's a Left.
|
|
67
|
+
*/
|
|
68
|
+
get(): Maybe<R>;
|
|
69
|
+
/**
|
|
70
|
+
* Returns the left value if this is a Left or undefined if it's a Right.
|
|
71
|
+
*/
|
|
72
|
+
getLeft(): Maybe<L>;
|
|
73
|
+
/**
|
|
74
|
+
* Gets the right value if this is a Right or the result of the provided function if it's a Left.
|
|
75
|
+
*/
|
|
76
|
+
getOrElse<T>(defaultValue: (l: L) => T): R | T;
|
|
77
|
+
}
|
|
78
|
+
declare class Left<L> extends EitherBase<L, never> {
|
|
79
|
+
private readonly value;
|
|
80
|
+
constructor(value: L);
|
|
81
|
+
fold<U1, U2>(leftFn: (l: L) => U1, _rightFn: (r: never) => U2): U1 | U2;
|
|
82
|
+
getLeft(): L;
|
|
83
|
+
}
|
|
84
|
+
declare class Right<R> extends EitherBase<never, R> {
|
|
85
|
+
private readonly value;
|
|
86
|
+
constructor(value: R);
|
|
87
|
+
fold<U1, U2>(_leftFn: (l: never) => U1, rightFn: (r: R) => U2): U1 | U2;
|
|
88
|
+
get(): R;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Mimics the [Cats Either[L, R]](https://typelevel.org/cats/datatypes/either.html) type.
|
|
92
|
+
*
|
|
93
|
+
* Either<L, R> is a union of Left<L> and Right<R>, so narrowing works in both directions:
|
|
94
|
+
*
|
|
95
|
+
* ```ts
|
|
96
|
+
* declare const e: Either<string, number>;
|
|
97
|
+
*
|
|
98
|
+
* if (e.isLeft()) {
|
|
99
|
+
* e; // Left<string>
|
|
100
|
+
* } else {
|
|
101
|
+
* e; // Right<number>
|
|
102
|
+
* }
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
type Either<L, R> = Left<L> | Right<R>;
|
|
106
|
+
declare namespace Either {
|
|
107
|
+
/**
|
|
108
|
+
* Creates a new Left Either with the provided value.
|
|
109
|
+
*/
|
|
110
|
+
function left<L>(value: L): Either<L, never>;
|
|
111
|
+
/**
|
|
112
|
+
* Creates a new Right Either with the provided value.
|
|
113
|
+
*/
|
|
114
|
+
function right<R>(value: R): Either<never, R>;
|
|
115
|
+
function fromMaybe<L, R>(value: Maybe<R>, leftValue: () => L): Either<L, R>;
|
|
116
|
+
function cond<L, R>(bool: boolean, rightFn: () => R, leftFn: () => L): Either<L, R>;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Mimics the [Cats EitherT[Future, L, R]](https://typelevel.org/cats/datatypes/eithert.html) type.
|
|
120
|
+
*/
|
|
121
|
+
declare class EitherP<L, R> implements PromiseLike<Either<L, R>> {
|
|
122
|
+
private readonly value;
|
|
123
|
+
private constructor();
|
|
124
|
+
/**
|
|
125
|
+
* Maps the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
126
|
+
*/
|
|
127
|
+
map<R2>(fn: (t: R) => R2): EitherP<L, R2>;
|
|
128
|
+
mapAsync<R2>(fn: (t: R) => Promise<R2>): EitherP<L, R2>;
|
|
129
|
+
/**
|
|
130
|
+
* Maps the value of this Either if it is a Left, performs no operation if this is a Right.
|
|
131
|
+
*/
|
|
132
|
+
leftMap<L2>(fn: (t: L) => L2): EitherP<L2, R>;
|
|
133
|
+
leftMapAsync<L2>(fn: (t: L) => Promise<L2>): EitherP<L2, R>;
|
|
134
|
+
/**
|
|
135
|
+
* Flat maps the value of this Either if it is a Left, performs no operation if this is a Right.
|
|
136
|
+
*/
|
|
137
|
+
leftFlatMap<L2, R2>(fn: (t: L) => Either<L2, R2>): EitherP<L2, R | R2>;
|
|
138
|
+
leftFlatMapAsync<L2, R2>(fn: (t: L) => PromiseLike<Either<L2, R2>>): EitherP<L2, R | R2>;
|
|
139
|
+
/**
|
|
140
|
+
* Applies the provided functions to the value of this Either, depending on whether it is a Right or a Left and returns a new Either.
|
|
141
|
+
*/
|
|
142
|
+
bimap<L2, R2>(leftFn: (l: L) => L2, rightFn: (r: R) => R2): EitherP<L2, R2>;
|
|
143
|
+
bimapAsync<L2, R2>(leftFn: (l: L) => Promise<L2>, rightFn: (r: R) => Promise<R2>): EitherP<L2, R2>;
|
|
144
|
+
/**
|
|
145
|
+
* Runs the provided function with the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
146
|
+
*/
|
|
147
|
+
tap(fn: (t: R) => void): EitherP<L, R>;
|
|
148
|
+
tapAsync(fn: (t: R) => Promise<void>): EitherP<L, R>;
|
|
149
|
+
/**
|
|
150
|
+
* Runs the provided function with the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
151
|
+
* If the result of the function is a Left, it will be returned, otherwise the original Right value will be returned.
|
|
152
|
+
*/
|
|
153
|
+
flatTap<L2>(fn: (t: R) => Either<L2, void>): EitherP<L | L2, R>;
|
|
154
|
+
flatTapAsync<L2>(fn: (t: R) => PromiseLike<Either<L2, void>>): EitherP<L | L2, R>;
|
|
155
|
+
/**
|
|
156
|
+
* Flat maps the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
157
|
+
*/
|
|
158
|
+
flatMap<L2, R2>(fn: (t: R) => Either<L2, R2>): EitherP<L | L2, R2>;
|
|
159
|
+
flatMapAsync<L2, R2>(fn: (t: R) => PromiseLike<Either<L2, R2>>): EitherP<L | L2, R2>;
|
|
160
|
+
/**
|
|
161
|
+
* Applies the provided functions to the value of this Either, depending on whether it is a Right or a Left and returns the result.
|
|
162
|
+
*/
|
|
163
|
+
fold<U1, U2>(leftFn: (l: L) => U1, rightFn: (r: R) => U2): Promise<U1 | U2>;
|
|
164
|
+
/**
|
|
165
|
+
* Allows to deconstruct the Either using:
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
*
|
|
169
|
+
* ```ts
|
|
170
|
+
* declare const e: EitherP<string, number>;
|
|
171
|
+
*
|
|
172
|
+
* const [left, right] = await e.pair();
|
|
173
|
+
* ```
|
|
174
|
+
*
|
|
175
|
+
*/
|
|
176
|
+
pair(): Promise<[Maybe<L>, Maybe<R>]>;
|
|
177
|
+
/**
|
|
178
|
+
* Returns true if this Either is a Right, false otherwise.
|
|
179
|
+
*/
|
|
180
|
+
isRight(): Promise<boolean>;
|
|
181
|
+
/**
|
|
182
|
+
* Returns true if this Either is a Left, false otherwise.
|
|
183
|
+
*/
|
|
184
|
+
isLeft(): Promise<boolean>;
|
|
185
|
+
/**
|
|
186
|
+
* Gets the right value if this is a Right or undefined if it's a Left.
|
|
187
|
+
*/
|
|
188
|
+
get(): Promise<Maybe<R>>;
|
|
189
|
+
/**
|
|
190
|
+
* Returns the left value if this is a Left or undefined if it's a Right.
|
|
191
|
+
*/
|
|
192
|
+
getLeft(): Promise<Maybe<L>>;
|
|
193
|
+
/**
|
|
194
|
+
* Gets the right value if this is a Right or the result of the provided function if it's a Left.
|
|
195
|
+
*/
|
|
196
|
+
getOrElse<T>(defaultValue: (l: L) => T): Promise<R | T>;
|
|
197
|
+
/**
|
|
198
|
+
* Creates a new Left EitherP with the provided value.
|
|
199
|
+
*/
|
|
200
|
+
static left<L>(value: Promise<L>): EitherP<L, never>;
|
|
201
|
+
/**
|
|
202
|
+
* Creates a new Right EitherP with the provided value.
|
|
203
|
+
*/
|
|
204
|
+
static right<R>(value: Promise<R>): EitherP<never, R>;
|
|
205
|
+
static fromMaybe<L, R>(value: Promise<Maybe<R>>, leftValue: () => Promise<L>): EitherP<L, R>;
|
|
206
|
+
/**
|
|
207
|
+
* @deprecated
|
|
208
|
+
*/
|
|
209
|
+
static fromEither<L, R>(either: PromiseLike<Either<L, R>>): EitherP<L, R>;
|
|
210
|
+
static fromPromise<L, R>(either: PromiseLike<Either<L, R>>): EitherP<L, R>;
|
|
211
|
+
static cond<L, R>(bool: Promise<boolean>, rightFn: () => Promise<R>, leftFn: () => Promise<L>): EitherP<L, R>;
|
|
212
|
+
then<U>(onfulfilled?: (value: Either<L, R>) => U | PromiseLike<U>): PromiseLike<U>;
|
|
213
|
+
}
|
|
214
|
+
//#endregion
|
|
215
|
+
export { Either, EitherP, Left, Right };
|
|
216
|
+
//# sourceMappingURL=either.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"either.d.mts","names":[],"sources":["../src/either.ts"],"mappings":"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"}
|
package/dist/either.mjs
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import { isDefined } from "./maybe.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/either.ts
|
|
4
|
+
var EitherBase = class {
|
|
5
|
+
/**
|
|
6
|
+
* Maps the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
7
|
+
*/
|
|
8
|
+
map(fn) {
|
|
9
|
+
return this.flatMap((value) => Either.right(fn(value)));
|
|
10
|
+
}
|
|
11
|
+
mapAsync(fn) {
|
|
12
|
+
return EitherP.fromPromise(toEitherPromise(this)).mapAsync(fn);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Flat maps the value of this Either if it is a Left, performs no operation if this is a Right.
|
|
16
|
+
*/
|
|
17
|
+
leftFlatMap(fn) {
|
|
18
|
+
return this.fold((l) => fn(l), (r) => Either.right(r));
|
|
19
|
+
}
|
|
20
|
+
leftFlatMapAsync(fn) {
|
|
21
|
+
return EitherP.fromPromise(toEitherPromise(this)).leftFlatMapAsync(fn);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Maps the value of this Either if it is a Left, performs no operation if this is a Right.
|
|
25
|
+
*/
|
|
26
|
+
leftMap(fn) {
|
|
27
|
+
return this.fold((l) => Either.left(fn(l)), (r) => Either.right(r));
|
|
28
|
+
}
|
|
29
|
+
leftMapAsync(fn) {
|
|
30
|
+
return EitherP.fromPromise(toEitherPromise(this)).leftMapAsync(fn);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Applies the provided functions to the value of this Either, depending on whether it is a Right or a Left and returns a new Either.
|
|
34
|
+
*/
|
|
35
|
+
bimap(leftFn, rightFn) {
|
|
36
|
+
return this.fold((l) => Either.left(leftFn(l)), (r) => Either.right(rightFn(r)));
|
|
37
|
+
}
|
|
38
|
+
bimapAsync(leftFn, rightFn) {
|
|
39
|
+
return EitherP.fromPromise(toEitherPromise(this)).bimapAsync(leftFn, rightFn);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Runs the provided function with the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
43
|
+
*/
|
|
44
|
+
tap(fn) {
|
|
45
|
+
return this.flatMap((value) => {
|
|
46
|
+
fn(value);
|
|
47
|
+
return Either.right(value);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
tapAsync(fn) {
|
|
51
|
+
return EitherP.fromPromise(toEitherPromise(this)).tapAsync(fn);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Runs the provided function with the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
55
|
+
* If the result of the function is a Left, it will be returned, otherwise the original Right value will be returned.
|
|
56
|
+
*/
|
|
57
|
+
flatTap(fn) {
|
|
58
|
+
return this.flatMap((value) => fn(value).map(() => value));
|
|
59
|
+
}
|
|
60
|
+
flatTapAsync(fn) {
|
|
61
|
+
return EitherP.fromPromise(toEitherPromise(this)).flatTapAsync(fn);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Flat maps the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
65
|
+
*/
|
|
66
|
+
flatMap(fn) {
|
|
67
|
+
return this.fold((l) => Either.left(l), (r) => fn(r));
|
|
68
|
+
}
|
|
69
|
+
flatMapAsync(fn) {
|
|
70
|
+
return EitherP.fromPromise(toEitherPromise(this)).flatMapAsync(fn);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Allows to deconstruct the Either using:
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
*
|
|
77
|
+
* ```ts
|
|
78
|
+
* declare const e: Either<string, number>;
|
|
79
|
+
*
|
|
80
|
+
* const [left, right] = e.pair();
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
*/
|
|
84
|
+
pair() {
|
|
85
|
+
return [this.getLeft(), this.get()];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Returns true if this Either is a Right, false otherwise.
|
|
89
|
+
*/
|
|
90
|
+
isRight() {
|
|
91
|
+
return this.fold(() => false, () => true);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Returns true if this Either is a Left, false otherwise.
|
|
95
|
+
*/
|
|
96
|
+
isLeft() {
|
|
97
|
+
return this.fold(() => true, () => false);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Gets the right value if this is a Right or undefined if it's a Left.
|
|
101
|
+
*/
|
|
102
|
+
get() {
|
|
103
|
+
return this.fold(() => undefined, (r) => r);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Returns the left value if this is a Left or undefined if it's a Right.
|
|
107
|
+
*/
|
|
108
|
+
getLeft() {
|
|
109
|
+
return this.fold((l) => l, () => undefined);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Gets the right value if this is a Right or the result of the provided function if it's a Left.
|
|
113
|
+
*/
|
|
114
|
+
getOrElse(defaultValue) {
|
|
115
|
+
return this.fold((l) => defaultValue(l), (r) => r);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
function toEitherPromise(e) {
|
|
119
|
+
return Promise.resolve(e);
|
|
120
|
+
}
|
|
121
|
+
var Left = class extends EitherBase {
|
|
122
|
+
value;
|
|
123
|
+
constructor(value) {
|
|
124
|
+
super();
|
|
125
|
+
this.value = value;
|
|
126
|
+
}
|
|
127
|
+
fold(leftFn, _rightFn) {
|
|
128
|
+
return leftFn(this.value);
|
|
129
|
+
}
|
|
130
|
+
getLeft() {
|
|
131
|
+
return this.value;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
var Right = class extends EitherBase {
|
|
135
|
+
value;
|
|
136
|
+
constructor(value) {
|
|
137
|
+
super();
|
|
138
|
+
this.value = value;
|
|
139
|
+
}
|
|
140
|
+
fold(_leftFn, rightFn) {
|
|
141
|
+
return rightFn(this.value);
|
|
142
|
+
}
|
|
143
|
+
get() {
|
|
144
|
+
return this.value;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
let Either;
|
|
148
|
+
(function(_Either) {
|
|
149
|
+
function left(value) {
|
|
150
|
+
return new Left(value);
|
|
151
|
+
}
|
|
152
|
+
_Either.left = left;
|
|
153
|
+
function right(value) {
|
|
154
|
+
return new Right(value);
|
|
155
|
+
}
|
|
156
|
+
_Either.right = right;
|
|
157
|
+
function fromMaybe(value, leftValue) {
|
|
158
|
+
return isDefined(value) ? Either.right(value) : Either.left(leftValue());
|
|
159
|
+
}
|
|
160
|
+
_Either.fromMaybe = fromMaybe;
|
|
161
|
+
function cond(bool, rightFn, leftFn) {
|
|
162
|
+
return bool ? Either.right(rightFn()) : Either.left(leftFn());
|
|
163
|
+
}
|
|
164
|
+
_Either.cond = cond;
|
|
165
|
+
})(Either || (Either = {}));
|
|
166
|
+
/**
|
|
167
|
+
* Mimics the [Cats EitherT[Future, L, R]](https://typelevel.org/cats/datatypes/eithert.html) type.
|
|
168
|
+
*/
|
|
169
|
+
var EitherP = class EitherP {
|
|
170
|
+
value;
|
|
171
|
+
constructor(value) {
|
|
172
|
+
this.value = value;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Maps the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
176
|
+
*/
|
|
177
|
+
map(fn) {
|
|
178
|
+
return new EitherP(this.value.then((e) => e.map(fn)));
|
|
179
|
+
}
|
|
180
|
+
mapAsync(fn) {
|
|
181
|
+
return this.flatMapAsync(async (value) => Either.right(await fn(value)));
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Maps the value of this Either if it is a Left, performs no operation if this is a Right.
|
|
185
|
+
*/
|
|
186
|
+
leftMap(fn) {
|
|
187
|
+
return new EitherP(this.value.then((e) => e.leftMap(fn)));
|
|
188
|
+
}
|
|
189
|
+
leftMapAsync(fn) {
|
|
190
|
+
return new EitherP(this.value.then(async (e) => await e.fold(async (l) => Either.left(await fn(l)), async (r) => Either.right(r))));
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Flat maps the value of this Either if it is a Left, performs no operation if this is a Right.
|
|
194
|
+
*/
|
|
195
|
+
leftFlatMap(fn) {
|
|
196
|
+
return new EitherP(this.value.then((e) => e.leftFlatMap(fn)));
|
|
197
|
+
}
|
|
198
|
+
leftFlatMapAsync(fn) {
|
|
199
|
+
return new EitherP(this.value.then(async (e) => await e.fold(async (left) => await fn(left), async (right) => Either.right(right))));
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Applies the provided functions to the value of this Either, depending on whether it is a Right or a Left and returns a new Either.
|
|
203
|
+
*/
|
|
204
|
+
bimap(leftFn, rightFn) {
|
|
205
|
+
return new EitherP(this.value.then((e) => e.bimap(leftFn, rightFn)));
|
|
206
|
+
}
|
|
207
|
+
bimapAsync(leftFn, rightFn) {
|
|
208
|
+
return new EitherP(this.value.then(async (e) => await e.fold(async (l) => Either.left(await leftFn(l)), async (r) => Either.right(await rightFn(r)))));
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Runs the provided function with the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
212
|
+
*/
|
|
213
|
+
tap(fn) {
|
|
214
|
+
return new EitherP(this.value.then((e) => e.tap(fn)));
|
|
215
|
+
}
|
|
216
|
+
tapAsync(fn) {
|
|
217
|
+
return this.flatMapAsync(async (value) => {
|
|
218
|
+
await fn(value);
|
|
219
|
+
return Either.right(value);
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Runs the provided function with the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
224
|
+
* If the result of the function is a Left, it will be returned, otherwise the original Right value will be returned.
|
|
225
|
+
*/
|
|
226
|
+
flatTap(fn) {
|
|
227
|
+
return new EitherP(this.value.then((e) => e.flatTap(fn)));
|
|
228
|
+
}
|
|
229
|
+
flatTapAsync(fn) {
|
|
230
|
+
return this.flatMapAsync(async (value) => (await fn(value)).map(() => value));
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Flat maps the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
234
|
+
*/
|
|
235
|
+
flatMap(fn) {
|
|
236
|
+
return new EitherP(this.value.then((e) => e.flatMap(fn)));
|
|
237
|
+
}
|
|
238
|
+
flatMapAsync(fn) {
|
|
239
|
+
return new EitherP(this.value.then((e) => e.fold(async (left) => Either.left(left), (right) => fn(right))));
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Applies the provided functions to the value of this Either, depending on whether it is a Right or a Left and returns the result.
|
|
243
|
+
*/
|
|
244
|
+
async fold(leftFn, rightFn) {
|
|
245
|
+
return (await this.value).fold(leftFn, rightFn);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Allows to deconstruct the Either using:
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
*
|
|
252
|
+
* ```ts
|
|
253
|
+
* declare const e: EitherP<string, number>;
|
|
254
|
+
*
|
|
255
|
+
* const [left, right] = await e.pair();
|
|
256
|
+
* ```
|
|
257
|
+
*
|
|
258
|
+
*/
|
|
259
|
+
async pair() {
|
|
260
|
+
return [await this.getLeft(), await this.get()];
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Returns true if this Either is a Right, false otherwise.
|
|
264
|
+
*/
|
|
265
|
+
async isRight() {
|
|
266
|
+
return (await this.value).isRight();
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Returns true if this Either is a Left, false otherwise.
|
|
270
|
+
*/
|
|
271
|
+
async isLeft() {
|
|
272
|
+
return !await this.isRight();
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Gets the right value if this is a Right or undefined if it's a Left.
|
|
276
|
+
*/
|
|
277
|
+
async get() {
|
|
278
|
+
return (await this.value).get();
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Returns the left value if this is a Left or undefined if it's a Right.
|
|
282
|
+
*/
|
|
283
|
+
async getLeft() {
|
|
284
|
+
return (await this.value).getLeft();
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Gets the right value if this is a Right or the result of the provided function if it's a Left.
|
|
288
|
+
*/
|
|
289
|
+
async getOrElse(defaultValue) {
|
|
290
|
+
return (await this.value).getOrElse(defaultValue);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Creates a new Left EitherP with the provided value.
|
|
294
|
+
*/
|
|
295
|
+
static left(value) {
|
|
296
|
+
return new EitherP(value.then((v) => Either.left(v)));
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Creates a new Right EitherP with the provided value.
|
|
300
|
+
*/
|
|
301
|
+
static right(value) {
|
|
302
|
+
return new EitherP(value.then((v) => Either.right(v)));
|
|
303
|
+
}
|
|
304
|
+
static fromMaybe(value, leftValue) {
|
|
305
|
+
return new EitherP(value.then(async (v) => isDefined(v) ? Either.right(v) : Either.left(await leftValue())));
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* @deprecated
|
|
309
|
+
*/
|
|
310
|
+
static fromEither(either) {
|
|
311
|
+
return new EitherP(either);
|
|
312
|
+
}
|
|
313
|
+
static fromPromise(either) {
|
|
314
|
+
return new EitherP(either);
|
|
315
|
+
}
|
|
316
|
+
static cond(bool, rightFn, leftFn) {
|
|
317
|
+
return new EitherP(bool.then(async (b) => b ? Either.right(await rightFn()) : Either.left(await leftFn())));
|
|
318
|
+
}
|
|
319
|
+
then(onfulfilled) {
|
|
320
|
+
return this.value.then(onfulfilled);
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
//#endregion
|
|
325
|
+
export { Either, EitherP, Left, Right };
|
|
326
|
+
//# sourceMappingURL=either.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"either.mjs","names":[],"sources":["../src/either.ts"],"sourcesContent":["import type { Maybe } from './maybe.js';\nimport { isDefined } from './maybe.js';\n\n// Note that xxxAsync implementations in Either all look like:\n// EitherP.fromPromise(toEitherPromise(this)).xxxAsync(...)\n//\n// And conversely, xxx implementations in EitherP all look like:\n// new EitherP(this.value.then(e => e.xxx(...)))\n\nabstract class EitherBase<L, R> {\n /**\n * Maps the value of this Either if it is a Right, performs no operation if this is a Left.\n */\n map<R2>(fn: (t: R) => R2): Either<L, R2> {\n return this.flatMap((value) => Either.right(fn(value)));\n }\n\n mapAsync<R2>(fn: (t: R) => Promise<R2>): EitherP<L, R2> {\n return EitherP.fromPromise(toEitherPromise(this)).mapAsync(fn);\n }\n\n /**\n * Flat maps the value of this Either if it is a Left, performs no operation if this is a Right.\n */\n leftFlatMap<L2, R2>(fn: (t: L) => Either<L2, R2>): Either<L2, R | R2> {\n return this.fold(\n (l) => fn(l),\n (r) => Either.right(r),\n );\n }\n\n leftFlatMapAsync<L2, R2>(fn: (t: L) => PromiseLike<Either<L2, R2>>): EitherP<L2, R | R2> {\n return EitherP.fromPromise(toEitherPromise(this)).leftFlatMapAsync(fn);\n }\n\n /**\n * Maps the value of this Either if it is a Left, performs no operation if this is a Right.\n */\n leftMap<L2>(fn: (t: L) => L2): Either<L2, R> {\n return this.fold(\n (l) => Either.left(fn(l)),\n (r) => Either.right(r),\n );\n }\n\n leftMapAsync<L2>(fn: (t: L) => Promise<L2>): EitherP<L2, R> {\n return EitherP.fromPromise(toEitherPromise(this)).leftMapAsync(fn);\n }\n\n /**\n * Applies the provided functions to the value of this Either, depending on whether it is a Right or a Left and returns a new Either.\n */\n bimap<L2, R2>(leftFn: (l: L) => L2, rightFn: (r: R) => R2): Either<L2, R2> {\n return this.fold(\n (l) => Either.left(leftFn(l)),\n (r) => Either.right(rightFn(r)),\n );\n }\n\n bimapAsync<L2, R2>(\n leftFn: (l: L) => Promise<L2>,\n rightFn: (r: R) => Promise<R2>,\n ): EitherP<L2, R2> {\n return EitherP.fromPromise(toEitherPromise(this)).bimapAsync(leftFn, rightFn);\n }\n\n /**\n * Runs the provided function with the value of this Either if it is a Right, performs no operation if this is a Left.\n */\n tap(fn: (t: R) => void): Either<L, R> {\n return this.flatMap((value) => {\n fn(value);\n return Either.right(value);\n });\n }\n\n tapAsync(fn: (t: R) => Promise<void>): EitherP<L, R> {\n return EitherP.fromPromise(toEitherPromise(this)).tapAsync(fn);\n }\n\n /**\n * Runs the provided function with the value of this Either if it is a Right, performs no operation if this is a Left.\n * If the result of the function is a Left, it will be returned, otherwise the original Right value will be returned.\n */\n flatTap<L2>(fn: (t: R) => Either<L2, void>): Either<L | L2, R> {\n return this.flatMap((value) => fn(value).map(() => value));\n }\n\n flatTapAsync<L2>(fn: (t: R) => PromiseLike<Either<L2, void>>): EitherP<L | L2, R> {\n return EitherP.fromPromise(toEitherPromise(this)).flatTapAsync(fn);\n }\n\n /**\n * Flat maps the value of this Either if it is a Right, performs no operation if this is a Left.\n */\n flatMap<L2, R2>(fn: (t: R) => Either<L2, R2>): Either<L | L2, R2> {\n return this.fold(\n (l) => Either.left(l),\n (r) => fn(r),\n );\n }\n\n flatMapAsync<L2, R2>(fn: (t: R) => PromiseLike<Either<L2, R2>>): EitherP<L | L2, R2> {\n return EitherP.fromPromise(toEitherPromise(this)).flatMapAsync(fn);\n }\n\n /**\n * Applies the provided functions to the value of this Either, depending on whether it is a Right or a Left and returns the result.\n */\n abstract fold<U1, U2>(leftFn: (l: L) => U1, rightFn: (r: R) => U2): U1 | U2;\n\n /**\n * Allows to deconstruct the Either using:\n *\n * @example\n *\n * ```ts\n * declare const e: Either<string, number>;\n *\n * const [left, right] = e.pair();\n * ```\n *\n */\n pair(): [Maybe<L>, Maybe<R>] {\n return [this.getLeft(), this.get()];\n }\n\n /**\n * Returns true if this Either is a Right, false otherwise.\n */\n isRight(): this is Right<R> {\n return this.fold(\n () => false,\n () => true,\n );\n }\n\n /**\n * Returns true if this Either is a Left, false otherwise.\n */\n isLeft(): this is Left<L> {\n return this.fold(\n () => true,\n () => false,\n );\n }\n\n /**\n * Gets the right value if this is a Right or undefined if it's a Left.\n */\n get(): Maybe<R> {\n return this.fold(\n () => undefined,\n (r) => r,\n );\n }\n\n /**\n * Returns the left value if this is a Left or undefined if it's a Right.\n */\n getLeft(): Maybe<L> {\n return this.fold(\n (l) => l,\n () => undefined,\n );\n }\n\n /**\n * Gets the right value if this is a Right or the result of the provided function if it's a Left.\n */\n getOrElse<T>(defaultValue: (l: L) => T): R | T {\n return this.fold(\n (l) => defaultValue(l),\n (r) => r,\n );\n }\n}\n\n// EitherBase is abstract with only Left/Right as concrete subclasses; the cast is always valid.\nfunction toEitherPromise<L, R>(e: EitherBase<L, R>): Promise<Either<L, R>> {\n return Promise.resolve(e as unknown as Either<L, R>);\n}\n\nexport class Left<L> extends EitherBase<L, never> {\n constructor(private readonly value: L) {\n super();\n }\n\n fold<U1, U2>(leftFn: (l: L) => U1, _rightFn: (r: never) => U2): U1 | U2 {\n return leftFn(this.value);\n }\n\n override getLeft(): L {\n return this.value;\n }\n}\n\nexport class Right<R> extends EitherBase<never, R> {\n constructor(private readonly value: R) {\n super();\n }\n\n fold<U1, U2>(_leftFn: (l: never) => U1, rightFn: (r: R) => U2): U1 | U2 {\n return rightFn(this.value);\n }\n\n override get(): R {\n return this.value;\n }\n}\n\n/**\n * Mimics the [Cats Either[L, R]](https://typelevel.org/cats/datatypes/either.html) type.\n *\n * Either<L, R> is a union of Left<L> and Right<R>, so narrowing works in both directions:\n *\n * ```ts\n * declare const e: Either<string, number>;\n *\n * if (e.isLeft()) {\n * e; // Left<string>\n * } else {\n * e; // Right<number>\n * }\n * ```\n */\nexport type Either<L, R> = Left<L> | Right<R>;\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace Either {\n /**\n * Creates a new Left Either with the provided value.\n */\n export function left<L>(value: L): Either<L, never> {\n return new Left(value);\n }\n\n /**\n * Creates a new Right Either with the provided value.\n */\n export function right<R>(value: R): Either<never, R> {\n return new Right(value);\n }\n\n export function fromMaybe<L, R>(value: Maybe<R>, leftValue: () => L): Either<L, R> {\n return isDefined(value) ? Either.right(value) : Either.left(leftValue());\n }\n\n export function cond<L, R>(bool: boolean, rightFn: () => R, leftFn: () => L): Either<L, R> {\n return bool ? Either.right(rightFn()) : Either.left(leftFn());\n }\n}\n\n/**\n * Mimics the [Cats EitherT[Future, L, R]](https://typelevel.org/cats/datatypes/eithert.html) type.\n */\nexport class EitherP<L, R> implements PromiseLike<Either<L, R>> {\n private constructor(private readonly value: PromiseLike<Either<L, R>>) {}\n\n /**\n * Maps the value of this Either if it is a Right, performs no operation if this is a Left.\n */\n map<R2>(fn: (t: R) => R2): EitherP<L, R2> {\n return new EitherP(this.value.then((e) => e.map(fn)));\n }\n\n mapAsync<R2>(fn: (t: R) => Promise<R2>): EitherP<L, R2> {\n return this.flatMapAsync(async (value) => Either.right(await fn(value)));\n }\n\n /**\n * Maps the value of this Either if it is a Left, performs no operation if this is a Right.\n */\n leftMap<L2>(fn: (t: L) => L2): EitherP<L2, R> {\n return new EitherP(this.value.then((e) => e.leftMap(fn)));\n }\n\n leftMapAsync<L2>(fn: (t: L) => Promise<L2>): EitherP<L2, R> {\n return new EitherP(\n this.value.then(\n async (e) =>\n await e.fold(\n async (l) => Either.left(await fn(l)),\n async (r) => Either.right(r),\n ),\n ),\n );\n }\n\n /**\n * Flat maps the value of this Either if it is a Left, performs no operation if this is a Right.\n */\n leftFlatMap<L2, R2>(fn: (t: L) => Either<L2, R2>): EitherP<L2, R | R2> {\n return new EitherP(this.value.then((e) => e.leftFlatMap(fn)));\n }\n\n leftFlatMapAsync<L2, R2>(fn: (t: L) => PromiseLike<Either<L2, R2>>): EitherP<L2, R | R2> {\n return new EitherP(\n this.value.then<Either<L2, R | R2>>(\n async (e) =>\n await e.fold(\n async (left) => await fn(left),\n async (right) => Either.right(right),\n ),\n ),\n );\n }\n\n /**\n * Applies the provided functions to the value of this Either, depending on whether it is a Right or a Left and returns a new Either.\n */\n bimap<L2, R2>(leftFn: (l: L) => L2, rightFn: (r: R) => R2): EitherP<L2, R2> {\n return new EitherP(this.value.then((e) => e.bimap(leftFn, rightFn)));\n }\n\n bimapAsync<L2, R2>(\n leftFn: (l: L) => Promise<L2>,\n rightFn: (r: R) => Promise<R2>,\n ): EitherP<L2, R2> {\n return new EitherP(\n this.value.then(\n async (e) =>\n await e.fold(\n async (l) => Either.left(await leftFn(l)),\n async (r) => Either.right(await rightFn(r)),\n ),\n ),\n );\n }\n\n /**\n * Runs the provided function with the value of this Either if it is a Right, performs no operation if this is a Left.\n */\n tap(fn: (t: R) => void): EitherP<L, R> {\n return new EitherP(this.value.then((e) => e.tap(fn)));\n }\n\n tapAsync(fn: (t: R) => Promise<void>): EitherP<L, R> {\n return this.flatMapAsync(async (value) => {\n await fn(value);\n return Either.right(value);\n });\n }\n\n /**\n * Runs the provided function with the value of this Either if it is a Right, performs no operation if this is a Left.\n * If the result of the function is a Left, it will be returned, otherwise the original Right value will be returned.\n */\n flatTap<L2>(fn: (t: R) => Either<L2, void>): EitherP<L | L2, R> {\n return new EitherP(this.value.then((e) => e.flatTap(fn)));\n }\n\n flatTapAsync<L2>(fn: (t: R) => PromiseLike<Either<L2, void>>): EitherP<L | L2, R> {\n return this.flatMapAsync(async (value) => (await fn(value)).map(() => value));\n }\n\n /**\n * Flat maps the value of this Either if it is a Right, performs no operation if this is a Left.\n */\n flatMap<L2, R2>(fn: (t: R) => Either<L2, R2>): EitherP<L | L2, R2> {\n return new EitherP(this.value.then((e) => e.flatMap(fn)));\n }\n\n flatMapAsync<L2, R2>(fn: (t: R) => PromiseLike<Either<L2, R2>>): EitherP<L | L2, R2> {\n return new EitherP(\n this.value.then<Either<L | L2, R2>>((e) =>\n e.fold(\n async (left) => Either.left(left),\n (right) => fn(right),\n ),\n ),\n );\n }\n\n /**\n * Applies the provided functions to the value of this Either, depending on whether it is a Right or a Left and returns the result.\n */\n async fold<U1, U2>(leftFn: (l: L) => U1, rightFn: (r: R) => U2): Promise<U1 | U2> {\n return (await this.value).fold(leftFn, rightFn);\n }\n\n /**\n * Allows to deconstruct the Either using:\n *\n * @example\n *\n * ```ts\n * declare const e: EitherP<string, number>;\n *\n * const [left, right] = await e.pair();\n * ```\n *\n */\n async pair(): Promise<[Maybe<L>, Maybe<R>]> {\n return [await this.getLeft(), await this.get()];\n }\n\n /**\n * Returns true if this Either is a Right, false otherwise.\n */\n async isRight(): Promise<boolean> {\n return (await this.value).isRight();\n }\n\n /**\n * Returns true if this Either is a Left, false otherwise.\n */\n async isLeft(): Promise<boolean> {\n return !(await this.isRight());\n }\n\n /**\n * Gets the right value if this is a Right or undefined if it's a Left.\n */\n async get(): Promise<Maybe<R>> {\n return (await this.value).get();\n }\n\n /**\n * Returns the left value if this is a Left or undefined if it's a Right.\n */\n async getLeft(): Promise<Maybe<L>> {\n return (await this.value).getLeft();\n }\n\n /**\n * Gets the right value if this is a Right or the result of the provided function if it's a Left.\n */\n async getOrElse<T>(defaultValue: (l: L) => T): Promise<R | T> {\n return (await this.value).getOrElse(defaultValue);\n }\n\n /**\n * Creates a new Left EitherP with the provided value.\n */\n static left<L>(value: Promise<L>): EitherP<L, never> {\n return new EitherP(value.then((v) => Either.left(v)));\n }\n\n /**\n * Creates a new Right EitherP with the provided value.\n */\n static right<R>(value: Promise<R>): EitherP<never, R> {\n return new EitherP(value.then((v) => Either.right(v)));\n }\n\n static fromMaybe<L, R>(value: Promise<Maybe<R>>, leftValue: () => Promise<L>): EitherP<L, R> {\n return new EitherP(\n value.then(async (v) => (isDefined(v) ? Either.right(v) : Either.left(await leftValue()))),\n );\n }\n\n /**\n * @deprecated\n */\n static fromEither<L, R>(either: PromiseLike<Either<L, R>>): EitherP<L, R> {\n return new EitherP(either);\n }\n\n static fromPromise<L, R>(either: PromiseLike<Either<L, R>>): EitherP<L, R> {\n return new EitherP(either);\n }\n\n static cond<L, R>(\n bool: Promise<boolean>,\n rightFn: () => Promise<R>,\n leftFn: () => Promise<L>,\n ): EitherP<L, R> {\n return new EitherP(\n bool.then(async (b) => (b ? Either.right(await rightFn()) : Either.left(await leftFn()))),\n );\n }\n\n then<U>(onfulfilled?: (value: Either<L, R>) => U | PromiseLike<U>): PromiseLike<U> {\n return this.value.then(onfulfilled);\n }\n}\n"],"mappings":";;;AASA,IAAe,aAAf,MAAgC;;;;CAI9B,IAAQ,IAAiC;EACvC,OAAO,KAAK,SAAS,UAAU,OAAO,MAAM,GAAG,KAAK,CAAC,CAAC;CACxD;CAEA,SAAa,IAA2C;EACtD,OAAO,QAAQ,YAAY,gBAAgB,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE;CAC/D;;;;CAKA,YAAoB,IAAkD;EACpE,OAAO,KAAK,MACT,MAAM,GAAG,CAAC,IACV,MAAM,OAAO,MAAM,CAAC,CACvB;CACF;CAEA,iBAAyB,IAAgE;EACvF,OAAO,QAAQ,YAAY,gBAAgB,IAAI,CAAC,CAAC,CAAC,iBAAiB,EAAE;CACvE;;;;CAKA,QAAY,IAAiC;EAC3C,OAAO,KAAK,MACT,MAAM,OAAO,KAAK,GAAG,CAAC,CAAC,IACvB,MAAM,OAAO,MAAM,CAAC,CACvB;CACF;CAEA,aAAiB,IAA2C;EAC1D,OAAO,QAAQ,YAAY,gBAAgB,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE;CACnE;;;;CAKA,MAAc,QAAsB,SAAuC;EACzE,OAAO,KAAK,MACT,MAAM,OAAO,KAAK,OAAO,CAAC,CAAC,IAC3B,MAAM,OAAO,MAAM,QAAQ,CAAC,CAAC,CAChC;CACF;CAEA,WACE,QACA,SACiB;EACjB,OAAO,QAAQ,YAAY,gBAAgB,IAAI,CAAC,CAAC,CAAC,WAAW,QAAQ,OAAO;CAC9E;;;;CAKA,IAAI,IAAkC;EACpC,OAAO,KAAK,SAAS,UAAU;GAC7B,GAAG,KAAK;GACR,OAAO,OAAO,MAAM,KAAK;EAC3B,CAAC;CACH;CAEA,SAAS,IAA4C;EACnD,OAAO,QAAQ,YAAY,gBAAgB,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE;CAC/D;;;;;CAMA,QAAY,IAAmD;EAC7D,OAAO,KAAK,SAAS,UAAU,GAAG,KAAK,CAAC,CAAC,UAAU,KAAK,CAAC;CAC3D;CAEA,aAAiB,IAAiE;EAChF,OAAO,QAAQ,YAAY,gBAAgB,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE;CACnE;;;;CAKA,QAAgB,IAAkD;EAChE,OAAO,KAAK,MACT,MAAM,OAAO,KAAK,CAAC,IACnB,MAAM,GAAG,CAAC,CACb;CACF;CAEA,aAAqB,IAAgE;EACnF,OAAO,QAAQ,YAAY,gBAAgB,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE;CACnE;;;;;;;;;;;;;CAmBA,OAA6B;EAC3B,OAAO,CAAC,KAAK,QAAQ,GAAG,KAAK,IAAI,CAAC;CACpC;;;;CAKA,UAA4B;EAC1B,OAAO,KAAK,WACJ,aACA,IACR;CACF;;;;CAKA,SAA0B;EACxB,OAAO,KAAK,WACJ,YACA,KACR;CACF;;;;CAKA,MAAgB;EACd,OAAO,KAAK,WACJ,YACL,MAAM,CACT;CACF;;;;CAKA,UAAoB;EAClB,OAAO,KAAK,MACT,MAAM,SACD,SACR;CACF;;;;CAKA,UAAa,cAAkC;EAC7C,OAAO,KAAK,MACT,MAAM,aAAa,CAAC,IACpB,MAAM,CACT;CACF;AACF;AAGA,SAAS,gBAAsB,GAA4C;CACzE,OAAO,QAAQ,QAAQ,CAA4B;AACrD;AAEA,IAAa,OAAb,cAA6B,WAAqB;CACnB;CAA7B,YAAY,AAAiB,OAAU;EACrC,MAAM;EADqB;CAE7B;CAEA,KAAa,QAAsB,UAAqC;EACtE,OAAO,OAAO,KAAK,KAAK;CAC1B;CAEA,AAAS,UAAa;EACpB,OAAO,KAAK;CACd;AACF;AAEA,IAAa,QAAb,cAA8B,WAAqB;CACpB;CAA7B,YAAY,AAAiB,OAAU;EACrC,MAAM;EADqB;CAE7B;CAEA,KAAa,SAA2B,SAAgC;EACtE,OAAO,QAAQ,KAAK,KAAK;CAC3B;CAEA,AAAS,MAAS;EAChB,OAAO,KAAK;CACd;AACF;AAoBO,IAAU;CAAV;CAIE,SAAS,KAAQ,OAA4B;EAClD,OAAO,IAAI,KAAK,KAAK;CACvB;;CAKO,SAAS,MAAS,OAA4B;EACnD,OAAO,IAAI,MAAM,KAAK;CACxB;;CAEO,SAAS,UAAgB,OAAiB,WAAkC;EACjF,OAAO,UAAU,KAAK,IAAI,OAAO,MAAM,KAAK,IAAI,OAAO,KAAK,UAAU,CAAC;CACzE;;CAEO,SAAS,KAAW,MAAe,SAAkB,QAA+B;EACzF,OAAO,OAAO,OAAO,MAAM,QAAQ,CAAC,IAAI,OAAO,KAAK,OAAO,CAAC;CAC9D;;EACD,wBAAD;;;;AAKA,IAAa,UAAb,MAAa,QAAmD;CACzB;CAArC,AAAQ,YAAY,AAAiB,OAAkC;EAAlC;CAAmC;;;;CAKxE,IAAQ,IAAkC;EACxC,OAAO,IAAI,QAAQ,KAAK,MAAM,MAAM,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;CACtD;CAEA,SAAa,IAA2C;EACtD,OAAO,KAAK,aAAa,OAAO,UAAU,OAAO,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC;CACzE;;;;CAKA,QAAY,IAAkC;EAC5C,OAAO,IAAI,QAAQ,KAAK,MAAM,MAAM,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;CAC1D;CAEA,aAAiB,IAA2C;EAC1D,OAAO,IAAI,QACT,KAAK,MAAM,KACT,OAAO,MACL,MAAM,EAAE,KACN,OAAO,MAAM,OAAO,KAAK,MAAM,GAAG,CAAC,CAAC,GACpC,OAAO,MAAM,OAAO,MAAM,CAAC,CAC7B,CACJ,CACF;CACF;;;;CAKA,YAAoB,IAAmD;EACrE,OAAO,IAAI,QAAQ,KAAK,MAAM,MAAM,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;CAC9D;CAEA,iBAAyB,IAAgE;EACvF,OAAO,IAAI,QACT,KAAK,MAAM,KACT,OAAO,MACL,MAAM,EAAE,KACN,OAAO,SAAS,MAAM,GAAG,IAAI,GAC7B,OAAO,UAAU,OAAO,MAAM,KAAK,CACrC,CACJ,CACF;CACF;;;;CAKA,MAAc,QAAsB,SAAwC;EAC1E,OAAO,IAAI,QAAQ,KAAK,MAAM,MAAM,MAAM,EAAE,MAAM,QAAQ,OAAO,CAAC,CAAC;CACrE;CAEA,WACE,QACA,SACiB;EACjB,OAAO,IAAI,QACT,KAAK,MAAM,KACT,OAAO,MACL,MAAM,EAAE,KACN,OAAO,MAAM,OAAO,KAAK,MAAM,OAAO,CAAC,CAAC,GACxC,OAAO,MAAM,OAAO,MAAM,MAAM,QAAQ,CAAC,CAAC,CAC5C,CACJ,CACF;CACF;;;;CAKA,IAAI,IAAmC;EACrC,OAAO,IAAI,QAAQ,KAAK,MAAM,MAAM,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;CACtD;CAEA,SAAS,IAA4C;EACnD,OAAO,KAAK,aAAa,OAAO,UAAU;GACxC,MAAM,GAAG,KAAK;GACd,OAAO,OAAO,MAAM,KAAK;EAC3B,CAAC;CACH;;;;;CAMA,QAAY,IAAoD;EAC9D,OAAO,IAAI,QAAQ,KAAK,MAAM,MAAM,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;CAC1D;CAEA,aAAiB,IAAiE;EAChF,OAAO,KAAK,aAAa,OAAO,WAAW,MAAM,GAAG,KAAK,EAAC,CAAE,UAAU,KAAK,CAAC;CAC9E;;;;CAKA,QAAgB,IAAmD;EACjE,OAAO,IAAI,QAAQ,KAAK,MAAM,MAAM,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;CAC1D;CAEA,aAAqB,IAAgE;EACnF,OAAO,IAAI,QACT,KAAK,MAAM,MAA0B,MACnC,EAAE,KACA,OAAO,SAAS,OAAO,KAAK,IAAI,IAC/B,UAAU,GAAG,KAAK,CACrB,CACF,CACF;CACF;;;;CAKA,MAAM,KAAa,QAAsB,SAAyC;EAChF,QAAQ,MAAM,KAAK,MAAK,CAAE,KAAK,QAAQ,OAAO;CAChD;;;;;;;;;;;;;CAcA,MAAM,OAAsC;EAC1C,OAAO,CAAC,MAAM,KAAK,QAAQ,GAAG,MAAM,KAAK,IAAI,CAAC;CAChD;;;;CAKA,MAAM,UAA4B;EAChC,QAAQ,MAAM,KAAK,MAAK,CAAE,QAAQ;CACpC;;;;CAKA,MAAM,SAA2B;EAC/B,OAAO,CAAE,MAAM,KAAK,QAAQ;CAC9B;;;;CAKA,MAAM,MAAyB;EAC7B,QAAQ,MAAM,KAAK,MAAK,CAAE,IAAI;CAChC;;;;CAKA,MAAM,UAA6B;EACjC,QAAQ,MAAM,KAAK,MAAK,CAAE,QAAQ;CACpC;;;;CAKA,MAAM,UAAa,cAA2C;EAC5D,QAAQ,MAAM,KAAK,MAAK,CAAE,UAAU,YAAY;CAClD;;;;CAKA,OAAO,KAAQ,OAAsC;EACnD,OAAO,IAAI,QAAQ,MAAM,MAAM,MAAM,OAAO,KAAK,CAAC,CAAC,CAAC;CACtD;;;;CAKA,OAAO,MAAS,OAAsC;EACpD,OAAO,IAAI,QAAQ,MAAM,MAAM,MAAM,OAAO,MAAM,CAAC,CAAC,CAAC;CACvD;CAEA,OAAO,UAAgB,OAA0B,WAA4C;EAC3F,OAAO,IAAI,QACT,MAAM,KAAK,OAAO,MAAO,UAAU,CAAC,IAAI,OAAO,MAAM,CAAC,IAAI,OAAO,KAAK,MAAM,UAAU,CAAC,CAAE,CAC3F;CACF;;;;CAKA,OAAO,WAAiB,QAAkD;EACxE,OAAO,IAAI,QAAQ,MAAM;CAC3B;CAEA,OAAO,YAAkB,QAAkD;EACzE,OAAO,IAAI,QAAQ,MAAM;CAC3B;CAEA,OAAO,KACL,MACA,SACA,QACe;EACf,OAAO,IAAI,QACT,KAAK,KAAK,OAAO,MAAO,IAAI,OAAO,MAAM,MAAM,QAAQ,CAAC,IAAI,OAAO,KAAK,MAAM,OAAO,CAAC,CAAE,CAC1F;CACF;CAEA,KAAQ,aAA2E;EACjF,OAAO,KAAK,MAAM,KAAK,WAAW;CACpC;AACF"}
|
package/dist/index.d.mts
ADDED
package/dist/index.mjs
ADDED
package/dist/maybe.d.mts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/maybe.d.ts
|
|
2
|
+
type Maybe<T> = T | undefined;
|
|
3
|
+
declare function mapMaybe<T, U>(value: Maybe<T>, fn: (value: T) => U): Maybe<U>;
|
|
4
|
+
declare function isDefined<T>(value: Maybe<T>): value is T;
|
|
5
|
+
declare function flattenMaybe<T>(value: Maybe<Maybe<T>>): Maybe<T>;
|
|
6
|
+
declare function ifTrue<T>(value: boolean, fn: () => T): Maybe<T>;
|
|
7
|
+
declare function ifFalse<T>(value: boolean, fn: () => T): Maybe<T>;
|
|
8
|
+
declare function matchPair<A, B, R>([a, b]: [Maybe<A>, Maybe<B>], cases: {
|
|
9
|
+
neither: () => R;
|
|
10
|
+
a: (a: A) => R;
|
|
11
|
+
b: (b: B) => R;
|
|
12
|
+
both: (a: A, b: B) => R;
|
|
13
|
+
}): R;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { Maybe, flattenMaybe, ifFalse, ifTrue, isDefined, mapMaybe, matchPair };
|
|
16
|
+
//# sourceMappingURL=maybe.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maybe.d.mts","names":[],"sources":["../src/maybe.ts"],"mappings":";KAAY,MAAM,KAAK;iBAEP,SAAS,GAAG,GAAG,OAAO,MAAM,IAAI,KAAK,OAAO,MAAM,IAAI,MAAM;iBAI5D,UAAU,GAAG,OAAO,MAAM,KAAK,SAAS;iBAIxC,aAAa,GAAG,OAAO,MAAM,MAAM,MAAM,MAAM;iBAI/C,OAAO,GAAG,gBAAgB,UAAU,IAAI,MAAM;iBAI9C,QAAQ,GAAG,gBAAgB,UAAU,IAAI,MAAM;iBAI/C,UAAU,GAAG,GAAG,IAC7B,GAAG,KAAK,MAAM,IAAI,MAAM,KACzB;EACE,eAAe;EACf,IAAI,GAAG,MAAM;EACb,IAAI,GAAG,MAAM;EACb,OAAO,GAAG,GAAG,GAAG,MAAM;IAEvB"}
|
package/dist/maybe.mjs
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/maybe.ts
|
|
2
|
+
function mapMaybe(value, fn) {
|
|
3
|
+
return value === undefined ? undefined : fn(value);
|
|
4
|
+
}
|
|
5
|
+
function isDefined(value) {
|
|
6
|
+
return value !== undefined;
|
|
7
|
+
}
|
|
8
|
+
function flattenMaybe(value) {
|
|
9
|
+
return mapMaybe(value, (v) => v);
|
|
10
|
+
}
|
|
11
|
+
function ifTrue(value, fn) {
|
|
12
|
+
return value ? fn() : undefined;
|
|
13
|
+
}
|
|
14
|
+
function ifFalse(value, fn) {
|
|
15
|
+
return !value ? fn() : undefined;
|
|
16
|
+
}
|
|
17
|
+
function matchPair([a, b], cases) {
|
|
18
|
+
if (!isDefined(a)) {
|
|
19
|
+
if (!isDefined(b)) {
|
|
20
|
+
return cases.neither();
|
|
21
|
+
}
|
|
22
|
+
return cases.b(b);
|
|
23
|
+
}
|
|
24
|
+
if (!isDefined(b)) {
|
|
25
|
+
return cases.a(a);
|
|
26
|
+
}
|
|
27
|
+
return cases.both(a, b);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
//#endregion
|
|
31
|
+
export { flattenMaybe, ifFalse, ifTrue, isDefined, mapMaybe, matchPair };
|
|
32
|
+
//# sourceMappingURL=maybe.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maybe.mjs","names":[],"sources":["../src/maybe.ts"],"sourcesContent":["export type Maybe<T> = T | undefined;\n\nexport function mapMaybe<T, U>(value: Maybe<T>, fn: (value: T) => U): Maybe<U> {\n return value === undefined ? undefined : fn(value);\n}\n\nexport function isDefined<T>(value: Maybe<T>): value is T {\n return value !== undefined;\n}\n\nexport function flattenMaybe<T>(value: Maybe<Maybe<T>>): Maybe<T> {\n return mapMaybe(value, (v) => v);\n}\n\nexport function ifTrue<T>(value: boolean, fn: () => T): Maybe<T> {\n return value ? fn() : undefined;\n}\n\nexport function ifFalse<T>(value: boolean, fn: () => T): Maybe<T> {\n return !value ? fn() : undefined;\n}\n\nexport function matchPair<A, B, R>(\n [a, b]: [Maybe<A>, Maybe<B>],\n cases: {\n neither: () => R;\n a: (a: A) => R;\n b: (b: B) => R;\n both: (a: A, b: B) => R;\n },\n): R {\n if (!isDefined(a)) {\n if (!isDefined(b)) {\n return cases.neither();\n }\n\n return cases.b(b);\n }\n\n if (!isDefined(b)) {\n return cases.a(a);\n }\n\n return cases.both(a, b);\n}\n"],"mappings":";AAEA,SAAgB,SAAe,OAAiB,IAA+B;CAC7E,OAAO,UAAU,YAAY,YAAY,GAAG,KAAK;AACnD;AAEA,SAAgB,UAAa,OAA6B;CACxD,OAAO,UAAU;AACnB;AAEA,SAAgB,aAAgB,OAAkC;CAChE,OAAO,SAAS,QAAQ,MAAM,CAAC;AACjC;AAEA,SAAgB,OAAU,OAAgB,IAAuB;CAC/D,OAAO,QAAQ,GAAG,IAAI;AACxB;AAEA,SAAgB,QAAW,OAAgB,IAAuB;CAChE,OAAO,CAAC,QAAQ,GAAG,IAAI;AACzB;AAEA,SAAgB,UACd,CAAC,GAAG,IACJ,OAMG;CACH,IAAI,CAAC,UAAU,CAAC,GAAG;EACjB,IAAI,CAAC,UAAU,CAAC,GAAG;GACjB,OAAO,MAAM,QAAQ;EACvB;EAEA,OAAO,MAAM,EAAE,CAAC;CAClB;CAEA,IAAI,CAAC,UAAU,CAAC,GAAG;EACjB,OAAO,MAAM,EAAE,CAAC;CAClB;CAEA,OAAO,MAAM,KAAK,GAAG,CAAC;AACxB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jeengbe/prelude",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"files": [
|
|
6
|
+
"dist",
|
|
7
|
+
"src",
|
|
8
|
+
"!src/**/*.spec.ts"
|
|
9
|
+
],
|
|
10
|
+
"type": "module",
|
|
11
|
+
"sideEffects": false,
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.mts",
|
|
15
|
+
"default": "./dist/index.mjs"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"oxfmt": "^0.60.0",
|
|
23
|
+
"oxlint": "^1.75.0",
|
|
24
|
+
"tsdown": "^0.22.14",
|
|
25
|
+
"typescript": "^7.0.2",
|
|
26
|
+
"vitest": "^4.1.10",
|
|
27
|
+
"@jeengbe/scaffolding": "0.0.0"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsdown",
|
|
31
|
+
"lint": "oxlint --fix . && oxfmt --write .",
|
|
32
|
+
"test": "vitest",
|
|
33
|
+
"typecheck": "tsc"
|
|
34
|
+
}
|
|
35
|
+
}
|
package/src/either.ts
ADDED
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
import type { Maybe } from './maybe.js';
|
|
2
|
+
import { isDefined } from './maybe.js';
|
|
3
|
+
|
|
4
|
+
// Note that xxxAsync implementations in Either all look like:
|
|
5
|
+
// EitherP.fromPromise(toEitherPromise(this)).xxxAsync(...)
|
|
6
|
+
//
|
|
7
|
+
// And conversely, xxx implementations in EitherP all look like:
|
|
8
|
+
// new EitherP(this.value.then(e => e.xxx(...)))
|
|
9
|
+
|
|
10
|
+
abstract class EitherBase<L, R> {
|
|
11
|
+
/**
|
|
12
|
+
* Maps the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
13
|
+
*/
|
|
14
|
+
map<R2>(fn: (t: R) => R2): Either<L, R2> {
|
|
15
|
+
return this.flatMap((value) => Either.right(fn(value)));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
mapAsync<R2>(fn: (t: R) => Promise<R2>): EitherP<L, R2> {
|
|
19
|
+
return EitherP.fromPromise(toEitherPromise(this)).mapAsync(fn);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Flat maps the value of this Either if it is a Left, performs no operation if this is a Right.
|
|
24
|
+
*/
|
|
25
|
+
leftFlatMap<L2, R2>(fn: (t: L) => Either<L2, R2>): Either<L2, R | R2> {
|
|
26
|
+
return this.fold(
|
|
27
|
+
(l) => fn(l),
|
|
28
|
+
(r) => Either.right(r),
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
leftFlatMapAsync<L2, R2>(fn: (t: L) => PromiseLike<Either<L2, R2>>): EitherP<L2, R | R2> {
|
|
33
|
+
return EitherP.fromPromise(toEitherPromise(this)).leftFlatMapAsync(fn);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Maps the value of this Either if it is a Left, performs no operation if this is a Right.
|
|
38
|
+
*/
|
|
39
|
+
leftMap<L2>(fn: (t: L) => L2): Either<L2, R> {
|
|
40
|
+
return this.fold(
|
|
41
|
+
(l) => Either.left(fn(l)),
|
|
42
|
+
(r) => Either.right(r),
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
leftMapAsync<L2>(fn: (t: L) => Promise<L2>): EitherP<L2, R> {
|
|
47
|
+
return EitherP.fromPromise(toEitherPromise(this)).leftMapAsync(fn);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Applies the provided functions to the value of this Either, depending on whether it is a Right or a Left and returns a new Either.
|
|
52
|
+
*/
|
|
53
|
+
bimap<L2, R2>(leftFn: (l: L) => L2, rightFn: (r: R) => R2): Either<L2, R2> {
|
|
54
|
+
return this.fold(
|
|
55
|
+
(l) => Either.left(leftFn(l)),
|
|
56
|
+
(r) => Either.right(rightFn(r)),
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
bimapAsync<L2, R2>(
|
|
61
|
+
leftFn: (l: L) => Promise<L2>,
|
|
62
|
+
rightFn: (r: R) => Promise<R2>,
|
|
63
|
+
): EitherP<L2, R2> {
|
|
64
|
+
return EitherP.fromPromise(toEitherPromise(this)).bimapAsync(leftFn, rightFn);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Runs the provided function with the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
69
|
+
*/
|
|
70
|
+
tap(fn: (t: R) => void): Either<L, R> {
|
|
71
|
+
return this.flatMap((value) => {
|
|
72
|
+
fn(value);
|
|
73
|
+
return Either.right(value);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
tapAsync(fn: (t: R) => Promise<void>): EitherP<L, R> {
|
|
78
|
+
return EitherP.fromPromise(toEitherPromise(this)).tapAsync(fn);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Runs the provided function with the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
83
|
+
* If the result of the function is a Left, it will be returned, otherwise the original Right value will be returned.
|
|
84
|
+
*/
|
|
85
|
+
flatTap<L2>(fn: (t: R) => Either<L2, void>): Either<L | L2, R> {
|
|
86
|
+
return this.flatMap((value) => fn(value).map(() => value));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
flatTapAsync<L2>(fn: (t: R) => PromiseLike<Either<L2, void>>): EitherP<L | L2, R> {
|
|
90
|
+
return EitherP.fromPromise(toEitherPromise(this)).flatTapAsync(fn);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Flat maps the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
95
|
+
*/
|
|
96
|
+
flatMap<L2, R2>(fn: (t: R) => Either<L2, R2>): Either<L | L2, R2> {
|
|
97
|
+
return this.fold(
|
|
98
|
+
(l) => Either.left(l),
|
|
99
|
+
(r) => fn(r),
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
flatMapAsync<L2, R2>(fn: (t: R) => PromiseLike<Either<L2, R2>>): EitherP<L | L2, R2> {
|
|
104
|
+
return EitherP.fromPromise(toEitherPromise(this)).flatMapAsync(fn);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Applies the provided functions to the value of this Either, depending on whether it is a Right or a Left and returns the result.
|
|
109
|
+
*/
|
|
110
|
+
abstract fold<U1, U2>(leftFn: (l: L) => U1, rightFn: (r: R) => U2): U1 | U2;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Allows to deconstruct the Either using:
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
*
|
|
117
|
+
* ```ts
|
|
118
|
+
* declare const e: Either<string, number>;
|
|
119
|
+
*
|
|
120
|
+
* const [left, right] = e.pair();
|
|
121
|
+
* ```
|
|
122
|
+
*
|
|
123
|
+
*/
|
|
124
|
+
pair(): [Maybe<L>, Maybe<R>] {
|
|
125
|
+
return [this.getLeft(), this.get()];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Returns true if this Either is a Right, false otherwise.
|
|
130
|
+
*/
|
|
131
|
+
isRight(): this is Right<R> {
|
|
132
|
+
return this.fold(
|
|
133
|
+
() => false,
|
|
134
|
+
() => true,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Returns true if this Either is a Left, false otherwise.
|
|
140
|
+
*/
|
|
141
|
+
isLeft(): this is Left<L> {
|
|
142
|
+
return this.fold(
|
|
143
|
+
() => true,
|
|
144
|
+
() => false,
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Gets the right value if this is a Right or undefined if it's a Left.
|
|
150
|
+
*/
|
|
151
|
+
get(): Maybe<R> {
|
|
152
|
+
return this.fold(
|
|
153
|
+
() => undefined,
|
|
154
|
+
(r) => r,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Returns the left value if this is a Left or undefined if it's a Right.
|
|
160
|
+
*/
|
|
161
|
+
getLeft(): Maybe<L> {
|
|
162
|
+
return this.fold(
|
|
163
|
+
(l) => l,
|
|
164
|
+
() => undefined,
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Gets the right value if this is a Right or the result of the provided function if it's a Left.
|
|
170
|
+
*/
|
|
171
|
+
getOrElse<T>(defaultValue: (l: L) => T): R | T {
|
|
172
|
+
return this.fold(
|
|
173
|
+
(l) => defaultValue(l),
|
|
174
|
+
(r) => r,
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// EitherBase is abstract with only Left/Right as concrete subclasses; the cast is always valid.
|
|
180
|
+
function toEitherPromise<L, R>(e: EitherBase<L, R>): Promise<Either<L, R>> {
|
|
181
|
+
return Promise.resolve(e as unknown as Either<L, R>);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export class Left<L> extends EitherBase<L, never> {
|
|
185
|
+
constructor(private readonly value: L) {
|
|
186
|
+
super();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
fold<U1, U2>(leftFn: (l: L) => U1, _rightFn: (r: never) => U2): U1 | U2 {
|
|
190
|
+
return leftFn(this.value);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
override getLeft(): L {
|
|
194
|
+
return this.value;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export class Right<R> extends EitherBase<never, R> {
|
|
199
|
+
constructor(private readonly value: R) {
|
|
200
|
+
super();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
fold<U1, U2>(_leftFn: (l: never) => U1, rightFn: (r: R) => U2): U1 | U2 {
|
|
204
|
+
return rightFn(this.value);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
override get(): R {
|
|
208
|
+
return this.value;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Mimics the [Cats Either[L, R]](https://typelevel.org/cats/datatypes/either.html) type.
|
|
214
|
+
*
|
|
215
|
+
* Either<L, R> is a union of Left<L> and Right<R>, so narrowing works in both directions:
|
|
216
|
+
*
|
|
217
|
+
* ```ts
|
|
218
|
+
* declare const e: Either<string, number>;
|
|
219
|
+
*
|
|
220
|
+
* if (e.isLeft()) {
|
|
221
|
+
* e; // Left<string>
|
|
222
|
+
* } else {
|
|
223
|
+
* e; // Right<number>
|
|
224
|
+
* }
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
export type Either<L, R> = Left<L> | Right<R>;
|
|
228
|
+
|
|
229
|
+
export namespace Either {
|
|
230
|
+
/**
|
|
231
|
+
* Creates a new Left Either with the provided value.
|
|
232
|
+
*/
|
|
233
|
+
export function left<L>(value: L): Either<L, never> {
|
|
234
|
+
return new Left(value);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Creates a new Right Either with the provided value.
|
|
239
|
+
*/
|
|
240
|
+
export function right<R>(value: R): Either<never, R> {
|
|
241
|
+
return new Right(value);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export function fromMaybe<L, R>(value: Maybe<R>, leftValue: () => L): Either<L, R> {
|
|
245
|
+
return isDefined(value) ? Either.right(value) : Either.left(leftValue());
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export function cond<L, R>(bool: boolean, rightFn: () => R, leftFn: () => L): Either<L, R> {
|
|
249
|
+
return bool ? Either.right(rightFn()) : Either.left(leftFn());
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Mimics the [Cats EitherT[Future, L, R]](https://typelevel.org/cats/datatypes/eithert.html) type.
|
|
255
|
+
*/
|
|
256
|
+
export class EitherP<L, R> implements PromiseLike<Either<L, R>> {
|
|
257
|
+
private constructor(private readonly value: PromiseLike<Either<L, R>>) {}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Maps the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
261
|
+
*/
|
|
262
|
+
map<R2>(fn: (t: R) => R2): EitherP<L, R2> {
|
|
263
|
+
return new EitherP(this.value.then((e) => e.map(fn)));
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
mapAsync<R2>(fn: (t: R) => Promise<R2>): EitherP<L, R2> {
|
|
267
|
+
return this.flatMapAsync(async (value) => Either.right(await fn(value)));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Maps the value of this Either if it is a Left, performs no operation if this is a Right.
|
|
272
|
+
*/
|
|
273
|
+
leftMap<L2>(fn: (t: L) => L2): EitherP<L2, R> {
|
|
274
|
+
return new EitherP(this.value.then((e) => e.leftMap(fn)));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
leftMapAsync<L2>(fn: (t: L) => Promise<L2>): EitherP<L2, R> {
|
|
278
|
+
return new EitherP(
|
|
279
|
+
this.value.then(
|
|
280
|
+
async (e) =>
|
|
281
|
+
await e.fold(
|
|
282
|
+
async (l) => Either.left(await fn(l)),
|
|
283
|
+
async (r) => Either.right(r),
|
|
284
|
+
),
|
|
285
|
+
),
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Flat maps the value of this Either if it is a Left, performs no operation if this is a Right.
|
|
291
|
+
*/
|
|
292
|
+
leftFlatMap<L2, R2>(fn: (t: L) => Either<L2, R2>): EitherP<L2, R | R2> {
|
|
293
|
+
return new EitherP(this.value.then((e) => e.leftFlatMap(fn)));
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
leftFlatMapAsync<L2, R2>(fn: (t: L) => PromiseLike<Either<L2, R2>>): EitherP<L2, R | R2> {
|
|
297
|
+
return new EitherP(
|
|
298
|
+
this.value.then<Either<L2, R | R2>>(
|
|
299
|
+
async (e) =>
|
|
300
|
+
await e.fold(
|
|
301
|
+
async (left) => await fn(left),
|
|
302
|
+
async (right) => Either.right(right),
|
|
303
|
+
),
|
|
304
|
+
),
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Applies the provided functions to the value of this Either, depending on whether it is a Right or a Left and returns a new Either.
|
|
310
|
+
*/
|
|
311
|
+
bimap<L2, R2>(leftFn: (l: L) => L2, rightFn: (r: R) => R2): EitherP<L2, R2> {
|
|
312
|
+
return new EitherP(this.value.then((e) => e.bimap(leftFn, rightFn)));
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
bimapAsync<L2, R2>(
|
|
316
|
+
leftFn: (l: L) => Promise<L2>,
|
|
317
|
+
rightFn: (r: R) => Promise<R2>,
|
|
318
|
+
): EitherP<L2, R2> {
|
|
319
|
+
return new EitherP(
|
|
320
|
+
this.value.then(
|
|
321
|
+
async (e) =>
|
|
322
|
+
await e.fold(
|
|
323
|
+
async (l) => Either.left(await leftFn(l)),
|
|
324
|
+
async (r) => Either.right(await rightFn(r)),
|
|
325
|
+
),
|
|
326
|
+
),
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Runs the provided function with the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
332
|
+
*/
|
|
333
|
+
tap(fn: (t: R) => void): EitherP<L, R> {
|
|
334
|
+
return new EitherP(this.value.then((e) => e.tap(fn)));
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
tapAsync(fn: (t: R) => Promise<void>): EitherP<L, R> {
|
|
338
|
+
return this.flatMapAsync(async (value) => {
|
|
339
|
+
await fn(value);
|
|
340
|
+
return Either.right(value);
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Runs the provided function with the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
346
|
+
* If the result of the function is a Left, it will be returned, otherwise the original Right value will be returned.
|
|
347
|
+
*/
|
|
348
|
+
flatTap<L2>(fn: (t: R) => Either<L2, void>): EitherP<L | L2, R> {
|
|
349
|
+
return new EitherP(this.value.then((e) => e.flatTap(fn)));
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
flatTapAsync<L2>(fn: (t: R) => PromiseLike<Either<L2, void>>): EitherP<L | L2, R> {
|
|
353
|
+
return this.flatMapAsync(async (value) => (await fn(value)).map(() => value));
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Flat maps the value of this Either if it is a Right, performs no operation if this is a Left.
|
|
358
|
+
*/
|
|
359
|
+
flatMap<L2, R2>(fn: (t: R) => Either<L2, R2>): EitherP<L | L2, R2> {
|
|
360
|
+
return new EitherP(this.value.then((e) => e.flatMap(fn)));
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
flatMapAsync<L2, R2>(fn: (t: R) => PromiseLike<Either<L2, R2>>): EitherP<L | L2, R2> {
|
|
364
|
+
return new EitherP(
|
|
365
|
+
this.value.then<Either<L | L2, R2>>((e) =>
|
|
366
|
+
e.fold(
|
|
367
|
+
async (left) => Either.left(left),
|
|
368
|
+
(right) => fn(right),
|
|
369
|
+
),
|
|
370
|
+
),
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Applies the provided functions to the value of this Either, depending on whether it is a Right or a Left and returns the result.
|
|
376
|
+
*/
|
|
377
|
+
async fold<U1, U2>(leftFn: (l: L) => U1, rightFn: (r: R) => U2): Promise<U1 | U2> {
|
|
378
|
+
return (await this.value).fold(leftFn, rightFn);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Allows to deconstruct the Either using:
|
|
383
|
+
*
|
|
384
|
+
* @example
|
|
385
|
+
*
|
|
386
|
+
* ```ts
|
|
387
|
+
* declare const e: EitherP<string, number>;
|
|
388
|
+
*
|
|
389
|
+
* const [left, right] = await e.pair();
|
|
390
|
+
* ```
|
|
391
|
+
*
|
|
392
|
+
*/
|
|
393
|
+
async pair(): Promise<[Maybe<L>, Maybe<R>]> {
|
|
394
|
+
return [await this.getLeft(), await this.get()];
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Returns true if this Either is a Right, false otherwise.
|
|
399
|
+
*/
|
|
400
|
+
async isRight(): Promise<boolean> {
|
|
401
|
+
return (await this.value).isRight();
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Returns true if this Either is a Left, false otherwise.
|
|
406
|
+
*/
|
|
407
|
+
async isLeft(): Promise<boolean> {
|
|
408
|
+
return !(await this.isRight());
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Gets the right value if this is a Right or undefined if it's a Left.
|
|
413
|
+
*/
|
|
414
|
+
async get(): Promise<Maybe<R>> {
|
|
415
|
+
return (await this.value).get();
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Returns the left value if this is a Left or undefined if it's a Right.
|
|
420
|
+
*/
|
|
421
|
+
async getLeft(): Promise<Maybe<L>> {
|
|
422
|
+
return (await this.value).getLeft();
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Gets the right value if this is a Right or the result of the provided function if it's a Left.
|
|
427
|
+
*/
|
|
428
|
+
async getOrElse<T>(defaultValue: (l: L) => T): Promise<R | T> {
|
|
429
|
+
return (await this.value).getOrElse(defaultValue);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Creates a new Left EitherP with the provided value.
|
|
434
|
+
*/
|
|
435
|
+
static left<L>(value: Promise<L>): EitherP<L, never> {
|
|
436
|
+
return new EitherP(value.then((v) => Either.left(v)));
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Creates a new Right EitherP with the provided value.
|
|
441
|
+
*/
|
|
442
|
+
static right<R>(value: Promise<R>): EitherP<never, R> {
|
|
443
|
+
return new EitherP(value.then((v) => Either.right(v)));
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
static fromMaybe<L, R>(value: Promise<Maybe<R>>, leftValue: () => Promise<L>): EitherP<L, R> {
|
|
447
|
+
return new EitherP(
|
|
448
|
+
value.then(async (v) => (isDefined(v) ? Either.right(v) : Either.left(await leftValue()))),
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* @deprecated
|
|
454
|
+
*/
|
|
455
|
+
static fromEither<L, R>(either: PromiseLike<Either<L, R>>): EitherP<L, R> {
|
|
456
|
+
return new EitherP(either);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
static fromPromise<L, R>(either: PromiseLike<Either<L, R>>): EitherP<L, R> {
|
|
460
|
+
return new EitherP(either);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
static cond<L, R>(
|
|
464
|
+
bool: Promise<boolean>,
|
|
465
|
+
rightFn: () => Promise<R>,
|
|
466
|
+
leftFn: () => Promise<L>,
|
|
467
|
+
): EitherP<L, R> {
|
|
468
|
+
return new EitherP(
|
|
469
|
+
bool.then(async (b) => (b ? Either.right(await rightFn()) : Either.left(await leftFn()))),
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// oxlint-disable-next-line unicorn/no-thenable -- Deliberately implementing PromiseLike to allow for `await` usage on EitherP instances.
|
|
474
|
+
then<U>(onfulfilled?: (value: Either<L, R>) => U | PromiseLike<U>): PromiseLike<U> {
|
|
475
|
+
return this.value.then(onfulfilled);
|
|
476
|
+
}
|
|
477
|
+
}
|
package/src/index.ts
ADDED
package/src/maybe.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export type Maybe<T> = T | undefined;
|
|
2
|
+
|
|
3
|
+
export function mapMaybe<T, U>(value: Maybe<T>, fn: (value: T) => U): Maybe<U> {
|
|
4
|
+
return value === undefined ? undefined : fn(value);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function isDefined<T>(value: Maybe<T>): value is T {
|
|
8
|
+
return value !== undefined;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function flattenMaybe<T>(value: Maybe<Maybe<T>>): Maybe<T> {
|
|
12
|
+
return mapMaybe(value, (v) => v);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function ifTrue<T>(value: boolean, fn: () => T): Maybe<T> {
|
|
16
|
+
return value ? fn() : undefined;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function ifFalse<T>(value: boolean, fn: () => T): Maybe<T> {
|
|
20
|
+
return !value ? fn() : undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function matchPair<A, B, R>(
|
|
24
|
+
[a, b]: [Maybe<A>, Maybe<B>],
|
|
25
|
+
cases: {
|
|
26
|
+
neither: () => R;
|
|
27
|
+
a: (a: A) => R;
|
|
28
|
+
b: (b: B) => R;
|
|
29
|
+
both: (a: A, b: B) => R;
|
|
30
|
+
},
|
|
31
|
+
): R {
|
|
32
|
+
if (!isDefined(a)) {
|
|
33
|
+
if (!isDefined(b)) {
|
|
34
|
+
return cases.neither();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return cases.b(b);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!isDefined(b)) {
|
|
41
|
+
return cases.a(a);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return cases.both(a, b);
|
|
45
|
+
}
|