diff --git a/README.md b/README.md index d54a0d1..408e2c2 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,46 @@ Rust-like `Result` for JavaScript. - [Installation](#installation) - [Usage](#usage) - [About Rust `Option`](#about-rust-option) -- [The Implementations for `Result`](#the-implementations-for-result) - - [Asynchronous Methods](#asynchronous-methods) -- [More Methods](#more-methods) - - [equal](#equal) +- [Methods Documentation](#methods-documentation) + - [Rust `Result` Methods](#rust-result-methods) + - [`isOk`](#isok) + - [`isOkAnd`](#isokand) + - [`isOkAndAsync`](#isokandasync) + - [`isErr`](#iserr) + - [`isErrAnd`](#iserrand) + - [`isErrAndAsync`](#iserrandasync) + - [`ok`](#ok) + - [`err`](#err) + - [`map`](#map) + - [`mapAsync`](#mapasync) + - [`mapOr`](#mapor) + - [`mapOrAsync`](#maporasync) + - [`mapOrElse`](#maporelse) + - [`mapOrElseAsync`](#maporelseasync) + - [`mapErr`](#maperr) + - [`mapErrAsync`](#maperrasync) + - [`inspect`](#inspect) + - [`inspectAsync`](#inspectasync) + - [`inspectErr`](#inspecterr) + - [`inspectErrAsync`](#inspecterrasync) + - [`expect`](#expect) + - [`unwrap`](#unwrap) + - [`expectErr`](#expecterr) + - [`unwrapErr`](#unwraperr) + - [`unwrapOr`](#unwrapor) + - [`unwrapOrElse`](#unwraporelse) + - [`unwrapOrElseAsync`](#unwraporelseasync) + - [`unwrapUnchecked`](#unwrapunchecked) + - [`unwrapErrUnchecked`](#unwraperrunchecked) + - [`and`](#and) + - [`andThen`](#andthen) + - [`andThenAsync`](#andthenasync) + - [`or`](#or) + - [`orElse`](#orelse) + - [`orElseAsync`](#orelseasync) + - [`transpose`](#transpose) + - [Additional Methods](#additional-methods) + - [equal](#equal) - [Helpers for Resultifying](#helpers-for-resultifying) - [resultify](#resultify) - [resultify.sync](#resultifysync) @@ -66,7 +102,8 @@ This package doesn't implement Rust-like `Option`. Handling `undefined`/`null` i [proposal-optional-chaining]: https://github.com/tc39/proposal-optional-chaining [proposal-nullish-coalescing]: https://github.com/tc39/proposal-nullish-coalescing -## The Implementations for `Result` +## Methods Documentation +### Rust `Result` Methods The Rust-like `Result` implements the following methods: @@ -150,20 +187,712 @@ hash [or_else]: https://doc.rust-lang.org/std/result/enum.Result.html#method.or_else [transpose]: https://doc.rust-lang.org/std/result/enum.Result.html#method.transpose -### Asynchronous Methods +#### `isOk` + +Returns `true` if the result is `Ok`. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +const x: Result = Ok(2); +assert(x.isOk() === true); + +const y: Result = Err('Some error message'); +assert(y.isOk() === false); +``` + +#### `isOkAnd` + +Returns `true` if the result is `Ok` and the value inside of it matches a predicate. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +const x: Result = Ok(2); +assert(x.isOkAnd((value) => value > 1) === true); + +const y: Result = Ok(0); +assert(y.isOkAnd((value) => value > 1) === false); + +const z: Result = Err('Some error message'); +assert(z.isOkAnd((value) => value > 1) === false); +``` + +#### `isOkAndAsync` + +Asynchronously returns `true` if the result is `Ok` and the value inside of it matches a predicate. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +const x: Result = Ok(2); +assert((await x.isOkAndAsync((value) => Promise.resolve(value > 1))) === true); + +const y: Result = Ok(0); +assert((await y.isOkAndAsync((value) => Promise.resolve(value > 1))) === false); + +const z: Result = Err('Some error message'); +assert((await z.isOkAndAsync((value) => Promise.resolve(value > 1))) === false); +``` + +#### `isErr` + +Returns `true` if the result is `Err`. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +const x: Result = Ok(-3); +assert(x.isErr() === false); + +const y: Result = Err('Some error message'); +assert(y.isErr() === true); +``` + +#### `isErrAnd` + +Returns `true` if the result is `Err` and the value inside of it matches a predicate. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +enum ErrorKind { +NOT_FOUND, +PERMISSION_DENIED, +} + +const x: Result = Err(ErrorKind.NOT_FOUND); +assert(x.isErrAnd((value) => value === ErrorKind.NOT_FOUND) === true); + +const y: Result = Err(ErrorKind.PERMISSION_DENIED); +assert(y.isErrAnd((value) => value === ErrorKind.NOT_FOUND) === false); + +const z: Result = Ok(123); +assert(z.isErrAnd((value) => value === ErrorKind.NOT_FOUND) === false); +``` + +#### `isErrAndAsync` + +Asynchronously returns `true` if the result is `Err` and the value inside of it matches a predicate. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +enum ErrorKind { +NOT_FOUND, +PERMISSION_DENIED, +} + +const x: Result = Err(ErrorKind.NOT_FOUND); +assert((await x.isErrAndAsync((value) => Promise.resolve(value === ErrorKind.NOT_FOUND))) === true); + +const y: Result = Err(ErrorKind.PERMISSION_DENIED); +assert((await y.isErrAndAsync((value) => Promise.resolve(value === ErrorKind.NOT_FOUND))) === false); + +const z: Result = Ok(123); +assert((await z.isErrAndAsync((value) => Promise.resolve(value === ErrorKind.NOT_FOUND))) === false); +``` + +#### `ok` + +Converts from `Result` to `Optional` and discarding the error, if any. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +const x: Result = Ok(2); +assert(x.ok() === 2); + +const y: Result = Err('Some error message'); +assert(y.ok() === undefined); +``` + +#### `err` + +Converts from `Result` to `Optional` and discarding the success value, if any. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +const x: Result = Ok(2); +assert(x.err() === undefined); + +const y: Result = Err('Some error message'); +assert(y.err() === 'Some error message'); +``` + +#### `map` + +Maps a `Result` to `Result` by applying a function to a contained `Ok` value, leaving an `Err` value untouched. + +This function can be used to compose the results of two functions. + +Examples: + +```ts +import { Ok, type Result } from 'rustlike-result'; + +const x: Result = Ok('foo'); +assert(x.map((value) => value.length).ok() === 3); +``` + +#### `mapAsync` + +Asynchronously maps a `Result` to `Result` by applying a function to a contained `Ok` value, leaving an `Err` value untouched. + +This function can be used to compose the results of two functions. + +Examples: + +```ts +import { Ok } from 'rustlike-result'; + +const x = await Ok('foo').mapAsync((value) => Promise.resolve(value.length)); +assert(x.ok() === 3); +``` + +#### `mapOr` + +Returns the provided `fallback` (if `Err`), or applies a function to the contained value (if `Ok`). + +Arguments passed to `mapOr` are eagerly evaluated; if you are passing the result of a function call, it is recommended to use `mapOrElse`, which is lazily evaluated. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +const x: Result = Ok('foo'); +assert(x.mapOr(42, (value) => value.length) === 3); + +const y: Result = Err('bar'); +assert(y.mapOr(42, (value) => value.length) === 42); +``` + +#### `mapOrAsync` + +Asynchronously returns the provided `fallback` (if `Err`), or applies a function to the contained value (if `Ok`). + +Arguments passed to `mapOr` are eagerly evaluated; if you are passing the result of a function call, it is recommended to use `mapOrElse`, which is lazily evaluated. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +const x: Result = Ok('foo'); +assert((await x.mapOrAsync(42, (value) => value.length)) === 3); + +const y: Result = Err('bar'); +assert((await y.mapOrAsync(42, (value) => value.length)) === 42); +``` + +#### `mapOrElse` + +Maps a `Result` to `U` by applying fallback function `fallback` to a contained `Err` value, or function `map` to a contained `Ok` value. + +This function can be used to unpack a successful result while handling an error. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +const k = 21; + +const x: Result = Ok('foo'); +assert(x.mapOrElse((err) => k * 2, (value) => value.length) === 3); + +const y: Result = Err('bar'); +assert(y.mapOrElse((err) => k * 2, (value) => value.length) === 42); +``` + +#### `mapOrElseAsync` + +Asynchronously maps a `Result` to `U` by applying fallback function `fallback` to a contained `Err` value, or function `map` to a contained `Ok` value. + +This function can be used to unpack a successful result while handling an error. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +const k = 21; + +const x: Result = Ok('foo'); +assert((await x.mapOrElseAsync(() => Promise.resolve(k * 2), (value) => Promise.resolve(value.length))) === 3); + +const y: Result = Err('bar'); +assert((await y.mapOrElseAsync(() => Promise.resolve(k * 2), (value) => Promise.resolve(value.length))) === 42); +``` + +#### `mapErr` + +Maps a `Result` to `Result` by applying a function to a contained `Err` value, leaving an `Ok` value untouched. + +This function can be used to pass through a successful result while handling an error. + +Examples: + +```ts +import { Err, type Result } from 'rustlike-result'; + +const x: Result = Err(new Error('Some error message')); +assert(x.mapErr((err) => err.message).err() === 'Some error message'); +``` + +#### `mapErrAsync` + +Asynchronously maps a `Result` to `Result` by applying a function to a contained `Err` value, leaving an `Ok` value untouched. + +This function can be used to pass through a successful result while handling an error. + +Examples: + +```ts +import { Err } from 'rustlike-result'; + +const x = await Err(new Error('Some error message')).mapErrAsync((err) => Promise.resolve(err.message)); +assert(x.err() === 'Some error message'); +``` + +#### `inspect` + +Calls the provided closure with a reference to the contained value if `Ok`. + +Examples: + +```ts +import { resultify } from 'rustlike-result'; + +const num = resultify + .sync()(JSON.parse)('4') + .inspect((value: number) => console.log(`original: ${value}`)) + .map((value) => value ** 3) + .expect('failed to parse number'); +assert(num === 64); +``` + +#### `inspectAsync` + +Asynchronously calls the provided closure with a reference to the contained value if `Ok`. + +Examples: + +```ts +import { resultify } from 'rustlike-result'; + +const num = await resultify + .sync()(JSON.parse)('4') + .inspectAsync((value: number) => { + console.log(`original: ${value}`); + return Promise.resolve(); + }) + .then((result) => result.map((value) => value ** 3)) + .then((result) => result.expect('failed to parse number')); +assert(num === 64); +``` + +#### `inspectErr` + +Calls the provided closure with a reference to the contained value if `Err`. + +Examples: + +```ts +import { resultify } from 'rustlike-result'; + +const num = resultify + .sync()(JSON.parse)('asdf') + .inspectErr((err) => console.log(`failed to parse json string: ${err.message}`)); +assert(num.err() instanceof SyntaxError); +``` + +#### `inspectErrAsync` + +Asynchronously calls the provided closure with a reference to the contained value if `Err`. + +Examples: + +```ts +import { resultify } from 'rustlike-result'; + +const num = await resultify + .sync()(JSON.parse)('asdf') + .inspectErrAsync((err) => { + console.log(`failed to parse json string: ${err.message}`); + return Promise.resolve(); + }); +assert(num.err() instanceof SyntaxError); +``` + +#### `expect` + +Returns the contained `Ok` value. + +Because this function may throw an error, its use is generally discouraged. Instead, prefer to call `unwrapOr`, `unwrapOrElse`. + +Throws an Error if itself is `Err`, with an error message including the passed message, and the content of the `Err`. + +Examples: + +```ts +import { Err, type Result } from 'rustlike-result'; + +const x: Result = Err('emergency failure'); +x.expect('Failed to operate'); // throws Error('Failed to operate: emergency failure') +``` + +#### `unwrap` + +Returns the contained `Ok` value. + +Because this function may throw an error, its use is generally discouraged. Instead, prefer to call `unwrapOr`, `unwrapOrElse`. + +Throws an Error if itself is `Err`, with an error message provided by the `Err`'s value. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +const x: Result = Ok(2); +assert(x.unwrap() === 2); + +const y: Result = Err('emergency failure'); +y.unwrap(); // throws Error('emergency failure') +``` + +#### `expectErr` + +Returns the contained `Err` value. + +Throws an Error if itself is `Err`, with an error message provided by the `Ok`'s value. + +Examples: + +```ts +import { Ok, type Result } from 'rustlike-result'; + +const x: Result = Ok(10); +x.expectErr('Testing expectErr'); // throws Error('Testing expectErr: 10') +``` + +#### `unwrapErr` + +Returns the contained `Err` value. + +Throws an Error if itself is `Ok`, with an error message provided by the `Ok`'s value. + +Examples: -Some of the methods have asynchronous versions to help you handle asynchronous logic, for example: ```ts -const result = await Ok(1) - .andThenAsync(asyncFn1) - .then((result) => result.andThenAsync(asyncFn2)) - .then((result) => result.andThenAsync(asyncFn3)) - .then((result) => result.andThenAsync(asyncFn4)) - .then((result) => result.andThenAsync(asyncFn5)); +import { Ok, type Result } from 'rustlike-result'; + +const x: Result = Err('emergency failure'); +assert(x.unwrapErr() === 'emergency failure'); + +const y: Result = Ok(2); +y.unwrapErr(); // throws Error(2) +``` + +#### `unwrapOr` + +Returns the contained `Ok` value or a provided default. + +Arguments passed to `unwrapOr` are eagerly evaluated; if you are passing the result of a function call, it is recommended to use `unwrapOrElse`, which is lazily evaluated. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +const $default = 2; +const x: Result = Ok(9); +assert(x.unwrapOr($default) === 9); + +const y: Result = Err('error'); +assert(y.unwrapOr($default) === $default); +``` + +#### `unwrapOrElse` + +Returns the contained `Ok` value or computes it from a closure. + +Examples: + +```ts +import { Err, Ok } from 'rustlike-result'; + +const count = (err: string) => err.length; +assert(Ok(2).unwrapOrElse(count) === 2); +assert(Err('foo').unwrapOrElse(count) === 3); +``` + +#### `unwrapOrElseAsync` + +Asynchronously returns the contained `Ok` value or computes it from a closure. + +Examples: + +```ts +import { Err, Ok } from 'rustlike-result'; + +const count = (err: string) => Promise.resolve(err.length); +assert((await Ok(2).unwrapOrElseAsync(count)) === 2); +assert((await Err('foo').unwrapOrElseAsync(count)) === 3); +``` + +#### `unwrapUnchecked` + +Returns the contained `Ok` value, without checking that the value is not an `Err`. + +**SAFETY**: Calling this method on an `Err` is undefined behavior. +The safety contract must be upheld by the caller. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +const x: Result = Ok(2); +assert(x.unwrapUnchecked() === 2); + +const y: Result = Err('emergency failure'); +y.unwrapUnchecked(); +``` + +#### `unwrapErrUnchecked` + +Returns the contained `Err` value, without checking that the value is not an `Ok`. + +**SAFETY**: Calling this method on an `Ok` is undefined behavior. +The safety contract must be upheld by the caller. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +const x: Result = Ok(2); +x.unwrapErrUnchecked(); + +const y: Result = Err('emergency failure'); +assert(y.unwrapErrUnchecked() === 'emergency failure'); +``` + +#### `and` + +Returns `res` if itself is `Ok`, otherwise returns the `Err` value of itself. + +Arguments passed to `and` are eagerly evaluated; if you are passing the result of a function call, it is recommended to use `andThen`, which is lazily evaluated. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +let x: Result; +let y: Result; + +x = Ok(2); +y = Err('late error'); +assert(x.and(y).equal(Err('late error'))); + +x = Err('early error'); +y = Ok('foo'); +assert(x.and(y).equal(Err('early error'))); + +x = Err('not a 2'); +y = Err('late error'); +assert(x.and(y).equal(Err('not a 2'))); + +x = Ok(2); +y = Ok('different result type'); +assert(x.and(y).equal(Ok('different result type'))); +``` + +#### `andThen` + +Calls `op` if itself is `Ok`, otherwise returns the `Err` value of itself. + +This function can be used for control flow based on Result values. + +Examples: + +```ts +import { Err, Ok } from 'rustlike-result'; + +const parseJSON = (json: string) => + resultify + .sync()(JSON.parse)(json) + .mapErr((err) => err.message); + +assert(Ok('2').andThen(parseJSON).equal(Ok(2))); +assert( + Ok('asdf') + .andThen(parseJSON) + .equal(Err('Unexpected token \'a\', "asdf" is not valid JSON')), +); +``` + +#### `andThenAsync` + +Asynchronously calls `op` if itself is `Ok`, otherwise returns the `Err` value of itself. + +This function can be used for control flow based on Result values. + +Examples: + +```ts +import { Err, Ok } from 'rustlike-result'; + +const parseJSON = (json: string) => + Promise.resolve( + resultify + .sync()(JSON.parse)(json) + .mapErr((err) => err.message), + ); + +const x = await Ok('2').andThenAsync(parseJSON); +assert(x.equal(Ok(2))); + +const y = await Ok('asdf').andThenAsync(parseJSON); +assert(y.equal(Err('Unexpected token \'a\', "asdf" is not valid JSON'))); + +const z = await Err('not a valid json string').andThenAsync(parseJSON); +assert(z.equal(Err('not a valid json string'))); +``` + +#### `or` + +Returns `res` if itself is `Err`, otherwise returns the `Ok` value of itself. + +Arguments passed to `or` are eagerly evaluated; if you are passing the result of a function call, it is recommended to use `orElse`, which is lazily evaluated. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +let x: Result; +let y: Result; + +x = Ok(2); +y = Err('late error'); +assert(x.or(y).equal(Ok(2))); + +x = Err('early error'); +y = Ok(2); +assert(x.or(y).equal(Ok(2))); + +x = Err('not a 2'); +y = Err('late error'); +assert(x.or(y).equal(Err('late error'))); + +x = Ok(2); +y = Ok(100); +assert(x.and(y).equal(Ok('different result type'))); +``` + +#### `orElse` + +Calls `op` if the result is `Err`, otherwise returns the `Ok` value of self. + +This function can be used for control flow based on result values. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +const sq = (num: number): Result => Ok(num * num); +const err = (num: number): Result => Err(num); + +assert(Ok(2).orElse(sq).orElse(sq).equal(Ok(2))); +assert(Ok(2).orElse(err).orElse(sq).equal(Ok(2))); +assert(Err(3).orElse(sq).orElse(err).equal(Ok(9))); +assert(Err(3).orElse(err).orElse(err).equal(Err(3))); +``` + +#### `orElseAsync` + +Asynchronously calls `op` if the result is `Err`, otherwise returns the `Ok` value of self. + +This function can be used for control flow based on result values. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +const sq = (num: number): Promise> => Promise.resolve(Ok(num * num)); +const err = (num: number): Promise> => Promise.resolve(Err(num)); + +const x = await Ok(2) + .orElseAsync(sq) + .then((result) => result.orElseAsync(sq)); +assert(x.equal(Ok(2))); + +const y = await Err(3) + .orElseAsync(sq) + .then((result) => result.orElseAsync(err)); +assert(y.equal(Ok(9))); + +const z = await Err(3) + .orElseAsync(err) + .then((result) => result.orElseAsync(err)); +assert(z.equal(Err(3))); +``` + +#### `transpose` + +Transposes a `Result` of an optional value into an optional of a `Result`. + +`Ok(undefined | null)` will be mapped to `undefined`. `Ok(_)` and `Err(_)` will be mapped to `Ok(_)` and `Err(_)`. + +Examples: + +```ts +import { Err, Ok, type Result } from 'rustlike-result'; + +type SomeErr = unknown; + +let x: Result; +let y: Result | undefined; + +x = Ok(5); +y = Ok(5); +assert(x.transpose()!.equal(y)); + +x = Ok(undefined); +y = undefined; +assert(x.transpose() === y); + +x = Ok(null); +y = undefined; +assert(x.transpose() === y); ``` -## More Methods -### equal +### Additional Methods +#### equal You can not just use `===` or `==` to compare `Result`, so `Result` itself provides an method call `equal` for that. diff --git a/src/__tests__/result.test.ts b/src/__tests__/result.test.ts index 34a7d9f..712d7cb 100644 --- a/src/__tests__/result.test.ts +++ b/src/__tests__/result.test.ts @@ -1,7 +1,9 @@ import { describe, expect, it, jest } from '@jest/globals'; +import assert from 'node:assert'; import { Err, Ok } from '../factory'; import { RustlikeResult } from '../result'; +import { resultify } from '../resultify'; import type { Result } from '../types'; function panicFn1(): never { @@ -29,6 +31,18 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot expect(Ok(1).isOk()).toBe(true); expect(Err('Some error message').isOk()).toBe(false); }); + + it('should have correct examples doc', () => { + function examples() { + const x: Result = Ok(2); + assert(x.isOk() === true); + + const y: Result = Err('Some error message'); + assert(y.isOk() === false); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.isOkAnd.name}\``, () => { @@ -58,6 +72,21 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot it('should panic if fn panic', () => { expect(() => Ok(2).isOkAnd(panicFn1)).toThrow(Error('error')); }); + + it('should have correct examples doc', () => { + function examples() { + const x: Result = Ok(2); + assert(x.isOkAnd((value) => value > 1) === true); + + const y: Result = Ok(0); + assert(y.isOkAnd((value) => value > 1) === false); + + const z: Result = Err('Some error message'); + assert(z.isOkAnd((value) => value > 1) === false); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.isOkAndAsync.name}\``, () => { @@ -101,6 +130,21 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot await expect(() => Ok(2).isOkAndAsync(panicFn1)).rejects.toThrow(Error('error')); await expect(() => Ok(2).isOkAndAsync(panicFn2)).rejects.toThrow(Error('error')); }); + + it('should have correct examples doc', async () => { + async function examples() { + const x: Result = Ok(2); + assert((await x.isOkAndAsync((value) => Promise.resolve(value > 1))) === true); + + const y: Result = Ok(0); + assert((await y.isOkAndAsync((value) => Promise.resolve(value > 1))) === false); + + const z: Result = Err('Some error message'); + assert((await z.isOkAndAsync((value) => Promise.resolve(value > 1))) === false); + } + + await expect(examples()).resolves.not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.isErr.name}\``, () => { @@ -108,6 +152,18 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot expect(Ok(1).isErr()).toBe(false); expect(Err('Some error message').isErr()).toBe(true); }); + + it('should have correct examples doc', () => { + function examples() { + const x: Result = Ok(-3); + assert(x.isErr() === false); + + const y: Result = Err('Some error message'); + assert(y.isErr() === true); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.isErrAnd.name}\``, () => { @@ -142,6 +198,21 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot it('should panic if fn panic', () => { expect(() => Err(ErrorKind.NOT_FOUND).isErrAnd(panicFn1)).toThrow(Error('error')); }); + + it('should have correct examples doc', () => { + function examples() { + const x: Result = Err(ErrorKind.NOT_FOUND); + assert(x.isErrAnd((value) => value === ErrorKind.NOT_FOUND) === true); + + const y: Result = Err(ErrorKind.PERMISSION_DENIED); + assert(y.isErrAnd((value) => value === ErrorKind.NOT_FOUND) === false); + + const z: Result = Ok(123); + assert(z.isErrAnd((value) => value === ErrorKind.NOT_FOUND) === false); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.isErrAndAsync.name}\``, () => { @@ -190,6 +261,21 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot await expect(() => Err(ErrorKind.NOT_FOUND).isErrAndAsync(panicFn1)).rejects.toThrow(Error('error')); await expect(() => Err(ErrorKind.NOT_FOUND).isErrAndAsync(panicFn2)).rejects.toThrow(Error('error')); }); + + it('should have correct examples doc', async () => { + async function examples() { + const x: Result = Err(ErrorKind.NOT_FOUND); + assert((await x.isErrAndAsync((value) => Promise.resolve(value === ErrorKind.NOT_FOUND))) === true); + + const y: Result = Err(ErrorKind.PERMISSION_DENIED); + assert((await y.isErrAndAsync((value) => Promise.resolve(value === ErrorKind.NOT_FOUND))) === false); + + const z: Result = Ok(123); + assert((await z.isErrAndAsync((value) => Promise.resolve(value === ErrorKind.NOT_FOUND))) === false); + } + + await expect(examples()).resolves.not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.ok.name}\``, () => { @@ -197,6 +283,18 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot expect(Ok(1).ok()).toBe(1); expect(Err('Some error message').ok()).toBeUndefined(); }); + + it('should have correct examples doc', () => { + function examples() { + const x: Result = Ok(2); + assert(x.ok() === 2); + + const y: Result = Err('Some error message'); + assert(y.ok() === undefined); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.err.name}\``, () => { @@ -204,6 +302,18 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot expect(Ok(1).err()).toBeUndefined(); expect(Err('Some error message').err()).toBe('Some error message'); }); + + it('should have correct examples doc', () => { + function examples() { + const x: Result = Ok(2); + assert(x.err() === undefined); + + const y: Result = Err('Some error message'); + assert(y.err() === 'Some error message'); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.map.name}\``, () => { @@ -232,6 +342,15 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot it('should panic if fn panic', () => { expect(() => Ok(1).map(panicFn1)).toThrow(Error('error')); }); + + it('should have correct examples doc', () => { + function examples() { + const x: Result = Ok('foo'); + assert(x.map((value) => value.length).ok() === 3); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.mapAsync.name}\``, () => { @@ -274,6 +393,15 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot await expect(() => Ok(1).mapAsync(panicFn1)).rejects.toThrow(Error('error')); await expect(() => Ok(1).mapAsync(panicFn2)).rejects.toThrow(Error('error')); }); + + it('should have correct examples doc', async () => { + async function examples() { + const x = await Ok('foo').mapAsync((value) => Promise.resolve(value.length)); + assert(x.ok() === 3); + } + + await expect(examples()).resolves.not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.mapOr.name}\``, () => { @@ -302,6 +430,18 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot it('should panic if fn panic', () => { expect(() => Ok(1).mapOr(Err('err'), panicFn1)).toThrow(Error('error')); }); + + it('should have correct examples doc', () => { + function examples() { + const x: Result = Ok('foo'); + assert(x.mapOr(42, (value) => value.length) === 3); + + const y: Result = Err('bar'); + assert(y.mapOr(42, (value) => value.length) === 42); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.mapOrAsync.name}\``, () => { @@ -344,6 +484,18 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot await expect(() => Ok(1).mapOrAsync(Err('err'), panicFn1)).rejects.toThrow(Error('error')); await expect(() => Ok(1).mapOrAsync(Err('err'), panicFn2)).rejects.toThrow(Error('error')); }); + + it('should have correct examples doc', async () => { + async function examples() { + const x: Result = Ok('foo'); + assert((await x.mapOrAsync(42, (value) => value.length)) === 3); + + const y: Result = Err('bar'); + assert((await y.mapOrAsync(42, (value) => value.length)) === 42); + } + + await expect(examples()).resolves.not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.mapOrElse.name}\``, () => { @@ -383,6 +535,30 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot expect(() => Ok(1).mapOrElse(panicFn1, panicFn1)).toThrow(Error('error')); expect(() => Err('err').mapOrElse(panicFn1, panicFn1)).toThrow(Error('error')); }); + + it('should have correct examples doc', () => { + function examples() { + const k = 21; + + const x: Result = Ok('foo'); + assert( + x.mapOrElse( + () => k * 2, + (value) => value.length, + ) === 3, + ); + + const y: Result = Err('bar'); + assert( + y.mapOrElse( + () => k * 2, + (value) => value.length, + ) === 42, + ); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.mapOrElseAsync.name}\``, () => { @@ -442,6 +618,30 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot await expect(() => Ok(1).mapOrElseAsync(panicFn2, panicFn2)).rejects.toThrow(Error('error')); await expect(() => Err('err').mapOrElseAsync(panicFn2, panicFn2)).rejects.toThrow(Error('error')); }); + + it('should have correct examples doc', async () => { + async function examples() { + const k = 21; + + const x: Result = Ok('foo'); + assert( + (await x.mapOrElseAsync( + () => Promise.resolve(k * 2), + (value) => Promise.resolve(value.length), + )) === 3, + ); + + const y: Result = Err('bar'); + assert( + (await y.mapOrElseAsync( + () => Promise.resolve(k * 2), + (value) => Promise.resolve(value.length), + )) === 42, + ); + } + + await expect(examples()).resolves.not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.mapErr.name}\``, () => { @@ -470,6 +670,15 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot it('should panic if fn panic', () => { expect(() => Err('err').mapErr(panicFn1)).toThrow(Error('error')); }); + + it('should have correct examples doc', () => { + function examples() { + const x: Result = Err(new Error('Some error message')); + assert(x.mapErr((err) => err.message).err() === 'Some error message'); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.mapErrAsync.name}\``, () => { @@ -512,6 +721,15 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot await expect(() => Err('err').mapErrAsync(panicFn1)).rejects.toThrow(Error('error')); await expect(() => Err('err').mapErrAsync(panicFn2)).rejects.toThrow(Error('error')); }); + + it('should have correct examples doc', async () => { + async function examples() { + const x = await Err(new Error('Some error message')).mapErrAsync((err) => Promise.resolve(err.message)); + assert(x.err() === 'Some error message'); + } + + await expect(examples()).resolves.not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.inspect.name}\``, () => { @@ -544,6 +762,21 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot it('should panic if fn panic', () => { expect(() => Ok(1).inspect(panicFn1)).toThrow(Error('error')); }); + + it('should have correct examples doc', () => { + jest.spyOn(console, 'log').mockImplementationOnce(() => {}); + + function examples() { + const num = resultify + .sync()(JSON.parse)('4') + .inspect((value: number) => console.log(`original: ${value}`)) + .map((value) => value ** 3) + .expect('failed to parse number'); + assert(num === 64); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.inspectAsync.name}\``, () => { @@ -592,6 +825,24 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot await expect(() => Ok(1).inspectAsync(panicFn1)).rejects.toThrow(Error('error')); await expect(() => Ok(1).inspectAsync(panicFn2)).rejects.toThrow(Error('error')); }); + + it('should have correct examples doc', async () => { + async function examples() { + jest.spyOn(console, 'log').mockImplementationOnce(() => {}); + + const num = await resultify + .sync()(JSON.parse)('4') + .inspectAsync((value: number) => { + console.log(`original: ${value}`); + return Promise.resolve(); + }) + .then((result) => result.map((value) => value ** 3)) + .then((result) => result.expect('failed to parse number')); + assert(num === 64); + } + + await expect(examples()).resolves.not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.inspectErr.name}\``, () => { @@ -624,6 +875,19 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot it('should panic if fn panic', () => { expect(() => Err('err').inspectErr(panicFn1)).toThrow(Error('error')); }); + + it('should have correct examples doc', () => { + jest.spyOn(console, 'log').mockImplementationOnce(() => {}); + + function examples() { + const num = resultify + .sync()(JSON.parse)('asdf') + .inspectErr((err) => console.log(`failed to parse json string: ${err.message}`)); + assert(num.err() instanceof SyntaxError); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.inspectErrAsync.name}\``, () => { @@ -672,6 +936,22 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot await expect(() => Err('err').inspectErrAsync(panicFn1)).rejects.toThrow(Error('error')); await expect(() => Err('err').inspectErrAsync(panicFn2)).rejects.toThrow(Error('error')); }); + + it('should have correct examples doc', async () => { + jest.spyOn(console, 'log').mockImplementationOnce(() => {}); + + async function examples() { + const num = await resultify + .sync()(JSON.parse)('asdf') + .inspectErrAsync((err) => { + console.log(`failed to parse json string: ${err.message}`); + return Promise.resolve(); + }); + assert(num.err() instanceof SyntaxError); + } + + await expect(examples()).resolves.not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.expect.name}\``, () => { @@ -679,6 +959,15 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot expect(Ok(1).expect('Operation type should be correct')).toBe(1); expect(() => Err(2).expect('Operation type should be correct')).toThrow('Operation type should be correct: 2'); }); + + it('should have correct examples doc', () => { + function examples() { + const x: Result = Err('emergency failure'); + x.expect('Failed to operate'); + } + + expect(examples).toThrow('Failed to operate: emergency failure'); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.unwrap.name}\``, () => { @@ -686,6 +975,18 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot expect(Ok(1).unwrap()).toBe(1); expect(() => Err('Some error message').unwrap()).toThrow('Some error message'); }); + + it('should have correct examples doc', () => { + function examples() { + const x: Result = Ok(2); + assert(x.unwrap() === 2); + + const y: Result = Err('emergency failure'); + y.unwrap(); + } + + expect(examples).toThrow('emergency failure'); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.expectErr.name}\``, () => { @@ -693,6 +994,15 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot expect(Err('Some error message').expectErr('Testing expectErr')).toBe('Some error message'); expect(() => Ok(1).expectErr('Testing expectErr')).toThrow('Testing expectErr: 1'); }); + + it('should have correct examples doc', () => { + function examples() { + const x: Result = Ok(10); + x.expectErr('Testing expectErr'); + } + + expect(examples).toThrow('Testing expectErr: 10'); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.unwrapErr.name}\``, () => { @@ -700,6 +1010,18 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot expect(Err('Some error message').unwrapErr()).toBe('Some error message'); expect(() => Ok(1).unwrapErr()).toThrow('1'); }); + + it('should have correct examples doc', () => { + function examples() { + const x: Result = Err('emergency failure'); + assert(x.unwrapErr() === 'emergency failure'); + + const y: Result = Ok(2); + y.unwrapErr(); + } + + expect(examples).toThrow('2'); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.unwrapOr.name}\``, () => { @@ -710,6 +1032,19 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot expect(ok.unwrapOr(50)).toBe(100); expect(okErr.unwrapOr(50)).toBe(50); }); + + it('should have correct examples doc', () => { + function examples() { + const $default = 2; + const x: Result = Ok(9); + assert(x.unwrapOr($default) === 9); + + const y: Result = Err('error'); + assert(y.unwrapOr($default) === $default); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.unwrapOrElse.name}\``, () => { @@ -742,6 +1077,16 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot it('should panic if fn panic', () => { expect(() => Err('err').unwrapOrElse(panicFn1)).toThrow(Error('error')); }); + + it('should have correct examples doc', () => { + function examples() { + const count = (err: string) => err.length; + assert(Ok(2).unwrapOrElse(count) === 2); + assert(Err('foo').unwrapOrElse(count) === 3); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.unwrapOrElseAsync.name}\``, () => { @@ -792,18 +1137,52 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot await expect(() => Err('err').unwrapOrElseAsync(panicFn1)).rejects.toThrow(Error('error')); await expect(() => Err('err').unwrapOrElseAsync(panicFn2)).rejects.toThrow(Error('error')); }); + + it('should have correct examples doc', async () => { + async function examples() { + const count = (err: string) => Promise.resolve(err.length); + assert((await Ok(2).unwrapOrElseAsync(count)) === 2); + assert((await Err('foo').unwrapOrElseAsync(count)) === 3); + } + + await expect(examples()).resolves.not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.unwrapUnchecked.name}\``, () => { it('should unwrap itself to get the contained `Ok` value', () => { expect(Ok(100).unwrapUnchecked()).toBe(100); }); + + it('should have correct examples doc', () => { + function examples() { + const x: Result = Ok(2); + assert(x.unwrapUnchecked() === 2); + + const y: Result = Err('emergency failure'); + y.unwrapUnchecked(); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.unwrapErrUnchecked.name}\``, () => { it('should unwrap itself to get the contained `Err` value', () => { expect(Err('Err').unwrapErrUnchecked()).toBe('Err'); }); + + it('should have correct examples doc', () => { + function examples() { + const x: Result = Ok(2); + x.unwrapErrUnchecked(); + + const y: Result = Err('emergency failure'); + assert(y.unwrapErrUnchecked() === 'emergency failure'); + } + + expect(examples).not.toThrow(); + }); }); function op1(): Result { @@ -824,6 +1203,31 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot expect(op2().and(Ok(667))).toStrictEqual(Err('sadface')); expect(op2().and(Err('bad'))).toStrictEqual(Err('sadface')); }); + + it('should have correct examples doc', () => { + function examples() { + let x: Result; + let y: Result; + + x = Ok(2); + y = Err('late error'); + assert(x.and(y).equal(Err('late error'))); + + x = Err('early error'); + y = Ok('foo'); + assert(x.and(y).equal(Err('early error'))); + + x = Err('not a 2'); + y = Err('late error'); + assert(x.and(y).equal(Err('not a 2'))); + + x = Ok(2); + y = Ok('different result type'); + assert(x.and(y).equal(Ok('different result type'))); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.andThen.name}\``, () => { @@ -854,6 +1258,25 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot it('should panic if fn panic', () => { expect(() => Ok(1).andThen(panicFn1)).toThrow(Error('error')); }); + + it('should have correct examples doc', () => { + function examples() { + const parseJSON = (json: string) => + resultify + .sync()(JSON.parse)(json) + .mapErr((err) => err.message); + + assert(Ok('2').andThen(parseJSON).equal(Ok(2))); + assert( + Ok('asdf') + .andThen(parseJSON) + .equal(Err('Unexpected token \'a\', "asdf" is not valid JSON')), + ); + assert(Err('not a valid json string').andThen(parseJSON).equal(Err('not a valid json string'))); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.andThenAsync.name}\``, () => { @@ -889,6 +1312,28 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot await expect(() => Ok(1).andThenAsync(panicFn1)).rejects.toThrow(Error('error')); await expect(() => Ok(1).andThenAsync(panicFn2)).rejects.toThrow(Error('error')); }); + + it('should have correct examples doc', async () => { + async function examples() { + const parseJSON = (json: string) => + Promise.resolve( + resultify + .sync()(JSON.parse)(json) + .mapErr((err) => err.message), + ); + + const x = await Ok('2').andThenAsync(parseJSON); + assert(x.equal(Ok(2))); + + const y = await Ok('asdf').andThenAsync(parseJSON); + assert(y.equal(Err('Unexpected token \'a\', "asdf" is not valid JSON'))); + + const z = await Err('not a valid json string').andThenAsync(parseJSON); + assert(z.equal(Err('not a valid json string'))); + } + + await expect(examples()).resolves.not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.or.name}\``, () => { @@ -901,6 +1346,31 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot expect(op2().or(Ok(667))).toStrictEqual(Ok(667)); expect(op2().or(Err('bad'))).toStrictEqual(Err('bad')); }); + + it('should have correct examples doc', () => { + function examples() { + let x: Result; + let y: Result; + + x = Ok(2); + y = Err('late error'); + assert(x.or(y).equal(Ok(2))); + + x = Err('early error'); + y = Ok(2); + assert(x.or(y).equal(Ok(2))); + + x = Err('not a 2'); + y = Err('late error'); + assert(x.or(y).equal(Err('late error'))); + + x = Ok(2); + y = Ok(100); + assert(x.or(y).equal(Ok(2))); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.orElse.name}\``, () => { @@ -931,6 +1401,20 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot it('should panic if fn panic', () => { expect(() => Err('err').orElse(panicFn1)).toThrow(Error('error')); }); + + it('should have correct examples doc', () => { + function examples() { + const sq = (num: number): Result => Ok(num * num); + const err = (num: number): Result => Err(num); + + assert(Ok(2).orElse(sq).orElse(sq).equal(Ok(2))); + assert(Ok(2).orElse(err).orElse(sq).equal(Ok(2))); + assert(Err(3).orElse(sq).orElse(err).equal(Ok(9))); + assert(Err(3).orElse(err).orElse(err).equal(Err(3))); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.orElseAsync.name}\``, () => { @@ -966,6 +1450,30 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot await expect(() => Err('err').orElseAsync(panicFn1)).rejects.toThrow(Error('error')); await expect(() => Err('err').orElseAsync(panicFn2)).rejects.toThrow(Error('error')); }); + + it('should have correct examples doc', async () => { + async function examples() { + const sq = (num: number): Promise> => Promise.resolve(Ok(num * num)); + const err = (num: number): Promise> => Promise.resolve(Err(num)); + + const x = await Ok(2) + .orElseAsync(sq) + .then((result) => result.orElseAsync(sq)); + assert(x.equal(Ok(2))); + + const y = await Err(3) + .orElseAsync(sq) + .then((result) => result.orElseAsync(err)); + assert(y.equal(Ok(9))); + + const z = await Err(3) + .orElseAsync(err) + .then((result) => result.orElseAsync(err)); + assert(z.equal(Err(3))); + } + + await expect(examples()).resolves.not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.transpose.name}\``, () => { @@ -977,6 +1485,29 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot Err('Some error message'), ); }); + + it('should have correct examples doc', () => { + function examples() { + type SomeErr = unknown; + + let x: Result; + let y: Result | undefined; + + x = Ok(5); + y = Ok(5); + assert(x.transpose()!.equal(y)); + + x = Ok(undefined); + y = undefined; + assert(x.transpose() === y); + + x = Ok(null); + y = undefined; + assert(x.transpose() === y); + } + + expect(examples).not.toThrow(); + }); }); describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.equal.name}\``, () => { diff --git a/src/result.ts b/src/result.ts index 94ec535..60a0032 100644 --- a/src/result.ts +++ b/src/result.ts @@ -26,14 +26,14 @@ export class RustlikeResult implements Result { } /** - * Contains the success value. + * Creates a `Result` that contains the success value. */ static Ok(value: T): Result { return new RustlikeResult('ok', value); } /** - * Contains the error value. + * Creates a `Result` that contains the error value. */ static Err(error: E): Result { return new RustlikeResult('err', error); @@ -42,6 +42,18 @@ export class RustlikeResult implements Result { /** * Returns `true` if the result is `Ok`. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(2); + * assert(x.isOk() === true); + * + * const y: Result = Err('Some error message'); + * assert(y.isOk() === false); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_ok */ isOk(): boolean { @@ -51,6 +63,21 @@ export class RustlikeResult implements Result { /** * Returns `true` if the result is `Ok` and the value inside of it matches a predicate. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(2); + * assert(x.isOkAnd((value) => value > 1) === true); + * + * const y: Result = Ok(0); + * assert(y.isOkAnd((value) => value > 1) === false); + * + * const z: Result = Err('Some error message'); + * assert(z.isOkAnd((value) => value > 1) === false); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_ok_and */ isOkAnd(fn: (value: T) => boolean): boolean { @@ -60,6 +87,21 @@ export class RustlikeResult implements Result { /** * Asynchronously returns `true` if the result is `Ok` and the value inside of it matches a predicate. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(2); + * assert((await x.isOkAndAsync((value) => Promise.resolve(value > 1))) === true); + * + * const y: Result = Ok(0); + * assert((await y.isOkAndAsync((value) => Promise.resolve(value > 1))) === false); + * + * const z: Result = Err('Some error message'); + * assert((await z.isOkAndAsync((value) => Promise.resolve(value > 1))) === false); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_ok_and */ async isOkAndAsync(fn: (value: T) => boolean | Promise): Promise { @@ -69,6 +111,18 @@ export class RustlikeResult implements Result { /** * Returns `true` if the result is `Err`. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(-3); + * assert(x.isErr() === false); + * + * const y: Result = Err('Some error message'); + * assert(y.isErr() === true); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_err */ isErr(): boolean { @@ -78,6 +132,26 @@ export class RustlikeResult implements Result { /** * Returns `true` if the result is `Err` and the value inside of it matches a predicate. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * enum ErrorKind { + * NOT_FOUND, + * PERMISSION_DENIED, + * } + * + * const x: Result = Err(ErrorKind.NOT_FOUND); + * assert(x.isErrAnd((value) => value === ErrorKind.NOT_FOUND) === true); + * + * const y: Result = Err(ErrorKind.PERMISSION_DENIED); + * assert(y.isErrAnd((value) => value === ErrorKind.NOT_FOUND) === false); + * + * const z: Result = Ok(123); + * assert(z.isErrAnd((value) => value === ErrorKind.NOT_FOUND) === false); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_err_and */ isErrAnd(fn: (err: E) => boolean): boolean { @@ -87,6 +161,26 @@ export class RustlikeResult implements Result { /** * Asynchronously returns `true` if the result is `Err` and the value inside of it matches a predicate. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * enum ErrorKind { + * NOT_FOUND, + * PERMISSION_DENIED, + * } + * + * const x: Result = Err(ErrorKind.NOT_FOUND); + * assert((await x.isErrAndAsync((value) => Promise.resolve(value === ErrorKind.NOT_FOUND))) === true); + * + * const y: Result = Err(ErrorKind.PERMISSION_DENIED); + * assert((await y.isErrAndAsync((value) => Promise.resolve(value === ErrorKind.NOT_FOUND))) === false); + * + * const z: Result = Ok(123); + * assert((await z.isErrAndAsync((value) => Promise.resolve(value === ErrorKind.NOT_FOUND))) === false); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_err_and */ async isErrAndAsync(fn: (err: E) => boolean | Promise): Promise { @@ -96,6 +190,18 @@ export class RustlikeResult implements Result { /** * Converts from `Result` to `Optional` and discarding the error, if any. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(2); + * assert(x.ok() === 2); + * + * const y: Result = Err('Some error message'); + * assert(y.ok() === undefined); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.ok */ ok(): Optional { @@ -105,6 +211,18 @@ export class RustlikeResult implements Result { /** * Converts from `Result` to `Optional` and discarding the success value, if any. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(2); + * assert(x.err() === undefined); + * + * const y: Result = Err('Some error message'); + * assert(y.err() === 'Some error message'); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.err */ err(): Optional { @@ -117,6 +235,15 @@ export class RustlikeResult implements Result { * * This function can be used to compose the results of two functions. * + * Examples: + * + * ``` + * import { Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok('foo'); + * assert(x.map((value) => value.length).ok() === 3); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.map */ map(op: (value: T) => U): Result { @@ -129,6 +256,15 @@ export class RustlikeResult implements Result { * * This function can be used to compose the results of two functions. * + * Examples: + * + * ``` + * import { Ok } from 'rustlike-result'; + * + * const x = await Ok('foo').mapAsync((value) => Promise.resolve(value.length)); + * assert(x.ok() === 3); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.map */ async mapAsync(op: (value: T) => U | Promise): Promise> { @@ -142,6 +278,18 @@ export class RustlikeResult implements Result { * if you are passing the result of a function call, * it is recommended to use `mapOrElse`, which is lazily evaluated. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok('foo'); + * assert(x.mapOr(42, (value) => value.length) === 3); + * + * const y: Result = Err('bar'); + * assert(y.mapOr(42, (value) => value.length) === 42); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or */ mapOr(fallback: U, map: (value: T) => U): U { @@ -156,6 +304,18 @@ export class RustlikeResult implements Result { * if you are passing the result of a function call, * it is recommended to use `mapOrElse`, which is lazily evaluated. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok('foo'); + * assert((await x.mapOrAsync(42, (value) => value.length)) === 3); + * + * const y: Result = Err('bar'); + * assert((await y.mapOrAsync(42, (value) => value.length)) === 42); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or */ async mapOrAsync(fallback: U, map: (value: T) => U | Promise): Promise { @@ -168,6 +328,20 @@ export class RustlikeResult implements Result { * * This function can be used to unpack a successful result while handling an error. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const k = 21; + * + * const x: Result = Ok('foo'); + * assert(x.mapOrElse((err) => k * 2, (value) => value.length) === 3); + * + * const y: Result = Err('bar'); + * assert(y.mapOrElse((err) => k * 2, (value) => value.length) === 42); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or_else */ mapOrElse(fallback: (err: E) => U, map: (value: T) => U): U { @@ -180,6 +354,20 @@ export class RustlikeResult implements Result { * * This function can be used to unpack a successful result while handling an error. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const k = 21; + * + * const x: Result = Ok('foo'); + * assert((await x.mapOrElseAsync(() => Promise.resolve(k * 2), (value) => Promise.resolve(value.length))) === 3); + * + * const y: Result = Err('bar'); + * assert((await y.mapOrElseAsync(() => Promise.resolve(k * 2), (value) => Promise.resolve(value.length))) === 42); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or_else */ async mapOrElseAsync(fallback: (err: E) => U | Promise, map: (value: T) => U | Promise): Promise { @@ -192,6 +380,15 @@ export class RustlikeResult implements Result { * * This function can be used to pass through a successful result while handling an error. * + * Examples: + * + * ``` + * import { Err, type Result } from 'rustlike-result'; + * + * const x: Result = Err(new Error('Some error message')); + * assert(x.mapErr((err) => err.message).err() === 'Some error message'); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_err */ mapErr(op: (err: E) => F): Result { @@ -204,6 +401,15 @@ export class RustlikeResult implements Result { * * This function can be used to pass through a successful result while handling an error. * + * Examples: + * + * ``` + * import { Err } from 'rustlike-result'; + * + * const x = await Err(new Error('Some error message')).mapErrAsync((err) => Promise.resolve(err.message)); + * assert(x.err() === 'Some error message'); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_err */ async mapErrAsync(op: (err: E) => F | Promise): Promise> { @@ -213,6 +419,19 @@ export class RustlikeResult implements Result { /** * Calls the provided closure with a reference to the contained value if `Ok`. * + * Examples: + * + * ``` + * import { resultify } from 'rustlike-result'; + * + * const num = resultify + * .sync()(JSON.parse)('4') + * .inspect((value: number) => console.log(`original: ${value}`)) + * .map((value) => value ** 3) + * .expect('failed to parse number'); + * assert(num === 64); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.inspect */ inspect(fn: (value: T) => void): this { @@ -225,6 +444,22 @@ export class RustlikeResult implements Result { /** * Asynchronously calls the provided closure with a reference to the contained value if `Ok`. * + * Examples: + * + * ``` + * import { resultify } from 'rustlike-result'; + * + * const num = await resultify + * .sync()(JSON.parse)('4') + * .inspectAsync((value: number) => { + * console.log(`original: ${value}`); + * return Promise.resolve(); + * }) + * .then((result) => result.map((value) => value ** 3)) + * .then((result) => result.expect('failed to parse number')); + * assert(num === 64); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.inspect */ async inspectAsync(fn: (value: T) => void | Promise): Promise { @@ -237,6 +472,17 @@ export class RustlikeResult implements Result { /** * Calls the provided closure with a reference to the contained value if `Err`. * + * Examples: + * + * ``` + * import { resultify } from 'rustlike-result'; + * + * const num = resultify + * .sync()(JSON.parse)('asdf') + * .inspectErr((err) => console.log(`failed to parse json string: ${err.message}`)); + * assert(num.err() instanceof SyntaxError); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.inspect_err */ inspectErr(fn: (err: E) => void): this { @@ -249,6 +495,20 @@ export class RustlikeResult implements Result { /** * Asynchronously calls the provided closure with a reference to the contained value if `Err`. * + * Examples: + * + * ``` + * import { resultify } from 'rustlike-result'; + * + * const num = await resultify + * .sync()(JSON.parse)('asdf') + * .inspectErrAsync((err) => { + * console.log(`failed to parse json string: ${err.message}`); + * return Promise.resolve(); + * }); + * assert(num.err() instanceof SyntaxError); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.inspect_err */ async inspectErrAsync(fn: (err: E) => void | Promise): Promise { @@ -265,7 +525,20 @@ export class RustlikeResult implements Result { /** * Returns the contained `Ok` value. * - * Throws Error if itself is `Err`, with a error message provided by the `Err`'s value. + * Because this function may throw an error, its use is generally discouraged. + * Instead, prefer to call `unwrapOr`, `unwrapOrElse`. + * + * Throws an Error if itself is `Err`, + * with an error message including the passed message, and the content of the `Err`. + * + * Examples: + * + * ``` + * import { Err, type Result } from 'rustlike-result'; + * + * const x: Result = Err('emergency failure'); + * x.expect('Failed to operate'); // throws Error('Failed to operate: emergency failure') + * ``` * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.expect */ @@ -276,7 +549,22 @@ export class RustlikeResult implements Result { /** * Returns the contained `Ok` value. * - * Throws Error if itself is `Err`, with a error message provided by the `Err`'s value. + * Because this function may throw an error, its use is generally discouraged. + * Instead, prefer to call `unwrapOr`, `unwrapOrElse`. + * + * Throws an Error if itself is `Err`, with an error message provided by the `Err`'s value. + * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(2); + * assert(x.unwrap() === 2); + * + * const y: Result = Err('emergency failure'); + * y.unwrap(); // throws Error('emergency failure') + * ``` * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap */ @@ -288,7 +576,16 @@ export class RustlikeResult implements Result { /** * Returns the contained `Err` value. * - * Throws Error if itself is `Err`, with a error message provided by the `Err`'s value. + * Throws an Error if itself is `Err`, with an error message provided by the `Ok`'s value. + * + * Examples: + * + * ``` + * import { Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(10); + * x.expectErr('Testing expectErr'); // throws Error('Testing expectErr: 10') + * ``` * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.expect_err */ @@ -299,7 +596,19 @@ export class RustlikeResult implements Result { /** * Returns the contained `Err` value. * - * Throws Error if itself is `Ok`, with a error message provided by the `Ok`'s value. + * Throws an Error if itself is `Ok`, with an error message provided by the `Ok`'s value. + * + * Examples: + * + * ``` + * import { Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Err('emergency failure'); + * assert(x.unwrapErr() === 'emergency failure'); + * + * const y: Result = Ok(2); + * y.unwrapErr(); // throws Error(2) + * ``` * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_err */ @@ -315,6 +624,19 @@ export class RustlikeResult implements Result { * if you are passing the result of a function call, * it is recommended to use `unwrapOrElse`, which is lazily evaluated. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const $default = 2; + * const x: Result = Ok(9); + * assert(x.unwrapOr($default) === 9); + * + * const y: Result = Err('error'); + * assert(y.unwrapOr($default) === $default); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or */ unwrapOr(fallback: T): T { @@ -324,6 +646,16 @@ export class RustlikeResult implements Result { /** * Returns the contained `Ok` value or computes it from a closure. * + * Examples: + * + * ``` + * import { Err, Ok } from 'rustlike-result'; + * + * const count = (err: string) => err.length; + * assert(Ok(2).unwrapOrElse(count) === 2); + * assert(Err('foo').unwrapOrElse(count) === 3); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or_else */ unwrapOrElse(op: (err: E) => T): T { @@ -333,6 +665,16 @@ export class RustlikeResult implements Result { /** * Asynchronously returns the contained `Ok` value or computes it from a closure. * + * Examples: + * + * ``` + * import { Err, Ok } from 'rustlike-result'; + * + * const count = (err: string) => Promise.resolve(err.length); + * assert((await Ok(2).unwrapOrElseAsync(count)) === 2); + * assert((await Err('foo').unwrapOrElseAsync(count)) === 3); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or_else */ async unwrapOrElseAsync(op: (err: E) => T | Promise): Promise { @@ -345,6 +687,18 @@ export class RustlikeResult implements Result { * **SAFETY**: Calling this method on an `Err` is undefined behavior. * The safety contract must be upheld by the caller. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(2); + * assert(x.unwrapUnchecked() === 2); + * + * const y: Result = Err('emergency failure'); + * y.unwrapUnchecked(); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_unchecked */ // TODO: find a way to do the check in debug/development mode. @@ -358,6 +712,18 @@ export class RustlikeResult implements Result { * **SAFETY**: Calling this method on an `Ok` is undefined behavior. * The safety contract must be upheld by the caller. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(2); + * x.unwrapErrUnchecked(); + * + * const y: Result = Err('emergency failure'); + * assert(y.unwrapErrUnchecked() === 'emergency failure'); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_err_unchecked */ // TODO: find a way to do the check in debug/development mode. @@ -371,6 +737,31 @@ export class RustlikeResult implements Result { * Arguments passed to `and` are eagerly evaluated; * if you are passing the result of a function call, it is recommended to use `andThen`, which is lazily evaluated. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * let x: Result; + * let y: Result; + * + * x = Ok(2); + * y = Err('late error'); + * assert(x.and(y).equal(Err('late error'))); + * + * x = Err('early error'); + * y = Ok('foo'); + * assert(x.and(y).equal(Err('early error'))); + * + * x = Err('not a 2'); + * y = Err('late error'); + * assert(x.and(y).equal(Err('not a 2'))); + * + * x = Ok(2); + * y = Ok('different result type'); + * assert(x.and(y).equal(Ok('different result type'))); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.and */ and(res: Result): Result { @@ -382,6 +773,24 @@ export class RustlikeResult implements Result { * * This function can be used for control flow based on Result values. * + * Examples: + * + * ``` + * import { Err, Ok } from 'rustlike-result'; + * + * const parseJSON = (json: string) => + * resultify + * .sync()(JSON.parse)(json) + * .mapErr((err) => err.message); + * + * assert(Ok('2').andThen(parseJSON).equal(Ok(2))); + * assert( + * Ok('asdf') + * .andThen(parseJSON) + * .equal(Err('Unexpected token \'a\', "asdf" is not valid JSON')), + * ); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.and_then */ andThen(op: (value: T) => Result): Result { @@ -393,6 +802,28 @@ export class RustlikeResult implements Result { * * This function can be used for control flow based on Result values. * + * Examples: + * + * ``` + * import { Err, Ok } from 'rustlike-result'; + * + * const parseJSON = (json: string) => + * Promise.resolve( + * resultify + * .sync()(JSON.parse)(json) + * .mapErr((err) => err.message), + * ); + * + * const x = await Ok('2').andThenAsync(parseJSON); + * assert(x.equal(Ok(2))); + * + * const y = await Ok('asdf').andThenAsync(parseJSON); + * assert(y.equal(Err('Unexpected token \'a\', "asdf" is not valid JSON'))); + * + * const z = await Err('not a valid json string').andThenAsync(parseJSON); + * assert(z.equal(Err('not a valid json string'))); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.and_then */ async andThenAsync(op: (value: T) => Result | Promise>): Promise> { @@ -405,6 +836,31 @@ export class RustlikeResult implements Result { * Arguments passed to `or` are eagerly evaluated; * if you are passing the result of a function call, it is recommended to use `orElse`, which is lazily evaluated. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * let x: Result; + * let y: Result; + * + * x = Ok(2); + * y = Err('late error'); + * assert(x.or(y).equal(Ok(2))); + * + * x = Err('early error'); + * y = Ok(2); + * assert(x.or(y).equal(Ok(2))); + * + * x = Err('not a 2'); + * y = Err('late error'); + * assert(x.or(y).equal(Err('late error'))); + * + * x = Ok(2); + * y = Ok(100); + * assert(x.and(y).equal(Ok('different result type'))); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.or */ or(res: Result): Result { @@ -416,6 +872,20 @@ export class RustlikeResult implements Result { * * This function can be used for control flow based on result values. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const sq = (num: number): Result => Ok(num * num); + * const err = (num: number): Result => Err(num); + * + * assert(Ok(2).orElse(sq).orElse(sq).equal(Ok(2))); + * assert(Ok(2).orElse(err).orElse(sq).equal(Ok(2))); + * assert(Err(3).orElse(sq).orElse(err).equal(Ok(9))); + * assert(Err(3).orElse(err).orElse(err).equal(Err(3))); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.or_else */ orElse(op: (err: E) => Result): Result { @@ -427,6 +897,30 @@ export class RustlikeResult implements Result { * * This function can be used for control flow based on result values. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const sq = (num: number): Promise> => Promise.resolve(Ok(num * num)); + * const err = (num: number): Promise> => Promise.resolve(Err(num)); + * + * const x = await Ok(2) + * .orElseAsync(sq) + * .then((result) => result.orElseAsync(sq)); + * assert(x.equal(Ok(2))); + * + * const y = await Err(3) + * .orElseAsync(sq) + * .then((result) => result.orElseAsync(err)); + * assert(y.equal(Ok(9))); + * + * const z = await Err(3) + * .orElseAsync(err) + * .then((result) => result.orElseAsync(err)); + * assert(z.equal(Err(3))); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.or_else */ async orElseAsync(op: (err: E) => Result | Promise>): Promise> { @@ -435,9 +929,32 @@ export class RustlikeResult implements Result { /** * Transposes a `Result` of an optional value into an optional of a `Result`. - * - `Ok(undefined | null)` will be mapped to `undefined`. - * - `Ok(_)` (`Ok(Some(_))` in Rust) will be mapped to `Ok(_)` (`Some(Ok(_))` in Rust). - * - `Err(_)` will be mapped to `Err(_)` (`Some(Err(_))` in Rust). + * + * `Ok(undefined | null)` will be mapped to `undefined`. + * `Ok(_)` and `Err(_)` will be mapped to `Ok(_)` and `Err(_)`. + * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * type SomeErr = unknown; + * + * let x: Result; + * let y: Result | undefined; + * + * x = Ok(5); + * y = Ok(5); + * assert(x.transpose()!.equal(y)); + * + * x = Ok(undefined); + * y = undefined; + * assert(x.transpose() === y); + * + * x = Ok(null); + * y = undefined; + * assert(x.transpose() === y); + * ``` * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.transpose */ diff --git a/src/types.ts b/src/types.ts index 8a8ccd4..f5b51f2 100644 --- a/src/types.ts +++ b/src/types.ts @@ -14,6 +14,18 @@ export interface Result { /** * Returns `true` if the result is `Ok`. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(2); + * assert(x.isOk() === true); + * + * const y: Result = Err('Some error message'); + * assert(y.isOk() === false); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_ok */ isOk(): boolean; @@ -21,6 +33,21 @@ export interface Result { /** * Returns `true` if the result is `Ok` and the value inside of it matches a predicate. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(2); + * assert(x.isOkAnd((value) => value > 1) === true); + * + * const y: Result = Ok(0); + * assert(y.isOkAnd((value) => value > 1) === false); + * + * const z: Result = Err('Some error message'); + * assert(z.isOkAnd((value) => value > 1) === false); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_ok_and */ isOkAnd(fn: (value: T) => boolean): boolean; @@ -28,6 +55,21 @@ export interface Result { /** * Asynchronously returns `true` if the result is `Ok` and the value inside of it matches a predicate. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(2); + * assert((await x.isOkAndAsync((value) => Promise.resolve(value > 1))) === true); + * + * const y: Result = Ok(0); + * assert((await y.isOkAndAsync((value) => Promise.resolve(value > 1))) === false); + * + * const z: Result = Err('Some error message'); + * assert((await z.isOkAndAsync((value) => Promise.resolve(value > 1))) === false); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_ok_and */ isOkAndAsync(fn: (value: T) => boolean | Promise): Promise; @@ -35,6 +77,18 @@ export interface Result { /** * Returns `true` if the result is `Err`. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(-3); + * assert(x.isErr() === false); + * + * const y: Result = Err('Some error message'); + * assert(y.isErr() === true); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_err */ isErr(): boolean; @@ -42,6 +96,26 @@ export interface Result { /** * Returns `true` if the result is `Err` and the value inside of it matches a predicate. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * enum ErrorKind { + * NOT_FOUND, + * PERMISSION_DENIED, + * } + * + * const x: Result = Err(ErrorKind.NOT_FOUND); + * assert(x.isErrAnd((value) => value === ErrorKind.NOT_FOUND) === true); + * + * const y: Result = Err(ErrorKind.PERMISSION_DENIED); + * assert(y.isErrAnd((value) => value === ErrorKind.NOT_FOUND) === false); + * + * const z: Result = Ok(123); + * assert(z.isErrAnd((value) => value === ErrorKind.NOT_FOUND) === false); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_err_and */ isErrAnd(fn: (err: E) => boolean): boolean; @@ -49,6 +123,26 @@ export interface Result { /** * Asynchronously returns `true` if the result is `Err` and the value inside of it matches a predicate. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * enum ErrorKind { + * NOT_FOUND, + * PERMISSION_DENIED, + * } + * + * const x: Result = Err(ErrorKind.NOT_FOUND); + * assert((await x.isErrAndAsync((value) => Promise.resolve(value === ErrorKind.NOT_FOUND))) === true); + * + * const y: Result = Err(ErrorKind.PERMISSION_DENIED); + * assert((await y.isErrAndAsync((value) => Promise.resolve(value === ErrorKind.NOT_FOUND))) === false); + * + * const z: Result = Ok(123); + * assert((await z.isErrAndAsync((value) => Promise.resolve(value === ErrorKind.NOT_FOUND))) === false); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_err_and */ isErrAndAsync(fn: (err: E) => boolean | Promise): Promise; @@ -56,6 +150,18 @@ export interface Result { /** * Converts from `Result` to `Optional` and discarding the error, if any. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(2); + * assert(x.ok() === 2); + * + * const y: Result = Err('Some error message'); + * assert(y.ok() === undefined); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.ok */ ok(): Optional; @@ -63,6 +169,18 @@ export interface Result { /** * Converts from `Result` to `Optional` and discarding the success value, if any. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(2); + * assert(x.err() === undefined); + * + * const y: Result = Err('Some error message'); + * assert(y.err() === 'Some error message'); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.err */ err(): Optional; @@ -73,6 +191,15 @@ export interface Result { * * This function can be used to compose the results of two functions. * + * Examples: + * + * ``` + * import { Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok('foo'); + * assert(x.map((value) => value.length).ok() === 3); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.map */ map(op: (value: T) => U): Result; @@ -83,6 +210,15 @@ export interface Result { * * This function can be used to compose the results of two functions. * + * Examples: + * + * ``` + * import { Ok } from 'rustlike-result'; + * + * const x = await Ok('foo').mapAsync((value) => Promise.resolve(value.length)); + * assert(x.ok() === 3); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.map */ mapAsync(op: (value: T) => U | Promise): Promise>; @@ -94,6 +230,18 @@ export interface Result { * if you are passing the result of a function call, * it is recommended to use `mapOrElse`, which is lazily evaluated. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok('foo'); + * assert(x.mapOr(42, (value) => value.length) === 3); + * + * const y: Result = Err('bar'); + * assert(y.mapOr(42, (value) => value.length) === 42); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or */ mapOr(fallback: U, map: (value: T) => U): U; @@ -106,6 +254,18 @@ export interface Result { * if you are passing the result of a function call, * it is recommended to use `mapOrElse`, which is lazily evaluated. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok('foo'); + * assert((await x.mapOrAsync(42, (value) => value.length)) === 3); + * + * const y: Result = Err('bar'); + * assert((await y.mapOrAsync(42, (value) => value.length)) === 42); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or */ mapOrAsync(fallback: U, map: (value: T) => U | Promise): Promise; @@ -116,6 +276,20 @@ export interface Result { * * This function can be used to unpack a successful result while handling an error. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const k = 21; + * + * const x: Result = Ok('foo'); + * assert(x.mapOrElse((err) => k * 2, (value) => value.length) === 3); + * + * const y: Result = Err('bar'); + * assert(y.mapOrElse((err) => k * 2, (value) => value.length) === 42); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or_else */ mapOrElse(fallback: (err: E) => U, map: (value: T) => U): U; @@ -126,6 +300,20 @@ export interface Result { * * This function can be used to unpack a successful result while handling an error. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const k = 21; + * + * const x: Result = Ok('foo'); + * assert((await x.mapOrElseAsync(() => Promise.resolve(k * 2), (value) => Promise.resolve(value.length))) === 3); + * + * const y: Result = Err('bar'); + * assert((await y.mapOrElseAsync(() => Promise.resolve(k * 2), (value) => Promise.resolve(value.length))) === 42); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or_else */ mapOrElseAsync(fallback: (err: E) => U | Promise, map: (value: T) => U | Promise): Promise; @@ -136,6 +324,15 @@ export interface Result { * * This function can be used to pass through a successful result while handling an error. * + * Examples: + * + * ``` + * import { Err, type Result } from 'rustlike-result'; + * + * const x: Result = Err(new Error('Some error message')); + * assert(x.mapErr((err) => err.message).err() === 'Some error message'); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_err */ mapErr(op: (err: E) => F): Result; @@ -146,6 +343,15 @@ export interface Result { * * This function can be used to pass through a successful result while handling an error. * + * Examples: + * + * ``` + * import { Err } from 'rustlike-result'; + * + * const x = await Err(new Error('Some error message')).mapErrAsync((err) => Promise.resolve(err.message)); + * assert(x.err() === 'Some error message'); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_err */ mapErrAsync(op: (err: E) => F | Promise): Promise>; @@ -153,6 +359,19 @@ export interface Result { /** * Calls the provided closure with a reference to the contained value if `Ok`. * + * Examples: + * + * ``` + * import { resultify } from 'rustlike-result'; + * + * const num = resultify + * .sync()(JSON.parse)('4') + * .inspect((value: number) => console.log(`original: ${value}`)) + * .map((value) => value ** 3) + * .expect('failed to parse number'); + * assert(num === 64); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.inspect */ inspect(fn: (value: T) => void): this; @@ -160,6 +379,22 @@ export interface Result { /** * Asynchronously calls the provided closure with a reference to the contained value if `Ok`. * + * Examples: + * + * ``` + * import { resultify } from 'rustlike-result'; + * + * const num = await resultify + * .sync()(JSON.parse)('4') + * .inspectAsync((value: number) => { + * console.log(`original: ${value}`); + * return Promise.resolve(); + * }) + * .then((result) => result.map((value) => value ** 3)) + * .then((result) => result.expect('failed to parse number')); + * assert(num === 64); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.inspect */ inspectAsync(fn: (value: T) => void | Promise): Promise; @@ -167,6 +402,17 @@ export interface Result { /** * Calls the provided closure with a reference to the contained value if `Err`. * + * Examples: + * + * ``` + * import { resultify } from 'rustlike-result'; + * + * const num = resultify + * .sync()(JSON.parse)('asdf') + * .inspectErr((err) => console.log(`failed to parse json string: ${err.message}`)); + * assert(num.err() instanceof SyntaxError); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.inspect_err */ inspectErr(fn: (err: E) => void): this; @@ -174,6 +420,20 @@ export interface Result { /** * Asynchronously calls the provided closure with a reference to the contained value if `Err`. * + * Examples: + * + * ``` + * import { resultify } from 'rustlike-result'; + * + * const num = await resultify + * .sync()(JSON.parse)('asdf') + * .inspectErrAsync((err) => { + * console.log(`failed to parse json string: ${err.message}`); + * return Promise.resolve(); + * }); + * assert(num.err() instanceof SyntaxError); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.inspect_err */ inspectErrAsync(fn: (err: E) => void | Promise): Promise; @@ -181,7 +441,20 @@ export interface Result { /** * Returns the contained `Ok` value. * - * Throws Error if itself is `Err`, with a error message provided by the `Err`'s value. + * Because this function may throw an error, its use is generally discouraged. + * Instead, prefer to call `unwrapOr`, `unwrapOrElse`. + * + * Throws an Error if itself is `Err`, + * with an error message including the passed message, and the content of the `Err`. + * + * Examples: + * + * ``` + * import { Err, type Result } from 'rustlike-result'; + * + * const x: Result = Err('emergency failure'); + * x.expect('Failed to operate'); // throws Error('Failed to operate: emergency failure') + * ``` * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.expect */ @@ -190,7 +463,22 @@ export interface Result { /** * Returns the contained `Ok` value. * - * Throws Error if itself is `Err`, with a error message provided by the `Err`'s value. + * Because this function may throw an error, its use is generally discouraged. + * Instead, prefer to call `unwrapOr`, `unwrapOrElse`. + * + * Throws an Error if itself is `Err`, with an error message provided by the `Err`'s value. + * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(2); + * assert(x.unwrap() === 2); + * + * const y: Result = Err('emergency failure'); + * y.unwrap(); // throws Error('emergency failure') + * ``` * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap */ @@ -199,7 +487,16 @@ export interface Result { /** * Returns the contained `Err` value. * - * Throws Error if itself is `Err`, with a error message provided by the `Err`'s value. + * Throws an Error if itself is `Err`, with an error message provided by the `Ok`'s value. + * + * Examples: + * + * ``` + * import { Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(10); + * x.expectErr('Testing expectErr'); // throws Error('Testing expectErr: 10') + * ``` * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.expect_err */ @@ -208,7 +505,19 @@ export interface Result { /** * Returns the contained `Err` value. * - * Throws Error if itself is `Ok`, with a error message provided by the `Ok`'s value. + * Throws an Error if itself is `Ok`, with an error message provided by the `Ok`'s value. + * + * Examples: + * + * ``` + * import { Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Err('emergency failure'); + * assert(x.unwrapErr() === 'emergency failure'); + * + * const y: Result = Ok(2); + * y.unwrapErr(); // throws Error(2) + * ``` * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_err */ @@ -221,6 +530,19 @@ export interface Result { * if you are passing the result of a function call, * it is recommended to use `unwrapOrElse`, which is lazily evaluated. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const $default = 2; + * const x: Result = Ok(9); + * assert(x.unwrapOr($default) === 9); + * + * const y: Result = Err('error'); + * assert(y.unwrapOr($default) === $default); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or */ unwrapOr(fallback: T): T; @@ -228,6 +550,16 @@ export interface Result { /** * Returns the contained `Ok` value or computes it from a closure. * + * Examples: + * + * ``` + * import { Err, Ok } from 'rustlike-result'; + * + * const count = (err: string) => err.length; + * assert(Ok(2).unwrapOrElse(count) === 2); + * assert(Err('foo').unwrapOrElse(count) === 3); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or_else */ unwrapOrElse(op: (err: E) => T): T; @@ -235,6 +567,16 @@ export interface Result { /** * Asynchronously returns the contained `Ok` value or computes it from a closure. * + * Examples: + * + * ``` + * import { Err, Ok } from 'rustlike-result'; + * + * const count = (err: string) => Promise.resolve(err.length); + * assert((await Ok(2).unwrapOrElseAsync(count)) === 2); + * assert((await Err('foo').unwrapOrElseAsync(count)) === 3); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or_else */ unwrapOrElseAsync(op: (err: E) => T | Promise): Promise; @@ -245,6 +587,18 @@ export interface Result { * **SAFETY**: Calling this method on an `Err` is undefined behavior. * The safety contract must be upheld by the caller. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(2); + * assert(x.unwrapUnchecked() === 2); + * + * const y: Result = Err('emergency failure'); + * y.unwrapUnchecked(); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_unchecked */ unwrapUnchecked(): T; @@ -255,6 +609,18 @@ export interface Result { * **SAFETY**: Calling this method on an `Ok` is undefined behavior. * The safety contract must be upheld by the caller. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const x: Result = Ok(2); + * x.unwrapErrUnchecked(); + * + * const y: Result = Err('emergency failure'); + * assert(y.unwrapErrUnchecked() === 'emergency failure'); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_err_unchecked */ unwrapErrUnchecked(): E; @@ -265,6 +631,31 @@ export interface Result { * Arguments passed to `and` are eagerly evaluated; * if you are passing the result of a function call, it is recommended to use `andThen`, which is lazily evaluated. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * let x: Result; + * let y: Result; + * + * x = Ok(2); + * y = Err('late error'); + * assert(x.and(y).equal(Err('late error'))); + * + * x = Err('early error'); + * y = Ok('foo'); + * assert(x.and(y).equal(Err('early error'))); + * + * x = Err('not a 2'); + * y = Err('late error'); + * assert(x.and(y).equal(Err('not a 2'))); + * + * x = Ok(2); + * y = Ok('different result type'); + * assert(x.and(y).equal(Ok('different result type'))); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.and */ and(res: Result): Result; @@ -274,6 +665,24 @@ export interface Result { * * This function can be used for control flow based on Result values. * + * Examples: + * + * ``` + * import { Err, Ok } from 'rustlike-result'; + * + * const parseJSON = (json: string) => + * resultify + * .sync()(JSON.parse)(json) + * .mapErr((err) => err.message); + * + * assert(Ok('2').andThen(parseJSON).equal(Ok(2))); + * assert( + * Ok('asdf') + * .andThen(parseJSON) + * .equal(Err('Unexpected token \'a\', "asdf" is not valid JSON')), + * ); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.and_then */ andThen(op: (value: T) => Result): Result; @@ -283,6 +692,28 @@ export interface Result { * * This function can be used for control flow based on Result values. * + * Examples: + * + * ``` + * import { Err, Ok } from 'rustlike-result'; + * + * const parseJSON = (json: string) => + * Promise.resolve( + * resultify + * .sync()(JSON.parse)(json) + * .mapErr((err) => err.message), + * ); + * + * const x = await Ok('2').andThenAsync(parseJSON); + * assert(x.equal(Ok(2))); + * + * const y = await Ok('asdf').andThenAsync(parseJSON); + * assert(y.equal(Err('Unexpected token \'a\', "asdf" is not valid JSON'))); + * + * const z = await Err('not a valid json string').andThenAsync(parseJSON); + * assert(z.equal(Err('not a valid json string'))); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.and_then */ andThenAsync(op: (value: T) => Result | Promise>): Promise>; @@ -293,6 +724,31 @@ export interface Result { * Arguments passed to `or` are eagerly evaluated; * if you are passing the result of a function call, it is recommended to use `orElse`, which is lazily evaluated. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * let x: Result; + * let y: Result; + * + * x = Ok(2); + * y = Err('late error'); + * assert(x.or(y).equal(Ok(2))); + * + * x = Err('early error'); + * y = Ok(2); + * assert(x.or(y).equal(Ok(2))); + * + * x = Err('not a 2'); + * y = Err('late error'); + * assert(x.or(y).equal(Err('late error'))); + * + * x = Ok(2); + * y = Ok(100); + * assert(x.and(y).equal(Ok('different result type'))); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.or */ or(res: Result): Result; @@ -302,6 +758,20 @@ export interface Result { * * This function can be used for control flow based on result values. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const sq = (num: number): Result => Ok(num * num); + * const err = (num: number): Result => Err(num); + * + * assert(Ok(2).orElse(sq).orElse(sq).equal(Ok(2))); + * assert(Ok(2).orElse(err).orElse(sq).equal(Ok(2))); + * assert(Err(3).orElse(sq).orElse(err).equal(Ok(9))); + * assert(Err(3).orElse(err).orElse(err).equal(Err(3))); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.or_else */ orElse(op: (err: E) => Result): Result; @@ -311,15 +781,62 @@ export interface Result { * * This function can be used for control flow based on result values. * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * const sq = (num: number): Promise> => Promise.resolve(Ok(num * num)); + * const err = (num: number): Promise> => Promise.resolve(Err(num)); + * + * const x = await Ok(2) + * .orElseAsync(sq) + * .then((result) => result.orElseAsync(sq)); + * assert(x.equal(Ok(2))); + * + * const y = await Err(3) + * .orElseAsync(sq) + * .then((result) => result.orElseAsync(err)); + * assert(y.equal(Ok(9))); + * + * const z = await Err(3) + * .orElseAsync(err) + * .then((result) => result.orElseAsync(err)); + * assert(z.equal(Err(3))); + * ``` + * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.or_else */ orElseAsync(op: (err: E) => Result | Promise>): Promise>; /** * Transposes a `Result` of an optional value into an optional of a `Result`. - * - `Ok(undefined | null)` will be mapped to `undefined`. - * - `Ok(_)` (`Ok(Some(_))` in Rust) will be mapped to `Ok(_)` (`Some(Ok(_))` in Rust). - * - `Err(_)` will be mapped to `Err(_)` (`Some(Err(_))` in Rust). + * + * `Ok(undefined | null)` will be mapped to `undefined`. + * `Ok(_)` and `Err(_)` will be mapped to `Ok(_)` and `Err(_)`. + * + * Examples: + * + * ``` + * import { Err, Ok, type Result } from 'rustlike-result'; + * + * type SomeErr = unknown; + * + * let x: Result; + * let y: Result | undefined; + * + * x = Ok(5); + * y = Ok(5); + * assert(x.transpose()!.equal(y)); + * + * x = Ok(undefined); + * y = undefined; + * assert(x.transpose() === y); + * + * x = Ok(null); + * y = undefined; + * assert(x.transpose() === y); + * ``` * * ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.transpose */