New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

neverthrow

Package Overview
Dependencies
Maintainers
1
Versions
62
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

neverthrow - npm Package Compare versions

Comparing version 2.2.1 to 2.3.0

dist/result-async.d.ts

18

dist/chain.js
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());

@@ -37,3 +38,2 @@ });

};
var _this = this;
exports.__esModule = true;

@@ -51,3 +51,3 @@ var toPromise = function (val) {

};
exports.chain = function (r1, r2) { return __awaiter(_this, void 0, void 0, function () {
exports.chain = function (r1, r2) { return __awaiter(void 0, void 0, void 0, function () {
var inner, mapped;

@@ -66,3 +66,3 @@ return __generator(this, function (_a) {

}); };
exports.chain3 = function (r1, r2, r3) { return __awaiter(_this, void 0, void 0, function () {
exports.chain3 = function (r1, r2, r3) { return __awaiter(void 0, void 0, void 0, function () {
var r2Promise, chained, mapped;

@@ -83,3 +83,3 @@ return __generator(this, function (_a) {

}); };
exports.chain4 = function (r1, r2, r3, r4) { return __awaiter(_this, void 0, void 0, function () {
exports.chain4 = function (r1, r2, r3, r4) { return __awaiter(void 0, void 0, void 0, function () {
var r3Promise, chained, mapped;

@@ -100,3 +100,3 @@ return __generator(this, function (_a) {

}); };
exports.chain5 = function (r1, r2, r3, r4, r5) { return __awaiter(_this, void 0, void 0, function () {
exports.chain5 = function (r1, r2, r3, r4, r5) { return __awaiter(void 0, void 0, void 0, function () {
var r4Promise, chained, mapped;

@@ -117,3 +117,3 @@ return __generator(this, function (_a) {

}); };
exports.chain6 = function (r1, r2, r3, r4, r5, r6) { return __awaiter(_this, void 0, void 0, function () {
exports.chain6 = function (r1, r2, r3, r4, r5, r6) { return __awaiter(void 0, void 0, void 0, function () {
var r5Promise, chained, mapped;

@@ -134,3 +134,3 @@ return __generator(this, function (_a) {

}); };
exports.chain7 = function (r1, r2, r3, r4, r5, r6, r7) { return __awaiter(_this, void 0, void 0, function () {
exports.chain7 = function (r1, r2, r3, r4, r5, r6, r7) { return __awaiter(void 0, void 0, void 0, function () {
var r6Promise, chained, mapped;

@@ -151,3 +151,3 @@ return __generator(this, function (_a) {

}); };
exports.chain8 = function (r1, r2, r3, r4, r5, r6, r7, r8) { return __awaiter(_this, void 0, void 0, function () {
exports.chain8 = function (r1, r2, r3, r4, r5, r6, r7, r8) { return __awaiter(void 0, void 0, void 0, function () {
var r7Promise, chained, mapped;

@@ -154,0 +154,0 @@ return __generator(this, function (_a) {

export { Result, ok, Ok, err, Err } from './result';
export { ResultAsync, okAsync, errAsync } from './result-async';
export { chain, chain3, chain4, chain5, chain6, chain7, chain8 } from './chain';

@@ -8,2 +8,6 @@ "use strict";

exports.Err = result_1.Err;
var result_async_1 = require("./result-async");
exports.ResultAsync = result_async_1.ResultAsync;
exports.okAsync = result_async_1.okAsync;
exports.errAsync = result_async_1.errAsync;
var chain_1 = require("./chain");

@@ -10,0 +14,0 @@ exports.chain = chain_1.chain;

@@ -0,1 +1,2 @@

import { ResultAsync } from './';
export declare type Result<T, E> = Ok<T, E> | Err<T, E>;

@@ -11,4 +12,5 @@ export declare const ok: <T, E>(value: T) => Ok<T, E>;

mapErr<U>(_f: (e: E) => U): Result<T, U>;
andThen<U>(f: (t: T) => ResultAsync<U, E>): ResultAsync<U, E>;
andThen<U>(f: (t: T) => Result<U, E>): Result<U, E>;
asyncMap<U>(f: (t: T) => Promise<U>): Promise<Result<U, E>>;
asyncMap<U>(f: (t: T) => Promise<U>): ResultAsync<U, E>;
match: <A>(ok: (t: T) => A, _err: (e: E) => A) => A;

@@ -26,3 +28,4 @@ _unsafeUnwrap(): T;

andThen<U>(_f: (t: T) => Result<U, E>): Result<U, E>;
asyncMap<U>(_f: (t: T) => Promise<U>): Promise<Result<U, E>>;
andThen<U>(_f: (t: T) => ResultAsync<U, E>): Result<U, E>;
asyncMap<U>(_f: (t: T) => Promise<U>): ResultAsync<U, E>;
match: <A>(_ok: (t: T) => A, err: (e: E) => A) => A;

@@ -29,0 +32,0 @@ _unsafeUnwrap(): T;

"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
exports.__esModule = true;
var _1 = require("./");
// eslint-disable-next-line @typescript-eslint/no-use-before-define

@@ -64,5 +30,2 @@ exports.ok = function (value) { return new Ok(value); };

};
// add info on how this is really useful for converting a
// Result<Result<T, E2>, E1>
// into a Result<T, E2>
Ok.prototype.andThen = function (f) {

@@ -72,13 +35,3 @@ return f(this.value);

Ok.prototype.asyncMap = function (f) {
return __awaiter(this, void 0, void 0, function () {
var newInner;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, f(this.value)];
case 1:
newInner = _a.sent();
return [2 /*return*/, exports.ok(newInner)];
}
});
});
return _1.ResultAsync.fromPromise(f(this.value));
};

@@ -121,7 +74,3 @@ Ok.prototype._unsafeUnwrap = function () {

Err.prototype.asyncMap = function (_f) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, exports.err(this.error)];
});
});
return _1.errAsync(this.error);
};

@@ -128,0 +77,0 @@ Err.prototype._unsafeUnwrap = function () {

{
"name": "neverthrow",
"version": "2.2.1",
"version": "2.3.0",
"description": "Stop throwing errors, and instead return Results!",

@@ -26,16 +26,17 @@ "main": "dist/index.js",

"devDependencies": {
"@babel/core": "^7.4.3",
"@babel/preset-env": "^7.4.3",
"@babel/preset-typescript": "^7.3.3",
"@types/jest": "^24.0.11",
"@typescript-eslint/eslint-plugin": "^2.21.0",
"@typescript-eslint/parser": "^2.21.0",
"babel-jest": "^24.7.1",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.0",
"eslint-plugin-prettier": "^3.1.2",
"jest": "^24.7.1",
"prettier": "^1.19.1",
"ts-jest": "^24.0.2",
"typescript": "3.4.2"
"@babel/core": "7.4.3",
"@babel/preset-env": "7.4.3",
"@babel/preset-typescript": "7.3.3",
"@types/jest": "24.0.11",
"@types/node": "^14.0.4",
"@typescript-eslint/eslint-plugin": "2.21.0",
"@typescript-eslint/parser": "2.21.0",
"babel-jest": "24.7.1",
"eslint": "6.8.0",
"eslint-config-prettier": "6.10.0",
"eslint-plugin-prettier": "3.1.2",
"jest": "24.7.1",
"prettier": "1.19.1",
"ts-jest": "24.0.2",
"typescript": "3.8.3"
},

@@ -42,0 +43,0 @@ "keywords": [

@@ -1,7 +0,5 @@

# NeverThrow 🙅
[![Build Status](https://travis-ci.com/gDelgado14/neverthrow.svg?branch=master)](https://travis-ci.com/gDelgado14/neverthrow)
[![Build Status](https://travis-ci.com/supermacro/neverthrow.svg?branch=master)](https://travis-ci.com/supermacro/neverthrow)
## Description

@@ -13,6 +11,8 @@

`neverthrow` also exposes an api for chaining sequential asynchronous tasks ([docs below](#chaining-api)).
For asynchronous tasks, `neverthrow` offers a `ResultAsync` class which wraps a `Promise<Result>` and enables chaining.
`ResultAsync` is `thenable` meaning it behaves exactly like a native `Promise<Result>`: the underlying `Result` can be accessed using the `await` or `.then()` operators.
[Read the blog post](https://gdelgado.ca/type-safe-error-handling-in-typescript.html#title) which explains *why you'd want to use this package*.
`neverthrow` also exposes `chain(...)` methods for chaining asynchronous tasks in a functional style ([docs below](#chaining-api)). However, these methods might be deprecated in the future. It is advised to use the `ResultAsync` instead.
[Read the blog post](https://gdelgado.ca/type-safe-error-handling-in-typescript.html#title) which explains _why you'd want to use this package_.

@@ -23,3 +23,2 @@ This package works for both JS and TypeScript. However, the types that this package provides will allow you to get compile-time guarantees around error handling if you are using TypeScript.

> Need to see real-life examples of how to leverage this package for error handling? See this repo: https://github.com/parlez-vous/server

@@ -33,8 +32,6 @@

## Usage
### Synchronous API
## Usage
Create `Ok` or `Err` instances with the `ok` and `err` functions.

@@ -65,9 +62,6 @@

`Result` is defined as follows:
```typescript
type Result<T, E>
= Ok<T, E>
| Err<T, E>
type Result<T, E> = Ok<T, E> | Err<T, E>
```

@@ -79,2 +73,61 @@

---
### Asynchronous API
Asynchronous methods can return a `ResultAsync` type instead of a `Promise<Result>` in order to enable further chaining.
`ResultAsync` is `thenable` meaning it behaves exactly like a native `Promise<Result>`: the underlying `Result` can be accessed using the `await` or `.then()` operators.
This is useful for handling multiple asynchronous apis like database queries, timers, http requests, ...
Example:
```typescript
import { errAsync, ResultAsync } from 'neverthrow'
import { insertIntoDb } from 'imaginary-database'
// Let's assume insertIntoDb has the following signature:
// insertIntoDb(user: User): Promise<User>
// We can create a synchronous method that returns a ResultAsync
function addUserToDatabase(user: User): ResultAsync<User, Error> {
if (user.name.length < 3) {
// Throw a async result from a synchronous block thanks to the errAsync helper
return errAsync(new Error('Username is too short'))
}
// Wrap the async method into a ResultAsync thanks to fromPromise
// The seconds argument catches the error from the promise
return ResultAsync.fromPromise(insertIntoDb(user), () => new Error('Database error'))
}
// We can now call the method above
const asyncRes = addUserToDatabase({ name: 'Tom' }) // asyncRes is a `ResultAsync<User, Error>`
// We can chain the ResultAsync to build another ResultAsync (see full api below)
const asyncRes2 = asyncRes.map((user: User) => user.name) // asyncRes2 is a `ResultAsync<string, Error>`
// A ResultAsync acts exactly like a Promise<Result>
// It can be transformed back into a Result just like a Promise would:
// using await
const res = await asyncRes
// res is a Result<string, Error>
if (res.isErr()) {
console.log('Oops fail: ' + res.error.message)
} else {
console.log('Successfully inserted user ' + res.value)
}
// using then
asyncRes.then(res => {
// res is Result<string, Error>
if (res.isErr()) {
console.log('Oops fail: ' + res.error.message)
} else {
console.log('Successfully inserted user ' + res.value)
}
})
```
## Top-Level API

@@ -89,2 +142,5 @@

- `Result` type - only available in TypeScript
- `ResultAsync` class
- `okAsync` convenience function to create a `ResultAsync` containing an `Ok` type `Result`
- `errAsync` convenience function to create a `ResultAsync` containing an `Err` type `Result`
- `chain` and all of its variants ([docs below](#chaining-api)) - for chaining sequential asynchronous operations that return `Result`s

@@ -96,15 +152,5 @@

// chain api available as well
import {
chain,
chain3,
chain4,
chain5,
chain6,
chain7,
chain8
} from 'neverthrow'
import { chain, chain3, chain4, chain5, chain6, chain7, chain8 } from 'neverthrow'
```
## Accessing the value inside of a Result

@@ -121,3 +167,2 @@

const example1 = ok(123)

@@ -132,3 +177,2 @@ const example2 = err('abc')

if (example2.isErr()) {

@@ -141,3 +185,2 @@ // you now have access to example2.error

## API

@@ -150,2 +193,3 @@

**Signature:**
```typescript

@@ -156,2 +200,3 @@ ok<T, E>(value: T): Ok<T, E> { ... }

**Example:**
```typescript

@@ -173,2 +218,3 @@ import { ok } from 'neverthrow'

**Signature:**
```typescript

@@ -179,2 +225,3 @@ err<T, E>(err: E): Err<T, E> { ... }

**Example:**
```typescript

@@ -189,3 +236,2 @@ import { err } from 'neverthrow'

---

@@ -198,2 +244,3 @@

**Signature:**
```typescript

@@ -210,2 +257,3 @@ isOk(): boolean { ... }

**Signature**:
```typescript

@@ -215,6 +263,4 @@ isErr(): boolean { ... }

---
### `Result.map` (method)

@@ -227,2 +273,3 @@

**Signature:**
```typescript

@@ -233,4 +280,4 @@ type MapFunc = <T>(f: T) => U

**Example**:
**Example**:
```typescript

@@ -254,3 +301,3 @@ const { getLines } from 'imaginary-parser'

---
---

@@ -264,2 +311,3 @@ ### `Result.mapErr` (method)

**Signature:**
```typescript

@@ -270,5 +318,4 @@ type MapFunc = <E>(e: E) => F

**Example**:
**Example**:
```typescript

@@ -296,4 +343,7 @@ import { parseHeaders } 'imaginary-http-parser'

Same idea as `map` above. Except you must return a new `Result`.
Same idea as `map` above. Except you must return a new `Result` or `ResultAsync`.
If the provided method returns a `Result` the returned value will be a `Result`.
If the provided method returns a `ResultAsync` the returned value will be a `ResultAsync`.
This is useful for when you need to do a subsequent computation using the inner `T` value, but that computation might fail.

@@ -304,9 +354,15 @@

**Signature:**
```typescript
type ExtendFunc = (t: T) => Result<U, E>
extend<U>(f: ExtendFunc): Result<U, E> { ... }
type AndThenFunc = (t: T) => Result<U, E>
andThen<U>(f: AndThenFunc): Result<U, E> { ... }
type AndThenAsyncFunc = (t: T) => ResultAsync<U, E>
andThen<U>(f: AndThenAsyncFunc): ResultAsync<U, E> { ... }
```
**Example 1: Chaining Results**
**Example 1: Chaining Results**
```typescript

@@ -317,12 +373,19 @@ import { err, ok } from 'neverthrow'

ok(2).andThen(sq).andThen(sq) // Ok(16)
ok(2)
.andThen(sq)
.andThen(sq) // Ok(16)
ok(2).andThen(sq).andThen(err) // Err(4)
ok(2)
.andThen(sq)
.andThen(err) // Err(4)
ok(2).andThen(err).andThen(sq) // Err(2)
ok(2)
.andThen(err)
.andThen(sq) // Err(2)
err(3).andThen(sq).andThen(sq) // Err(3)
err(3)
.andThen(sq)
.andThen(sq) // Err(3)
```
**Example 2: Flattening Nested Results**

@@ -338,3 +401,2 @@

---

@@ -349,2 +411,3 @@

**Signature:**
```typescript

@@ -357,6 +420,4 @@ match<A>(

`match` is like chaining `map` and `mapErr`, with the distinction that with `match` both functions must have the same return type.
**Example:**

@@ -379,17 +440,10 @@

// error handling
result
.map(successCallback)
.mapErr(failureCallback)
result.map(successCallback).mapErr(failureCallback)
// match api
// works exactly the same as above,
// except, now you HAVE to do error handling :)
myval.match(
successCallback,
failureCallback
)
myval.match(successCallback, failureCallback)
```
---

@@ -400,6 +454,7 @@

Similar to `map` except for two things:
- the mapping function must return a `Promise`
- asyncMap returns a `Promise`
- asyncMap returns a `ResultAsync`
**Check out the `chain` API**. If you need to chain multiple `Promise<Result>` type of computations together, `chain` is what you need. `asyncMap` is only suitable for doing a single async computation, not many sequential computations.
You can then chain the result of `asyncMap` using the `ResultAsync` apis (like `map`, `mapErr`, `andThen`, etc.)

@@ -410,3 +465,3 @@ **Signature:**

type MappingFunc = (t: T) => Promise<U>
asyncMap<U>(fn: MappingFunc): Promise<Result<U, E>> { ... }
asyncMap<U>(fn: MappingFunc): ResultAsync<U, E> { ... }
```

@@ -421,3 +476,3 @@

const promise = parseHeaders(rawHeader)
const asyncRes = parseHeaders(rawHeader)
.map(headerKvMap => headerKvMap.Authorization)

@@ -427,8 +482,263 @@ .asyncMap(findUserInDatabase)

Note that in the above example if `parseHeaders` returns an `Err` then `.map` and `.asyncMap` will not be invoked, and `promise` variable will contain a `Err` inside of the promise.
Note that in the above example if `parseHeaders` returns an `Err` then `.map` and `.asyncMap` will not be invoked, and `asyncRes` variable will resolve to an `Err` when turned into a `Result` using `await` or `.then()`.
---
### `okAsync`
Constructs an `Ok` variant of `ResultAsync`
**Signature:**
```typescript
okAsync<T, E>(value: T): ResultAsync<T, E>
```
**Example:**
```typescript
import { okAsync } from 'neverthrow'
const myResultAsync = okAsync({ myData: 'test' }) // instance of `ResultAsync`
const myResult = await myResultAsync // instance of `Ok`
myResult.isOk() // true
myResult.isErr() // false
```
---
### `errAsync`
Constructs an `Err` variant of `ResultAsync`
**Signature:**
```typescript
errAsync<T, E>(err: E): ResultAsync<T, E>
```
**Example:**
```typescript
import { errAsync } from 'neverthrow'
const myResultAsync = errAsync('Oh nooo') // instance of `ResultAsync`
const myResult = await myResultAsync // instance of `Err`
myResult.isOk() // false
myResult.isErr() // true
```
---
### `ResultAsync.fromPromise` (method)
Transforms a `Promise<T>` into a `ResultAsync<T, E>`.
The second argument handles the rejection case of the promise. If it is ommited, **the code might throw** because `neverthrow` does not know if the promise you are passing to `fromPromise` has any promise rejection logic associated to it (via a `.catch` method call or `catch (err) {}` block).
**Signature:**
```typescript
fromPromise<U, E>(p: Promise<U>, f?: (e: unknown) => E): ResultAsync<U, E> { ... }
```
**Example**:
```typescript
import { insertIntoDb } from 'imaginary-database'
// insertIntoDb(user: User): Promise<User>
const res = ResultAsync.fromPromise(insertIntoDb(myUser), () => new Error('Database error'))
// res has a type of ResultAsync<User, Error>
```
---
### `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.
The applied function can be synchronous or asynchronous (returning a `Promise<U>`) with no impact to the return type.
This function can be used to compose the results of two functions.
**Signature:**
```typescript
type MapFunc = <T>(f: T | Promise<T>) => U
map<U>(fn: MapFunc): ResultAsync<U, E> { ... }
```
**Example**:
```typescript
const { findUsersIn } from 'imaginary-database'
// ^ assume findUsersIn has the following signature:
// findUsersIn(country: string): ResultAsync<Array<User>, Error>
const usersInCanada = findUsersIn("Canada")
// Let's assume we only need their names
const namesInCanada = usersInCanada.map((users: Array<User>) => users.map(user => user.name))
// namesInCanada is of type ResultAsync<Array<string>, Error>
// We can extract the Result using .then() or await
namesInCanada.then((namesResult: Result<Array<string>, Error>) => {
if(namesResult.isErr()){
console.log("Couldn't get the users from the database", namesResult.error)
}
else{
console.log("Users in Canada are named: " + namesResult.value.join(','))
}
})
```
---
### `ResultAsync.mapErr` (method)
Maps a `ResultAsync<T, E>` to `ResultAsync<T, F>` by applying a function to a contained `Err` value, leaving an `Ok` value untouched.
The applied function can be synchronous or asynchronous (returning a `Promise<F>`) with no impact to the return type.
This function can be used to pass through a successful result while handling an error.
**Signature:**
```typescript
type MapFunc = <E>(e: E) => F | Promise<F>
mapErr<U>(fn: MapFunc): ResultAsync<T, F> { ... }
```
**Example**:
```typescript
const { findUsersIn } from 'imaginary-database'
// ^ assume findUsersIn has the following signature:
// findUsersIn(country: string): ResultAsync<Array<User>, Error>
// Let's say we need to low-level errors from findUsersIn to be more readable
const usersInCanada = findUsersIn("Canada").mapErr((e: Error) => {
// The only error we want to pass to the user is "Unknown country"
if(e.message === "Unknown country"){
return e.message
}
// All other errors will be labelled as a system error
return "System error, please contact an administrator."
})
// usersInCanada is of type ResultAsync<Array<User>, string>
usersInCanada.then((usersResult: Result<Array<User>, string>) => {
if(usersResult.isErr()){
res.status(400).json({
error: usersResult.error
})
}
else{
res.status(200).json({
users: usersResult.value
})
}
})
```
---
### `ResultAsync.andThen` (method)
Same idea as `map` above. Except the applied function must return a `Result` or `ResultAsync`.
`ResultAsync.andThen` always returns a `ResultAsync` no matter the return type of the applied function.
This is useful for when you need to do a subsequent computation using the inner `T` value, but that computation might fail.
`andThen` is really useful as a tool to flatten a `ResultAsync<ResultAsync<A, E2>, E1>` into a `ResultAsync<A, E2>` (see example below).
**Signature:**
```typescript
type AndThenFunc = (t: T) => ResultAsync<U, E> | Result<U, E>
andThen<U>(f: AndThenFunc): ResultAsync<U, E> { ... }
```
**Example**
```typescript
const { validateUser } from 'imaginary-validator'
const { insertUser } from 'imaginary-database'
const { sendNotification } from 'imaginary-service'
// ^ assume validateUser, insertUser and sendNotification have the following signatures:
// validateUser(user: User): Result<User, Error>
// insertUser(user): ResultAsync<User, Error>
// sendNotification(user): ResultAsync<void, Error>
const resAsync = validateUser(user)
.andThen(insertUser)
.andThen(sendNotification)
// resAsync is a ResultAsync<void, Error>
resAsync.then((res: Result<void, Error>) => {
if(res.isErr()){
console.log("Oops, at least one step failed", res.error)
}
else{
console.log("User has been validated, inserted and notified successfully.")
}
})
```
---
### `ResultAsync.match` (method)
Given 2 functions (one for the `Ok` variant and one for the `Err` variant) execute the function that matches the `ResultAsync` variant.
The difference with `Result.match` is that it always returns a `Promise` because of the asynchronous nature of the `ResultAsync`.
**Signature:**
```typescript
match<A>(
okFn: (t: T) => A,
errFn: (e: E) => A
): Promise<A> => { ... }
```
**Example:**
```typescript
const { validateUser } from 'imaginary-validator'
const { insertUser } from 'imaginary-database'
// ^ assume validateUser and insertUser have the following signatures:
// validateUser(user: User): Result<User, Error>
// insertUser(user): ResultAsync<User, Error>
// Handle both cases at the end of the chain using match
const resultMessage = await validateUser(user)
.andThen(insertUser)
.match((user: User) => `User ${user.name} has been successfully created`,
(e: Error) => `User could not be created because ${e.message}`)
// resultMessage is a string
```
---
# 🔗
## Chaining API
> Disclaimer: the preferred solution to chaining asynchronous tasks is `ResultAsync`.
> The following method might be deprecated in the future.
tldr: `chain` is the `.andThen` equivalent for `Result`s wrapped inside of a `Promise`.

@@ -461,13 +771,10 @@

// ...
chain4(
sessionManager.getSessionUser(),
({ id }) => getSingleSite(id, siteId),
fetchSiteWithComments,
(siteWithComments) => Promise.resolve(
ok(buildSite(siteWithComments))
),
)
chain4(
sessionManager.getSessionUser(),
({ id }) => getSingleSite(id, siteId),
fetchSiteWithComments,
siteWithComments => Promise.resolve(ok(buildSite(siteWithComments))),
)
```
### `chain`

@@ -485,2 +792,3 @@

The above in plain english:
- given a computation `r1`

@@ -490,3 +798,2 @@ - evaluate `r2` with the `Ok` value of `r1` as r2`'s argument.

### `chain3`

@@ -521,3 +828,2 @@

### `chain5`

@@ -539,3 +845,2 @@

### `chain6`

@@ -558,3 +863,2 @@

### `chain7`

@@ -578,3 +882,2 @@

### `chain8`

@@ -601,6 +904,5 @@

## Wrapping a Dependency that throws
> incomplete documenation ...
> incomplete documenation ...
> Examples to come soon

@@ -611,6 +913,2 @@

## A note on the Package Name

@@ -617,0 +915,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc