Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ For asynchronous tasks, `neverthrow` offers a `ResultAsync` class which wraps a
- [`ResultAsync.fromThrowable` (static class method)](#resultasyncfromthrowable-static-class-method)
- [`ResultAsync.fromPromise` (static class method)](#resultasyncfrompromise-static-class-method)
- [`ResultAsync.fromSafePromise` (static class method)](#resultasyncfromsafepromise-static-class-method)
- [`ResultAsync.fromPromiseResult` (static class method)](#resultasyncfrompromiseresult-static-class-method)
- [`ResultAsync.map` (method)](#resultasyncmap-method)
- [`ResultAsync.mapErr` (method)](#resultasyncmaperr-method)
- [`ResultAsync.unwrapOr` (method)](#resultasyncunwrapor-method)
Expand All @@ -66,6 +67,7 @@ For asynchronous tasks, `neverthrow` offers a `ResultAsync` class which wraps a
- [`fromAsyncThrowable`](#fromasyncthrowable)
- [`fromPromise`](#frompromise)
- [`fromSafePromise`](#fromsafepromise)
- [`fromPromiseResult`](#frompromiseresult)
- [`safeTry`](#safetry)
+ [Testing](#testing)
* [A note on the Package Name](#a-note-on-the-package-name)
Expand Down Expand Up @@ -124,6 +126,7 @@ import {
fromThrowable,
fromPromise,
fromSafePromise,
fromPromiseResult,
safeTry,
} from 'neverthrow'
```
Expand Down Expand Up @@ -1038,6 +1041,46 @@ export const signupHandler = route<User>((req, sessionManager) =>

---

#### `ResultAsync.fromPromiseResult` (static class method)

`ResultAsync.fromPromiseResult` wraps a function returning `Promise<Result<T, E>>` returning function, returning a function with the same signature, expect returning an `ResultAsync<T, E>`. This is particularly useful combined with `async` functions since you cannot return `ResultAsync<T, E>` directly, though you desire to.

**Signature:**

```typescript
// fromPromiseResult is a static class method
// also available as a standalone function
// import { fromPromiseResult } from 'neverthrow'
ResultAsync.fromPromiseResult = <A extends readonly any[], T, E>(
fn: (...args: A) => Promise<Result<T, E>>,
) => (...args: A): ResultAsync<T, E>
```

**Example**:

```typescript
export const callApi: ResultAsync<Person[], Error> = ResultAsync.fromPromiseResult(async (postId: number): Promise<Result<Person[], Error>> => {
try {
const post = await fetch(`/api/posts/${id}`).then(resp => !resp.ok ? Promise.reject(resp) : resp);
const query = post.comments.map(c => c.commenterId).join(',');
const people = await fetch(`/api/people?ids=${query}`).then(resp => !resp.ok ? Promise.reject(resp) : resp);
return ok(people);
} catch(e) {
return err(e as Error);
}
});

const people: Person[] = await callApi(123)
.orElse(e => {
console.error(e);
return [];
});
```

[⬆️ Back to top](#toc)

---

#### `ResultAsync.map` (method)

Maps a `ResultAsync<T, E>` to `ResultAsync<U, E>` by applying a function to a contained `Ok` value, leaving an `Err` value untouched.
Expand Down
8 changes: 8 additions & 0 deletions src/result-async.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ export class ResultAsync<T, E> implements PromiseLike<Result<T, E>> {
}
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
static fromPromiseResult = <A extends readonly any[], T, E>(
fn: (...args: A) => Promise<Result<T, E>>,
) => (...args: A): ResultAsync<T, E> => {
return ResultAsync.fromThrowable(fn, (e) => e as E)(...args).andThen((x) => x)
}

static combine<
T extends readonly [ResultAsync<unknown, unknown>, ...ResultAsync<unknown, unknown>[]]
>(asyncResultList: T): CombineResultAsyncs<T>
Expand Down Expand Up @@ -260,6 +267,7 @@ export const fromPromise = ResultAsync.fromPromise
export const fromSafePromise = ResultAsync.fromSafePromise

export const fromAsyncThrowable = ResultAsync.fromThrowable
export const fromPromiseResult = ResultAsync.fromPromiseResult

// Combines the array of async results into one result.
export type CombineResultAsyncs<
Expand Down