Skip to content

Commit ba7d8b1

Browse files
Wolfremium13Marius9595
authored andcommitted
feat(either): add future interoperability
1 parent f024f32 commit ba7d8b1

File tree

3 files changed

+76
-1
lines changed

3 files changed

+76
-1
lines changed

src/either/either.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { Monad } from '../monad';
22
import { Matchable } from '../match';
3+
import { Future } from '../future';
4+
import { Futurizable } from '../future/futurizable';
35

46
/**
57
* Abstract class representing a value that can be one of two possible types.
68
* @template L The type of the left value.
79
* @template R The type of the right value.
810
*/
9-
abstract class Either<L, R> implements Monad<R>, Matchable<R, L> {
11+
abstract class Either<L, R> implements Monad<R>, Matchable<R, L>, Futurizable<L | R> {
1012
/**
1113
* Creates a `Right` instance.
1214
* @template T The type of the right value.
@@ -141,6 +143,19 @@ abstract class Either<L, R> implements Monad<R>, Matchable<R, L> {
141143
* console.log(result.isRight()); // true
142144
*/
143145
abstract isRight(): this is Right<L, R>;
146+
147+
/**
148+
* Converts this `Either` instance into a `Future` instance.
149+
* @returns {Future<L | R>} A `Future` instance containing the value.
150+
* @example
151+
* const result = Either.right(5);
152+
* const asyncClosure: async (x: number) => x * 2
153+
* result.toFuture().map(asyncClosure).complete(
154+
async (value) => expect(await value).toEqual(expected), // 10
155+
async (error) => expect(error).toBeUndefined()
156+
);
157+
*/
158+
abstract toFuture(): Future<L | R>;
144159
}
145160

146161
/**
@@ -184,6 +199,10 @@ class Left<L, R> extends Either<L, R> {
184199
isRight(): this is Right<L, never> {
185200
return false;
186201
}
202+
203+
toFuture(): Future<L> {
204+
return Future.of(() => Promise.resolve(this.value));
205+
}
187206
}
188207

189208
/**
@@ -227,6 +246,10 @@ class Right<L, R> extends Either<L, R> {
227246
isRight(): this is Right<never, R> {
228247
return true;
229248
}
249+
250+
toFuture(): Future<R> {
251+
return Future.of(() => Promise.resolve(this.value));
252+
}
230253
}
231254

232255
export { Either, Right, Left };

src/future/futurizable.test.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { describe, it, expect } from 'vitest';
2+
import { Either } from '../either';
3+
import { Future } from './future';
4+
5+
const testCasesFutureMapOperation = [
6+
{
7+
type: 'Either Right',
8+
monad: Either.right(2),
9+
assertion: (futureMonad: Future<number> | Future<string>, expected: Future<number> | Future<string>) => {
10+
futureMonad.complete(
11+
(currentValue: number | string) => {
12+
expected.complete(
13+
(expectedValue: number | string) => expect(currentValue).toBe(expectedValue),
14+
(error) => expect(error).toBeUndefined()
15+
);
16+
},
17+
(error) => expect(error).toBeUndefined()
18+
);
19+
},
20+
expected: Future.of(() => Promise.resolve(2)),
21+
},
22+
{
23+
type: 'Either Left',
24+
monad: Either.left('Error'),
25+
assertion: (futureMonad: Future<number> | Future<string>, expected: Future<number> | Future<string>) => {
26+
futureMonad.complete(
27+
(currentValue: number | string) => {
28+
expected.complete(
29+
(expectedValue: number | string) => expect(currentValue).toBe(expectedValue),
30+
(error) => expect(error).toBeUndefined()
31+
);
32+
},
33+
(error) => expect(error).toBeUndefined()
34+
);
35+
},
36+
expected: Future.of(() => Promise.resolve('Error')),
37+
},
38+
];
39+
40+
describe('Futurizable', () => {
41+
it.each(testCasesFutureMapOperation)(
42+
'$type should handle toFuture correctly',
43+
async ({ monad, expected, assertion }) => {
44+
assertion(monad.toFuture(), expected);
45+
}
46+
);
47+
});

src/future/futurizable.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { Future } from './future';
2+
3+
export interface Futurizable<T> {
4+
toFuture(): Future<T>;
5+
}

0 commit comments

Comments
 (0)