An open API service indexing awesome lists of open source software.

https://github.com/jamashita/genitore

Asynchronous optional/result monad
https://github.com/jamashita/genitore

asynchronous monad optional result typescript

Last synced: 3 months ago
JSON representation

Asynchronous optional/result monad

Awesome Lists containing this project

README

        

# Genitore

This package contains Optional monad and Result monad that support asynchronously.

[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org)
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)

[![CI](https://github.com/jamashita/genitore/actions/workflows/ci.yml/badge.svg)](https://github.com/jamashita/genitore/actions/workflows/ci.yml)

## Install

```text
yarn add @jamashita/genitore
```

## Prerequisite

```
> node -v
v20.12.2

> npm -v
10.5.0

> yarn -v
1.22.21
```

## Conventional commit

```
git cz
```

# Heisenberg classes

## Absent\

A class that represents the fulfilled state for `Heisenberg`, but with the absence of a value. It means the value is
`null` or `undefined`. It is equivalent to None for Optional types and it implements `Heisenberg` interface.

## Lost\

A class that represents the rejected state for `Heisenberg`. This class contains an exception for the operation that
occurred. It implements `Heisenberg` interface.

## Present\

A class that represents the fulfilled state for `Heisenberg`. This class contains a value of type `P` that cannot be
`null` or `undefined`. It is equivalent to Some for Optional types. It implements `Heisenberg` interface.

## Uncertain\

A class that represents the pending state for `Heisenberg`. It implements `Heisenberg` interface.

## (interface) Heisenberg\

This interface represents an Optional of Monad programming. The common interface
for `Absent

`, `Lost

`, `Present

` and `Uncertain

`. This interface provides common methods for the value
presence and absence. `P` represents the type of the data.

### `Heisenberg.all

(heisenbergs: Iterable>): Heisenberg>`

Takes an `Iterable>` and returns a single `Heisenberg>`. Returns `Present>` when
all `heisenbergs` are in the `Present` state, returns `Absent>` when at least one of `heisenbergs` is in
the `Absent` state, and returns `Lost>` when at least one of `heisenbergs` is in the `Lost`state. If there are
both `Absent` and `Lost` states present in the `heisenbergs`, the return value will be `Lost>` (prioritized).

### `Heisenberg.prototype.get(): Exclude

`

Retrieves the retained value. If this instance is `Present`, the returned value will be a non-null, non-undefined value
of type `P`. If this instance is `Absent` or `Uncertain`, `HeisenbergError` will be thrown. If this instance is `Lost`,
the retained `cause` will be thrown.

### `Heisenberg.prototype.getState(): HeisenbergState`

Returns the current state. The state can be one of the following statuses: `'ABSENT'`, `'LOST'`, `'PRESENT'`
or `'UNCERTAIN'`.

### `Heisenberg.prototype.ifAbsent(consumer: Consumer): this`

Executes the given `consumer` if this class instance is the `Absent` state.

### `Heisenberg.prototype.ifLost(consumer: Consumer): this`

Executes the given `consumer` with the internal `cause` value of `unknown` type if this class instance is in the `Lost`
state.

### `Heisenberg.prototype.ifPresent(consumer: Consumer>): this`

Executes the given `consumer` with the internal non-null, non-undefined value of `P` type if this class instance
is in the `Present` state.

### `Heisenberg.prototype.isAbsent(): this is Absent

`

Returns `true` if this class instance is in the `Absent` state, `false` otherwise.

### `Heisenberg.prototype.isLost(): this is Lost

`

Returns `true` if this class instance is in the `Lost` state, `false` otherwise.

### `Heisenberg.prototype.isPresent(): this is Present

`

Returns `true` if this class instance is in the `Present` state, `false` otherwise.

# Schrödinger classes

## Alive\

A class that represents the fulfilled state for `Schrodinger`. It is equivalent to Success for Result types. It implements `Schrodinger` class.

## Contradiction\

A class that represents the rejected state for `Schrodinger`. This class contains an exception for the operation that
occurred. It implements `Schrodinger` interface.

## Dead\

A class that represents the fulfilled state for `Schrodinger`, but with an intended error of type `D`. It is equivalent
to Failure for Result types and it implements `Schrodinger` interface.

## Still\

A class that represents the pending state for `Schrodinger`. It implements `Schrodinger` interface.

## (interface) Schrodinger\

This interface represents an Result of Monad programming. The common interface
for `Alive
`, `Contradiction`, `Dead` and `Still`. This interface provides common methods for
success and failure. `A` represents the type of the data and `D` represents the type of the error that may be thrown.

### `Schrodinger.all(schrodingers: Iterable>): Schrodinger, D>`

Takes an `Iterable>` and returns a single `Schrodinger, D>`. Returns `Alive, D>`
when all `schrodingers` are in the `Alive` state, returns `Dead, D>` when at least one of `schrodingers` is in
the `Dead` state, and returns `Contradiction, D>` when at least one of `schrodingers` is in the `Contradiction`
state. If there are both `Dead` and `Contradiction` states present in the `schrodingers`, the return value will
be `Contradiction, D>` (prioritized).

### `Schrodinger.prototype.get(): A`

Returns the retained value.

Retrieves the retained value. If this instance is `Alive`, the returned value will be a non-error value of type `A`. If
this instance is `Dead`, the retained error will be thrown. If this instance is `Contradiction`, the retained `cause`
will be thrown. If this instance is `Still`, `SchrodingerError` will be thrown.

### `Schrodinger.prototype.getState(): SchrodingerState`

Returns the current state. The state can be one of the following statuses: `'ALIVE'`, `'CONTRADICTION'`, `'DEAD'`
or `'STILL'`.

### `Schrodinger.prototype.ifAlive(consumer: Consumer): this`

Executes the given `consumer` with the non-error value of `A` type if this class instance is in the `Alive` state.

### `Schrodinger.prototype.ifContradiction(consumer: Consumer): this`

Executes the given `consumer` with the internal `cause` value of `unknown` type if this class instance is in
the `Contradiction` state.

### `Schrodinger.prototype.ifDead(consumer: Consumer): this`

Executes the given `consumer` with the error value of `D` type if this class instance is in the `Dead` state.

### `Schrodinger.prototype.isAlive(): this is Alive`

Returns `true` if this class instance is in the `Alive` state, `false` otherwise.

### `Schrodinger.prototype.isContradiction(): this is Contradiction`

Returns `true` if this class instance is in the `Contradiction` state, `false` otherwise.

### `Schrodinger.prototype.isDead(): this is Dead`

Returns `true` if this class instance is in the `Dead` state, `false` otherwise.

# Superposition classes

## (interface) Chrono\

### `Chrono.prototype.accept(valye: M>): unknown`

### `Chrono.prototype.decline(value: R): unknown`

### `Chrono.prototype.throw(cause: unknown): unknown`

## Superposition\

A class that handles Result of Monad programming asynchronously. This class wraps a `Schrodinger` instance, which
represents the outcome of an asynchronous operation, and can change its state based on the outcome of that operation.

Like `Promise`, the Superposition class can handle multiple states, but it is more finely divided than `Promise`. The
possible states are:

- Successfully fulfilled: corresponds to a fulfilled state of `Promise`.
- Unsuccessfully fulfilled: corresponds to a rejected state of `Promise`, but only for expected errors.
- Rejected: corresponds to a rejected state of `Promise`, but for unexpected errors.
- Pending: corresponds to a pending state of `Promise`.

### `Superposition.all(superpositions: Iterable>): Superposition, D>`

Takes an `Iterable>` and returns a single `Superposition, D>`. If all `superpositions` are
in the `Alive` state, the returned instance will be successfully fulfilled with an array of the values from the
`superpositions`. If at least one of `superpositions` is in the `Dead` state, the returned instance will be
unsuccessfully fulfilled with the error from the first `Dead` state encountered. If at least one of `superpositions` is
in the `Contradiction` state, the returned instance will be rejected with the cause from the first `Contradiction` state
encountered. If there are both `Dead` and `Contradiction` states present in the `superpositions`, the returned instance
will be rejected (prioritized).

### `Superposition.anyway(superpositions: Iterable>): Promise>>`

Retrieves the outcome of each asynchronous operation in `superpositions` by
calling `Superposition.prototype.terminate()` on each item. The resulting `Schrodinger` state for each `Superposition`
can be found in the documentation for `Superposition.prototype.terminate()`.

### `Superposition.of(func: Consumer, D>>): Superposition, D>`

Generates a new `Superposition` instance by invoking the provided `func` argument with a `Chrono` object. If
the `Chrono.prototype.accept(value)` is called with a valid value of `Awaited
` type, it returns a successfully
fulfilled `Superposition
`. If the `Chrono.prototype.decline(error)` is called with an error of type `D`, it returns an unsuccessfully
fulfilled `Superposition
`. If
the `Chrono.prototype.throw(cause)` is called with an argument of `unknown` type, it returns a
rejected `Superposition
`.

```ts
// let value is type of A or PromiseLike

Superposition.of
((chrono: Chrono, D>) => {
try {
if (value.isValid()) {
chrono.accept(value);

return;
}

chrono.decline(value.error);
}
catch (e: unknown) {
if (e instanceof RuntimeError) {
chrono.decline(e);

return;
}

chrono.throw(e);
}
});
```

### `Superposition.ofSchrodinger(schrodinger: Schrodinger, D>): Superposition, D>`

Creates a new `Superposition` instance from a given `Schrodinger` instance. If the given `schrodinger` is in the `Alive` state, the
resulting `Superposition` will be successfully fulfilled. If it is in the `Dead` state, it will be unsuccessfully
fulfilled. If it is in the `Contradiction` or `Still` state, it will be rejected.

### `Superposition.ofSuperposition(superposition: ISuperposition): Superposition`

Generates a new `Superposition` instance from a given `Superposition` instance.

### `Superposition.prototype.get(): Promise>`

Retrieves the outcome of the asynchronous operation as a `Promise`. If the instance is in the successfully fulfilled
state, it will return a fulfilled `Promise` instance. If the instance is in the unsuccessfully fulfilled or rejected
state, it will return a rejected `Promise` instance.

### `Superposition.prototype.ifAlive(consumer: Consumer): this`

Executes the given `consumer` with the non-error value of `A` type if the asynchronous operation is going to be
successfully fulfilled.

### `Superposition.prototype.ifContradiction(consumer: Consumer): this`

Executes the given `consumer` with the internal `cause` value of `unknown` type if the asynchronous operation is going
to be rejected.

### `Superposition.prototype.ifDead(consumer: Consumer): this`

Executes the given `consumer` with the error value of `D` type if the asynchronous operation is going to be
unsuccessfully fulfilled.

### `Superposition.prototype.map(mapper: UnaryFunction>): Superposition`

Executes the given `mapper` only when the current instance is in a successfully fulfilled state. The `mapper` should
take in a single argument of type `A` and should return a value of type `B` without an error, or an
instance of `ISuperposition`, a `PromiseLike`, or a `PromiseLike>`.
The return value of this method will be a `Superposition` instance if the `mapper` is executed and returns a value
or `Superposition` without error, otherwise it will return a `Superposition` instance if the `mapper` is not
executed or the returned value contain an error. The overall result will be a `Superposition` instance.

This method can be used as an alternative to `Promise.prototype.then()`.

```ts
superposition.map((num: number) => {
return num.toFixed();
}).map((str: string) => {
const num = Number(str);

if (Number.isNaN(num)) {
throw new TypeError('NaN');
}

return num;
});
```

### `Superposition.prototype.pass(accepted: Consumer, declinded: Consumer, thrown: Consumer): this`

Executes the given `accepted` with the non-error value of type `A` when the asynchronous operation is successfully
fulfilled, `declined` with the error value of type `D` when the asynchronous operation is unsuccessfully fulfilled, or
`thrown` with the internal `cause` value of type `unknown` when the asynchronous operation is rejected.

### `Superposition.prototype.peek(peek: Peek): this`

Executes the given `peek` with no arguments when the asynchronous operation represented by the current superposition
instance is completed, regardless of whether it is successfully fulfilled, unsuccessfully fulfilled, or rejected. It
allows you to perform side effects, such as logging, without changing the outcome of the operation.

### `Superposition.prototype.recover(mapper: UnaryFunction, SReturnType>): Superposition`

Executes the given `mapper` only when the current instance is in an unsuccessfully fulfilled state. The `mapper` should
take in a single argument of type `D` and should return a value of type `B` without an error, or an instance of
`ISuperposition`, a `PromiseLike`, or a `PromiseLike>`. The return value
of this method will be a `Superposition` instance if the `mapper` is executed and returns a value
or `Superposition` without error, otherwise it will return a `Superposition
` instance if the `mapper` is not
executed or the returned value contains an error. The overall result will be a `Superposition
` instance.

This method can be used as an alternative to `Promise.prototype.catch()`.

```ts
superposition.map((num: number) => {
return num.toFixed();
}).map((str: string) => {
const num = Number(str);

if (Number.isNaN(num)) {
throw new TypeError('NaN');
}

return num;
}).recover((e: SyntaxError | TypeError) => {
logger.error(e);

return 1;
});
```

### `Superposition.prototype.terminate(): Promise>`

Terminates the asynchronous operation represented by the current `Superposition` instance and obtain the final state of
the operation represented by a `Schrodinger` instance. If the `Superposition` is successfully fulfilled, the returned
`Schrodinger` will be in the `Alive` state, containing the value of the operation. If the `Superposition` is
unsuccessfully fulfilled, the returned `Schrodinger` will be in the `Dead` state, containing the error that caused the
failure. If the `Superposition` is rejected, the returned `Schrodinger` will be in the `Contradiction` state, indicating
that the operation has been rejected for an unknown reason.

### `Superposition.prototype.transform(alive: UnaryFunction, SReturnType>, dead: UnaryFunction>): Superposition`

Executes the given `alive` only when the current instance is in a successfully fulfilled state, and also executes the
`dead` only when the current instance is in an unsuccessfully fulfilled state. One of these functions will be executed
unless the current instance is in a rejected state. The overall result will be a `Superposition` instance.

This method combines the functionality of `Superposition.prototype.map()` and `Superposition.prototype.recover()` into
one, allowing you to handle both successful and unsuccessful outcomes of the asynchronous operation in a single call.

# Ünscharferelation classes

## (interface) Epoque\

### `epoque.accept(valye: Exclude): unknown`

### `epoque.decline(): unknown`

### `epoque.throw(cause: unknown): unknown`

## Unscharfeleration\

A class that handles Optional of Monad programming asynchronously. This class wraps a `Heisenberg` instance, which
represents the outcome of an asynchronous operation, and can change its state based on the outcome of that operation.

Like `Promise`, the Unscharferelation class can handle multiple states, but it is more finely divided than `Promise`.
The possible states are:

- Successfully fulfilled: corresponds to a fulfilled state of `Promise`.
- Unsuccessfully fulfilled: corresponds to a rejected state of `Promise`, but only for `null` and `undefined`.
- Rejected: corresponds to a rejected state of `Promise`.
- Pending: corresponds to a pending state of `Promise`.

### `Unscharferelation.all


(unscharferelations: Iterable>): Unscharfeleration>`

Takes an `Iterable>` and returns a single `Unscharferelation>`. If
all `unscharferelations` are in the `Present` state, the returned instance will be successfully fulfilled with an array
of the values from the `unscharferelations`. If at least one of `unscharferelations` is in the `Absent` state, the
returned instance will be unsuccessfully fulfilled with `null` of `undefined` from the first `Absent` state encountered.
If at least one of `unscharferelations` is in the `Lost` state, the returned instance will be rejected with the cause
from the first `Lost` state encountered. If there are both `Absent` and `Lost` states present in
the `unscharferelations`, the returned instance will be rejected (prioritized).

### `Unscharferelation.anyway

(unscharferelations: Iterable>): Promise>>`

Retrieves the outcome of each asynchronous operation in `unscharferelations` by
calling `Unscharferelation.prototype.terminate()` on each item. The resulting `Heisenberg` state for
each `Unscharferelation` can be found in the documentation for `Unscharferelation.prototype.terminate()`.

### `Unscharferelation.maybe

(value: UReturnType

): Unscharferelation>`

Creates a new `Unscharferelation` from the given value of type `P` or a `PromiseLike

`. If the value is `null`,
`undefined`, or a `PromiseLike` that resolves to `null` or `undefined`, the resulting `Unscharferelation` will be
unsuccessfully fulfilled. If a rejected `Promise` is given, the resulting `Unscharferelation` will be rejected.

### `Unscharferelation.of

(func: Consumer>>): Unscharferelation>`

Generates a new `Unscharferelation` instance by invoking the provided `func` argument with a `Epoque` object. If
the `epoque.accept(value)` is called with a valid value of `Awaited
` type, it returns a successfully
fulfilled `Unscharferelation

`. If the `Epoque.prototype.decline()` is called, it returns an unsuccessfully
fulfilled `Unscharferelation


`. If the `Epoque.prototype.throw(cause)` is called with an argument of `unknown` type,
it returns a rejected `Unscharferelation


`.

```ts
// let value is type of P or PromiseLike



Unscharferelation.of


((epoque: Epoque>) => {
try {
if (value !== null) {
epoque.accept(value);

return;
}

epoque.decline();
}
catch (e: unknown) {
epoque.throw(e);
}
});
```

### `Unscharferelation.ofHeisenberg

(heisenberg: Heisenberg>): Unscharferelation>`

Creates a new `Unscharferelation` instance from a given `Heisenberg` instance. If the given `heisenberg` is in
the `Present` state, the resulting `Unscharferelation` will be successfully fulfilled. If it is in the `Absent` state,
it will be unsuccessfully fulfilled. If it is in the `Lost` or `Uncertain` state, it will be rejected.

### `Unscharferelation.ofUnscharferelation

(unscharferelation: IUnscharferelation

): Unscharferelation

`

Generates a new `Unscharferelation` instance from a given `Unscharferelation` instance.

### `Unscharferelation.prototype.get(): Promise>`

Retrieves the outcome of the asynchronous operation as a `Promise`. If the instance is in the successfully fulfilled
state, it will return a fulfilled `Promise` instance. If the instance is in the unsuccessfully fulfilled or rejected
state, it will return a rejected `Promise` instance.

### `Unscharferelation.prototype.ifAbsent(consumer: Consumer): this`

Executes the given `consumer` if the asynchronous operation is going to be unsuccessfully fulfilled.

### `Unscharferelation.prototype.ifLost(consumer: Consumer): this`

Executes the given `consumer` with the internal `cause` value of `unknown` type if the asynchronous operation is going
to be rejected.

### `Unscharferelation.prototype.ifPresent(consumer: Consumer>): this`

Executes the given `consumer` with the non-null, non-undefined value of `P` type if the asynchronous operation is going
to be
successfully fulfilled.

### `Unscharferelation.prototype.map(mapper: UnaryFunction, UReturnType>): Unscharferelation`

Executes the given `mapper` only when the current instance is in a successfully fulfilled state. The `mapper` should
take in a single argument of type `Exclude
` and should return a value of type `Q` with a
non-null, non-undefined, or an instance of `IUnscharferelation`,
a `PromiseLike>`, or a `PromiseLike>`. The return value of
this method will be a `Unscharferelation` instance if the `mapper` is executed and returns a value
or `Unscharferelation`.

This method can be used as an alternative to `Promise.prototype.then()`.

```ts
unscharferelation.map((num: number) => {
return num.toFixed();
}).map((str: string) => {
const num = Number(str);

if (Number.isNaN(num)) {
throw new TypeError('NaN');
}

return num;
});
```

### `Unscharfeleration.prototype.pass(accepted: Consumer>, declinded: Consumer, thrown: Consumer): this`

Executes the given `accepted` with the non-null, non-undefined value of type `P` when the asynchronous operation is
successfully fulfilled, `declined` when the asynchronous operation is unsuccessfully fulfilled, or `thrown` with the
internal `cause` value of type `unknown` when the asynchronous operation is rejected.

### `Unscharferelation.prototype.peek(peek: Peek): this`

Executes the given `peek` with no arguments when the asynchronous operation represented by the current unscharferelation
instance is completed, regardless of whether it is successfully fulfilled, unsuccessfully fulfilled, or rejected. It
allows you to perform side effects, such as logging, without changing the outcome of the operation.

### `Unscharferelation.prototype.recover(mapper: Supplier>): Unscharferelation

`

Executes the given `mapper` only when the current instance is in an unsuccessfully fulfilled state. The `mapper` should
return a value of type `Q` with a non-null, non-undefined, or an instance of
`IUnscharferelation`, a `PromiseLike>`, or
a `PromiseLike>`. The return value of this method will be a `Unscharferelation` instance if
the `mapper` is executed and returns a value or `Unscharferelation` without error, otherwise it will return
a `Superposition

` instance if the `mapper` is not executed or the returned value contains an error. The overall
result will be a `Unscharferelation

` instance.

This method can be used as an alternative to `Promise.prototype.catch()`.

```ts
unscharferelation.map((num: number) => {
return num.toFixed();
}).map((str: string) => {
const num = Number(str);

if (Number.isNaN(num)) {
throw new TypeError('NaN');
}

return num;
}).recover(() => {
logger.error('null or undefined given');

return 1;
});
```

### `Unscharferelation.prototype.terminate(): Promise>`

Terminates the asynchronous operation represented by the current `Unscharferelation` instance and obtain the final state
of the operation represented by a `Heisenberg` instance. If the `Unscharferelation` is successfully fulfilled, the
returned `Heisenberg` will be in the `Present` state, containing the value of the operation. If the `Unscharferelation`
is unsuccessfully fulfilled, the returned `Heisenberg` will be in the `Absent` state, containing the error that caused
the failure. If the `Unscharferelation` is rejected, the returned `Heisenberg` will be in the `Lost` state, indicating
that the operation has been rejected for an unknown reason.

## License

[MIT](LICENSE)