Skip to content

Commit

Permalink
Merge pull request #53 from wookieb/either-from-try
Browse files Browse the repository at this point in the history
feat: Implement 'fromTry' for 'Either'
  • Loading branch information
JSMonk authored Apr 2, 2023
2 parents 459c3e2 + 1fbc091 commit 2aa70e8
Show file tree
Hide file tree
Showing 4 changed files with 1,560 additions and 1,228 deletions.
22 changes: 19 additions & 3 deletions either/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const user = getUser(1).map(({ email }) => email);
- [`left`](#left)
- [`right`](#right)
- [`from`](#from)
- [`fromTry`](#fromtry)
- [`isEither`](#iseither)
- [`Either#isLeft`](#eitherisleft)
- [`Either#isRight`](#eitherisright)
Expand Down Expand Up @@ -200,6 +201,21 @@ function from<R>(value: R): Either<never, R>;
from(2); // Either<never, number>.Right
```

#### `fromTry`

Returns `Right` with function result or `Left` if function execution throws an error.

```typescript
function fromTry<L, R>(fn: () => R): Either<L, R>;
```

```typescript
fromTry(() => 2); // Either<never, number>.Right
fromTry(() => {
throw new Error("test");
}); // Either<Error, never>.Left
```

#### `isEither`

```typescript
Expand Down Expand Up @@ -478,9 +494,9 @@ const { value } = left(new Error()); // Error
```

```typescript
right(2).unwrap() // number
left(new TypeError()).unwrap() // throws value (TypeError)
left(2).unwrap() // throws 2 (don't do this)
right(2).unwrap(); // number
left(new TypeError()).unwrap(); // throws value (TypeError)
left(2).unwrap(); // throws 2 (don't do this)
```

## License
Expand Down
10 changes: 9 additions & 1 deletion either/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,14 @@ class EitherConstructor<L, R, T extends EitherType = EitherType>
return EitherConstructor.right(v);
}

static fromTry<L, R>(fn: () => R): Either<L, R> {
try {
return EitherConstructor.right(fn());
} catch (e) {
return EitherConstructor.left(e);
}
}

static right<L = never, T = never>(v: T): Either<L, T> {
return new EitherConstructor<L, T, EitherType.Right>(EitherType.Right, v);
}
Expand Down Expand Up @@ -308,7 +316,7 @@ class EitherConstructor<L, R, T extends EitherType = EitherType>

export type Either<L, R> = EitherConstructor<L, R, EitherType.Right> | EitherConstructor<L, R, EitherType.Left>;

export const { merge, mergeInOne, mergeInMany, left, right, from, chain } = EitherConstructor;
export const { merge, mergeInOne, mergeInMany, left, right, from, fromTry, chain } = EitherConstructor;

export const isEither = <L, R>(value: unknown | Either<L, R>): value is Either<L, R> =>
value instanceof EitherConstructor;
13 changes: 13 additions & 0 deletions tests/either.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as fc from "fast-check";
import { Either, left, merge, right } from "@sweet-monads/either";
import { fromTry } from "../either";

describe("Either", () => {
test("merge generic", () =>
Expand Down Expand Up @@ -62,4 +63,16 @@ describe("Either", () => {
expect(v1.unwrap()).toBe(2);
expect(() => v2.unwrap()).toThrow(new Error("Either state is Left"));
});

test("fromTry", () => {
const error = new Error("test");
const v1 = fromTry(() => 1);
const v2 = fromTry(() => {
throw error;
});

expect(v1.unwrap()).toBe(1);
expect(v2.value).toBe(error);
expect(v2.isLeft()).toBe(true);
});
});
Loading

0 comments on commit 2aa70e8

Please sign in to comment.