Skip to content

Commit 04db8a3

Browse files
committed
feat(3.0.0-rc.4): add getsEither to effect.ts
There are cases where getting from state and returning a raw Either or Promise<Either> are useful in effect.ts. The getEither function works as this constructor.
1 parent d83d74b commit 04db8a3

File tree

3 files changed

+82
-1
lines changed

3 files changed

+82
-1
lines changed

deno.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@baetheus/fun",
3-
"version": "3.0.0-rc.3",
3+
"version": "3.0.0-rc.4",
44
"exports": {
55
"./applicable": "./applicable.ts",
66
"./array": "./array.ts",

effect.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,51 @@ export function getsSecond<S extends unknown[], B>(
842842
return async (...s) => [E.left(await fsa.apply(fsa, s)), ...s];
843843
}
844844

845+
/**
846+
* Extract an Either value from the current state using a function. Unlike
847+
* `gets` which always returns a Right (success), or `getsSecond` which always
848+
* returns a Left (error), `getsEither` allows the function to return either
849+
* a Left or a Right based on the state. The state is passed through unchanged.
850+
*
851+
* This is useful when you need to perform validation or conditional logic on
852+
* the state that can result in either success or failure.
853+
*
854+
* @example
855+
* ```ts
856+
* import * as Eff from "./effect.ts";
857+
* import * as E from "./either.ts";
858+
*
859+
* // Synchronous Either
860+
* const validatePositive = Eff.getsEither((n: number) =>
861+
* n > 0 ? E.right(n * 2) : E.left("Number must be positive")
862+
* );
863+
*
864+
* const result1 = await validatePositive(21);
865+
* // [E.right(42), 21]
866+
*
867+
* const result2 = await validatePositive(-5);
868+
* // [E.left("Number must be positive"), -5]
869+
*
870+
* // Asynchronous Either
871+
* const asyncValidate = Eff.getsEither((n: number) =>
872+
* Promise.resolve(n > 0 ? E.right(n * 2) : E.left("Must be positive"))
873+
* );
874+
*
875+
* const result3 = await asyncValidate(21);
876+
* // [E.right(42), 21]
877+
*
878+
* const result4 = await asyncValidate(-5);
879+
* // [E.left("Must be positive"), -5]
880+
* ```
881+
*
882+
* @since 3.0.0-rc.4
883+
*/
884+
export function getsEither<S extends unknown[], A, B>(
885+
fsab: (...s: S) => Either<B, A> | Promise<Either<B, A>>,
886+
): Effect<S, B, A, S> {
887+
return async (...s) => [await fsab.apply(fsab, s), ...s];
888+
}
889+
845890
/**
846891
* Transform the current state using a function. The transformed value
847892
* becomes both the success value and the new state.

testing/effect.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,3 +744,39 @@ Deno.test("Effect mapEither composition with other operations", async () => {
744744
const result = await effect("state");
745745
assertEquals(result, [E.right(60), "state"]);
746746
});
747+
748+
Deno.test("Effect getsEither with Right output", async () => {
749+
const validatePositive = Effect.getsEither((n: number) =>
750+
n > 0 ? E.right(n * 2) : E.left("Number must be positive")
751+
);
752+
753+
const result = await validatePositive(21);
754+
assertEquals(result, [E.right(42), 21]);
755+
});
756+
757+
Deno.test("Effect getsEither with Left output", async () => {
758+
const validatePositive = Effect.getsEither((n: number) =>
759+
n > 0 ? E.right(n * 2) : E.left("Number must be positive")
760+
);
761+
762+
const result = await validatePositive(-5);
763+
assertEquals(result, [E.left("Number must be positive"), -5]);
764+
});
765+
766+
Deno.test("Effect getsEither with Promise<Right> output", async () => {
767+
const asyncValidate = Effect.getsEither((n: number) =>
768+
Promise.resolve(n > 0 ? E.right(n * 2) : E.left("Must be positive"))
769+
);
770+
771+
const result = await asyncValidate(21);
772+
assertEquals(result, [E.right(42), 21]);
773+
});
774+
775+
Deno.test("Effect getsEither with Promise<Left> output", async () => {
776+
const asyncValidate = Effect.getsEither((n: number) =>
777+
Promise.resolve(n > 0 ? E.right(n * 2) : E.left("Must be positive"))
778+
);
779+
780+
const result = await asyncValidate(-5);
781+
assertEquals(result, [E.left("Must be positive"), -5]);
782+
});

0 commit comments

Comments
 (0)