@daisugi/anzen
TypeScript icon, indicating that this package has built-in type declarations

0.4.0 • Public • Published

@daisugi/anzen

version npm downloads bundlephobia

This project is part of the @daisugi monorepo.

Anzen helps write safe code without exceptions, taking roots from Rust's Result and Haskell's Either.

🌟 Features

  • 💡 Minimum size overhead.
  • ⚡️ Written in TypeScript.
  • 📦 Only uses trusted dependencies.
  • 🔨 Powerful and agnostic to your code.
  • 🧪 Well tested.
  • 🤝 Is used in production.
  • ⚡️ Exports ES Modules as well as CommonJS.

Usage

import { Result } from '@daisugi/anzen';
import { readFileSync } from 'node:fs';

function readFile(path) {
  try {
    const response = readFileSync(path);
    return Result.success(response);
  } catch (err) {
    return Result.failure(err);
  }
}

// This line may fail unexpectedly without warnings.
const text = readFile('test.txt');

if (text.isFailure) {
  return text.getError();
}

return text.getValue();

Table of contents

Install

Using npm:

npm install @daisugi/anzen

Using yarn:

yarn add @daisugi/anzen

🔝 back to top

Motivation

This library was created to address certain requirements that were not being fully met by other libraries of the same type, some libraries only partially met the requirements, while others fulfilled everything but also came with unnecessary overhead for the project.

If you are looking for a library that meets any of the following requirements, feel free to use this library. However, there are many other good libraries out there that implement the Result pattern, such as True-Myth or Folktale, that you can also use.

  • ✅ Early failures in invalid operations.
  • ✅ Can be written in a cleaner style, avoiding the need for chains.
  • ✅ Provides better TypeScript typing.
  • ✅ Keeps the API simple and does not try to mimic the Rust API or any other, but includes enough features to cover the most common use cases in the JavaScript world.

🔝 back to top

#success(value)

Creates the successful variant instance of the Result, representing a successful outcome from an operation which may fail.

Usage

import { Result } from '@daisugi/anzen';

const res = Result.success('foo');

🔝 back to top

#failure(err)

Creates the failure variant instance of the Result, representing a failure outcome from an operation which may fail.

Usage

import { Result } from '@daisugi/anzen';

const res = Result.failure('err');

🔝 back to top

#isSuccess/#isFailure

Properties that indicates if the Result is a success or failure instance.

Usage

import { Result } from '@daisugi/anzen';

const res = Result.success('foo');
res.isSuccess;
// true
res.isFailure;
// false

const errRes = Result.failure('err');
errRes.isSuccess;
// false
errRes.isFailure;
// true

🔝 back to top

#getValue()

Returns an value when comes from a success Result, and throws an error if comes from a failure instance.

Usage

import { Result } from '@daisugi/anzen';

Result.success('foo').getValue();
// 'foo'

🔝 back to top

#getError()

Returns an error value when comes from a failure Result, and throws an error if comes from a success instance.

Usage

import { Result } from '@daisugi/anzen';

Result.failure('err').getError();
// 'err'

🔝 back to top

#getOrElse(value)

If the Result is a success, the function returns the value; if it's a failure, it returns the provided value.

Usage

import { Result } from '@daisugi/anzen';

Result.failure('err').getOrElse('foo');
// 'foo'

🔝 back to top

#map(fn)

Map over a Result instance, apply the callback to the Result value and returns an success instance, and the same failure instance if maps over a failure.

Usage

import { Result } from '@daisugi/anzen';

Result.success('foo')
  .map((value) => value)
  .getValue();
// 'foo'

🔝 back to top

#chain(fn)

Map over a Result instance, apply the callback to the Result value and returns it, and the same failure instance if maps over a failure.

Usage

import { Result } from '@daisugi/anzen';

Result.success('foo')
  .chain((value) => Result.success(value))
  .getValue();
// 'foo'

#elseChain(fn)

Map over a Result instance as in each and get out the value if result is success, or apply a function (elseChain) to the value wrapped in the failure to get a default value.

Usage

import { Result } from '@daisugi/anzen';

Result.failure('err')
  .elseChain((err) => Result.success('foo'))
  .getValue();
// 'foo'

🔝 back to top

#elseMap(fn)

Map over a Result instance as in map and get out the value if result is success, or apply a function (elseChain) to the value wrapped in the failure to get a default value.

Usage

import { Result } from '@daisugi/anzen';

Result.failure('err')
  .elseMap((err) => 'foo')
  .getValue();
// 'foo'

#unsafeUnwrap()

Retrieves the value/error from the Result, it can extract the value/error from a success or failure instances.

Usage

import { Result } from '@daisugi/anzen';

Result.failure('err').unsafeUnwrap();
// 'err'

🔝 back to top

#toJSON()

Useful to serialize to JSON a Result instance.

Usage

import { Result } from '@daisugi/anzen';

Result.success('foo').toJSON();
// '{ "value": "foo", "isSuccess": true }'

Result.failure('err').toJSON();
// '{ "error": "err", "isSuccess": false }'

🔝 back to top

#fromJSON(json)

Useful to deserialize from JSON Result instance like.

Usage

import { Result } from '@daisugi/anzen';

Result.fromJSON('{ "value": "foo", "isSuccess": true }')
  .getValue();
// 'foo'

🔝 back to top

#promiseAll(fns)

A wrapper over Promise.all which helps work with promises whose returns a Result instances.

Usage

import { Result } from '@daisugi/anzen';

Result.promiseAll([
  async () => Result.success('foo')
])
  .getValue();
// ['foo']

In case of failure:

import { Result } from '@daisugi/anzen';

Result.promiseAll([
  async () => Result.failure('foo')
])
  .getError();
// 'foo'

🔝 back to top

#fromThrowable(fn, parseErr)

This function executes an asynchronous function that could potentially raise an exception. It returns a success Result containing the function's return value if it executes successfully. Otherwise, it returns a failure Result containing the raised exception.

Usage

import { Result } from '@daisugi/anzen';

await Result.fromThrowable(
  async () => throw new Error('err'),
  (err) => err.message,
)
  .getError();
// 'err'

🔝 back to top

#fromSyncThrowable(fn, parseErr)

This function is similar to fromThrowable, but it requires a synchronous function to be provided.

Usage

import { Result } from '@daisugi/anzen';

Result.fromSyncThrowable(
  () => throw new Error('err'),
  (err) => err.message,
)
  .getError();
// 'err'

🔝 back to top

TypeScript

The Anzen is fully written in TypeScript, therefore you have available some types.

import {
  Result,
  type AnzenResultAny,
  type AnzenResultSuccess,
  type AnzenResultFailure,
} from '@daisugi/anzen';

function foo(): AnzenResultSuccess<string> {
  return Result.success('foo');
}

function bar(): AnzenResultFailure<string> {
  return Result.failure('foo');
}

function baz(): AnzenAnyResult<string, number> {
  if ((Math.random() * 10) % 2 === 0) {
    return Result.success(11);
  }
  return Result.failure('foo')
}

🔝 back to top

Goal

The goal is to create an abstraction over errors that simplifies reasoning and ensures predictable results, thereby avoiding unexpected exceptions.

🔝 back to top

Other projects

Meet the ecosystem

🔝 back to top

License

MIT

Package Sidebar

Install

npm i @daisugi/anzen

Weekly Downloads

34

Version

0.4.0

License

MIT

Unpacked Size

38.1 kB

Total Files

10

Last publish

Collaborators

  • sviridoff
  • mawrkus