neverthrow
Advanced tools
Comparing version 6.1.0 to 6.2.0
{ | ||
"name": "neverthrow", | ||
"version": "6.1.0", | ||
"version": "6.2.0", | ||
"description": "Stop throwing errors, and instead return Results!", | ||
@@ -34,2 +34,3 @@ "main": "dist/index.cjs.js", | ||
"@babel/preset-typescript": "7.16.7", | ||
"@tsconfig/node14": "^1.0.3", | ||
"@types/jest": "27.4.1", | ||
@@ -36,0 +37,0 @@ "@types/node": "14.17.4", |
146
README.md
@@ -0,1 +1,4 @@ | ||
> Seeking co-maintainers: I don't have much time to maintain this project these days. If someone would like to jump in and become a co-maintainer, it would be appreciated! | ||
> See https://github.com/supermacro/neverthrow/issues/531 | ||
# NeverThrow 🙅 | ||
@@ -45,2 +48,3 @@ | ||
- [`errAsync`](#errasync) | ||
- [`ResultAsync.fromThrowable` (static class method)](#resultasyncfromthrowable-static-class-method) | ||
- [`ResultAsync.fromPromise` (static class method)](#resultasyncfrompromise-static-class-method) | ||
@@ -59,2 +63,3 @@ - [`ResultAsync.fromSafePromise` (static class method)](#resultasyncfromsafepromise-static-class-method) | ||
- [`fromThrowable`](#fromthrowable) | ||
- [`fromAsyncThrowable`](#fromasyncthrowable) | ||
- [`fromPromise`](#frompromise) | ||
@@ -116,2 +121,3 @@ - [`fromSafePromise`](#fromsafepromise) | ||
ResultAsync, | ||
fromAsyncThrowable, | ||
fromThrowable, | ||
@@ -670,3 +676,3 @@ fromPromise, | ||
**⚠️ You must use `.safeUnwrap` in a generator context with `safeTry`** | ||
**⚠️ You must use `.safeUnwrap` in a generator context with `safeTry`**. Please see [safeTry](#safeTry). | ||
@@ -736,2 +742,43 @@ Allows for unwrapping a `Result` or returning an `Err` implicitly, thereby reducing boilerplate. | ||
#### `ResultAsync.fromThrowable` (static class method) | ||
Similar to [Result.fromThrowable](#resultfromthrowable-static-class-method), but for functions that return a `Promise`. | ||
**Example**: | ||
```typescript | ||
import { ResultAsync } from 'neverthrow' | ||
import { insertIntoDb } from 'imaginary-database' | ||
// insertIntoDb(user: User): Promise<User> | ||
const insertUser = ResultAsync.fromThrowable(insertIntoDb, () => new Error('Database error')) | ||
// `res` has a type of (user: User) => ResultAsync<User, Error> | ||
``` | ||
Note that this can be safer than using [ResultAsync.fromPromise](#resultasyncfrompromise-static-class-method) with | ||
the result of a function call, because not all functions that return a `Promise` are `async`, and thus they can throw | ||
errors synchronously rather than returning a rejected `Promise`. For example: | ||
```typescript | ||
// NOT SAFE !! | ||
import { ResultAsync } from 'neverthrow' | ||
import { db } from 'imaginary-database' | ||
// db.insert<T>(table: string, value: T): Promise<T> | ||
const insertUser = (user: User): Promise<User> => { | ||
if (!user.id) { | ||
// this throws synchronously! | ||
throw new TypeError('missing user id') | ||
} | ||
return db.insert('users', user) | ||
} | ||
// this will throw, NOT return a `ResultAsync` | ||
const res = ResultAsync.fromPromise(insertIntoDb(myUser), () => new Error('Database error')) | ||
``` | ||
[⬆️ Back to top](#toc) | ||
--- | ||
#### `ResultAsync.fromPromise` (static class method) | ||
@@ -814,3 +861,2 @@ | ||
[⬆️ Back to top](#toc) | ||
@@ -1149,3 +1195,3 @@ | ||
**⚠️ You must use `.safeUnwrap` in a generator context with `safeTry`** | ||
**⚠️ You must use `.safeUnwrap` in a generator context with `safeTry`**. Please see [safeTry](#safeTry). | ||
@@ -1167,2 +1213,9 @@ Allows for unwrapping a `Result` or returning an `Err` implicitly, thereby reducing boilerplate. | ||
#### `fromAsyncThrowable` | ||
Top level export of `ResultAsync.fromSafePromise`. | ||
Please find documentation at [ResultAsync.fromThrowable](#resultasyncfromthrowable-static-class-method) | ||
[⬆️ Back to top](#toc) | ||
#### `fromPromise` | ||
@@ -1182,9 +1235,86 @@ | ||
#### `safeTry` | ||
Used to implicityly return errors and reduce boilerplate. | ||
Used to implicitly return errors and reduce boilerplate. | ||
See https://github.com/supermacro/neverthrow/pull/448 and https://github.com/supermacro/neverthrow/issues/444 | ||
Let's say we are writing a function that returns a `Result`, and in that function we call some functions which also return `Result`s and we check those results to see whether we should keep going or abort. Usually, we will write like the following. | ||
```typescript | ||
declare function mayFail1(): Result<number, string>; | ||
declare function mayFail2(): Result<number, string>; | ||
function myFunc(): Result<number, string> { | ||
// We have to define a constant to hold the result to check and unwrap its value. | ||
const result1 = mayFail1(); | ||
if (result1.isErr()) { | ||
return err(`aborted by an error from 1st function, ${result1.error}`); | ||
} | ||
const value1 = result1.value | ||
// Again, we need to define a constant and then check and unwrap. | ||
const result2 = mayFail2(); | ||
if (result2.isErr()) { | ||
return err(`aborted by an error from 2nd function, ${result2.error}`); | ||
} | ||
const value2 = result2.value | ||
// And finally we return what we want to calculate | ||
return ok(value1 + value2); | ||
} | ||
``` | ||
Basically, we need to define a constant for each result to check whether it's a `Ok` and read its `.value` or `.error`. | ||
With safeTry, we can state 'Return here if its an `Err`, otherwise unwrap it here and keep going.' in just one expression. | ||
```typescript | ||
declare function mayFail1(): Result<number, string>; | ||
declare function mayFail2(): Result<number, string>; | ||
function myFunc(): Result<number, string> { | ||
return safeTry<number, string>(function*() { | ||
return ok( | ||
// If the result of mayFail1().mapErr() is an `Err`, the evaluation is | ||
// aborted here and the enclosing `safeTry` block is evaluated to that `Err`. | ||
// Otherwise, this `(yield* ...)` is evaluated to its `.value`. | ||
(yield* mayFail1() | ||
.mapErr(e => `aborted by an error from 1st function, ${e}`) | ||
.safeUnwrap()) | ||
+ | ||
// The same as above. | ||
(yield* mayFail2() | ||
.mapErr(e => `aborted by an error from 2nd function, ${e}`) | ||
.safeUnwrap()) | ||
) | ||
}) | ||
} | ||
``` | ||
To use `safeTry`, the points are as follows. | ||
* Wrap the entire block in a [generator function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) | ||
* In that block, you can use `yield* <RESULT>` to state 'Return `<RESULT>` if it's an `Err`, otherwise evaluate to its `.value`' | ||
* Pass the generator function to `safeTry` | ||
You can also use [async generator function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function*) to pass an async block to `safeTry`. | ||
```typescript | ||
// You can use either Promise<Result> or ResultAsync. | ||
declare function mayFail1(): Promise<Result<number, string>>; | ||
declare function mayFail2(): ResultAsync<number, string>; | ||
function myFunc(): Promise<Result<number, string>> { | ||
return safeTry<number, string>(async function*() { | ||
return ok( | ||
// You have to await if the expression is Promise<Result> | ||
(yield* (await mayFail1()) | ||
.mapErr(e => `aborted by an error from 1st function, ${e}`) | ||
.safeUnwrap()) | ||
+ | ||
// You can call `safeUnwrap` directly if its ResultAsync | ||
(yield* mayFail2() | ||
.mapErr(e => `aborted by an error from 2nd function, ${e}`) | ||
.safeUnwrap()) | ||
) | ||
}) | ||
} | ||
``` | ||
For more information, see https://github.com/supermacro/neverthrow/pull/448 and https://github.com/supermacro/neverthrow/issues/444 | ||
[⬆️ Back to top](#toc) | ||
@@ -1241,1 +1371,5 @@ | ||
With all that said, there are definitely good use cases for throwing in your program. But much less than you might think. | ||
### License | ||
The neverthrow project is available as open source under the terms of the [MIT license](https://github.com/supermacro/neverthrow/blob/master/LICENSE). |
Empty package
Supply chain riskPackage does not contain any code. It may be removed, is name squatting, or the result of a faulty package publish.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
1366
44201
22
3
0
2