From 1b6462aff1ae382125a780b8251df689af1b1d68 Mon Sep 17 00:00:00 2001 From: yifanwww Date: Tue, 20 Aug 2024 22:50:38 +0800 Subject: [PATCH 1/2] feat: remove deprecated resultify helpers --- README.md | 16 ++-- src/Result.ts | 32 +++---- src/__tests__/RustlikeResult.test.ts | 34 +++----- src/__tests__/resultify.test.ts | 84 +----------------- src/resultify.ts | 124 --------------------------- 5 files changed, 31 insertions(+), 259 deletions(-) diff --git a/README.md b/README.md index e68cf22..24bbefa 100644 --- a/README.md +++ b/README.md @@ -454,10 +454,9 @@ Calls the provided closure with a reference to the contained value if `Ok`. Examples: ```ts -import { resultify } from 'rustlike-result'; +import { resultifySync } from 'rustlike-result'; -const num = resultify - .sync()(JSON.parse)('4') +const num = resultifySync()(JSON.parse)('4') .inspect((value: number) => console.log(`original: ${value}`)) .map((value) => value ** 3) .expect('failed to parse number'); @@ -471,10 +470,9 @@ Calls the provided closure with a reference to the contained value if `Err`. Examples: ```ts -import { resultify } from 'rustlike-result'; +import { resultifySync } from 'rustlike-result'; -const num = resultify - .sync()(JSON.parse)('asdf') +const num = resultifySync()(JSON.parse)('asdf') .inspectErr((err) => console.log(`failed to parse json string: ${err.message}`)); assert(num.err() instanceof SyntaxError); ``` @@ -660,12 +658,10 @@ This function can be used for control flow based on `Result` values. Examples: ```ts -import { Err, Ok } from 'rustlike-result'; +import { Err, Ok, resultifySync } from 'rustlike-result'; const parseJSON = (json: string) => - resultify - .sync()(JSON.parse)(json) - .mapErr((err) => err.message); + resultifySync()(JSON.parse)(json).mapErr((err) => err.message); assert(Ok('2').andThen(parseJSON).equal(Ok(2))); assert( diff --git a/src/Result.ts b/src/Result.ts index 3894fee..b7b7898 100644 --- a/src/Result.ts +++ b/src/Result.ts @@ -375,10 +375,9 @@ export interface Result { * Examples: * * ``` - * import { resultify } from 'rustlike-result'; + * import { resultifySync } from 'rustlike-result'; * - * const num = resultify - * .sync()(JSON.parse)('4') + * const num = resultifySync()(JSON.parse)('4') * .inspect((value: number) => console.log(`original: ${value}`)) * .map((value) => value ** 3) * .expect('failed to parse number'); @@ -397,10 +396,9 @@ export interface Result { * Examples: * * ``` - * import { resultify } from 'rustlike-result'; + * import { resultifySync } from 'rustlike-result'; * - * const num = await resultify - * .sync()(JSON.parse)('4') + * const num = await resultifySync()(JSON.parse)('4') * .inspectAsync((value: number) => { * console.log(`original: ${value}`); * return Promise.resolve(); @@ -420,10 +418,9 @@ export interface Result { * Examples: * * ``` - * import { resultify } from 'rustlike-result'; + * import { resultifySync } from 'rustlike-result'; * - * const num = resultify - * .sync()(JSON.parse)('asdf') + * const num = resultifySync()(JSON.parse)('asdf') * .inspectErr((err) => console.log(`failed to parse json string: ${err.message}`)); * assert(num.err() instanceof SyntaxError); * ``` @@ -440,10 +437,9 @@ export interface Result { * Examples: * * ``` - * import { resultify } from 'rustlike-result'; + * import { resultifySync } from 'rustlike-result'; * - * const num = await resultify - * .sync()(JSON.parse)('asdf') + * const num = await resultifySync()(JSON.parse)('asdf') * .inspectErrAsync((err) => { * console.log(`failed to parse json string: ${err.message}`); * return Promise.resolve(); @@ -687,12 +683,10 @@ export interface Result { * Examples: * * ``` - * import { Err, Ok } from 'rustlike-result'; + * import { Err, Ok, resultifySync } from 'rustlike-result'; * * const parseJSON = (json: string) => - * resultify - * .sync()(JSON.parse)(json) - * .mapErr((err) => err.message); + * resultifySync()(JSON.parse)(json).mapErr((err) => err.message); * * assert(Ok('2').andThen(parseJSON).equal(Ok(2))); * assert( @@ -716,13 +710,11 @@ export interface Result { * Examples: * * ``` - * import { Err, Ok } from 'rustlike-result'; + * import { Err, Ok, resultifySync } from 'rustlike-result'; * * const parseJSON = (json: string) => * Promise.resolve( - * resultify - * .sync()(JSON.parse)(json) - * .mapErr((err) => err.message), + * resultifySync()(JSON.parse)(json).mapErr((err) => err.message), * ); * * const x = await Ok('2').andThenAsync(parseJSON); diff --git a/src/__tests__/RustlikeResult.test.ts b/src/__tests__/RustlikeResult.test.ts index 7ee1539..2730be8 100644 --- a/src/__tests__/RustlikeResult.test.ts +++ b/src/__tests__/RustlikeResult.test.ts @@ -3,7 +3,7 @@ import assert from 'node:assert'; import { Err, Ok } from '../factory'; import type { Result } from '../Result'; -import { resultify } from '../resultify'; +import { resultifySync } from '../resultify'; import { RustlikeResult } from '../RustlikeResult'; import { RustlikeResultAsync } from '../RustlikeResultAsync'; @@ -790,8 +790,7 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot jest.spyOn(console, 'log').mockImplementationOnce(() => {}); function examples() { - const num = resultify - .sync()(JSON.parse)('4') + const num = resultifySync()(JSON.parse)('4') .inspect((value: number) => console.log(`original: ${value}`)) .map((value) => value ** 3) .expect('failed to parse number'); @@ -853,8 +852,7 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot async function examples() { jest.spyOn(console, 'log').mockImplementationOnce(() => {}); - const num = await resultify - .sync()(JSON.parse)('4') + const num = await resultifySync()(JSON.parse)('4') .inspectAsync((value: number) => { console.log(`original: ${value}`); return Promise.resolve(); @@ -903,9 +901,9 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot 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}`)); + const num = resultifySync()(JSON.parse)('asdf').inspectErr((err) => + console.log(`failed to parse json string: ${err.message}`), + ); assert(num.err() instanceof SyntaxError); } @@ -964,12 +962,10 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot 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(); - }); + const num = await resultifySync()(JSON.parse)('asdf').inspectErrAsync((err) => { + console.log(`failed to parse json string: ${err.message}`); + return Promise.resolve(); + }); assert(num.err() instanceof SyntaxError); } @@ -1285,9 +1281,7 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot it('should have correct examples doc', () => { function examples() { const parseJSON = (json: string) => - resultify - .sync()(JSON.parse)(json) - .mapErr((err) => err.message); + resultifySync()(JSON.parse)(json).mapErr((err) => err.message); assert(Ok('2').andThen(parseJSON).equal(Ok(2))); assert( @@ -1339,11 +1333,7 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot 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), - ); + Promise.resolve(resultifySync()(JSON.parse)(json).mapErr((err) => err.message)); const x = await Ok('2').andThenAsync(parseJSON); assert(x.equal(Ok(2))); diff --git a/src/__tests__/resultify.test.ts b/src/__tests__/resultify.test.ts index 3847db7..22c5159 100644 --- a/src/__tests__/resultify.test.ts +++ b/src/__tests__/resultify.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from '@jest/globals'; -import { resultify, resultifyAsync, resultifyPromise, resultifySync } from '../resultify'; +import { resultifyAsync, resultifyPromise, resultifySync } from '../resultify'; import { RustlikeResult } from '../RustlikeResult'; import { RustlikeResultAsync } from '../RustlikeResultAsync'; @@ -20,64 +20,6 @@ async function asyncFn(throws: boolean) { } } -describe(`Test fn \`${resultify.name}\``, () => { - it('should resultify a sync function', async () => { - const fn = resultify(syncFn); - - const [result1, result2] = await Promise.all([fn(false), fn(true)]); - - expect(result1).toBeInstanceOf(RustlikeResult); - expect(result2).toBeInstanceOf(RustlikeResult); - expect(result1.isOk()).toBe(true); - expect(result1.unwrap()).toBe('hello world'); - expect(result2.isErr()).toBe(true); - expect(result2.unwrapErr()).toBeInstanceOf(Error); - expect((result2.unwrapErr() as Error).message).toBe('Some error message'); - }); - - it('should resultify an async function', async () => { - const fn = resultify(asyncFn); - - const [result1, result2] = await Promise.all([fn(false), fn(true)]); - - expect(result1).toBeInstanceOf(RustlikeResult); - expect(result2).toBeInstanceOf(RustlikeResult); - expect(result1.isOk()).toBe(true); - expect(result1.unwrap()).toBe('hello world'); - expect(result2.isErr()).toBe(true); - expect(result2.unwrapErr()).toBeInstanceOf(Error); - expect((result2.unwrapErr() as Error).message).toBe('Some error message'); - }); - - it('should resultify a sync function with error type specified', async () => { - const fn = resultify()(syncFn); - - const [result1, result2] = await Promise.all([fn(false), fn(true)]); - - expect(result1).toBeInstanceOf(RustlikeResult); - expect(result2).toBeInstanceOf(RustlikeResult); - expect(result1.isOk()).toBe(true); - expect(result1.unwrap()).toBe('hello world'); - expect(result2.isErr()).toBe(true); - expect(result2.unwrapErr()).toBeInstanceOf(Error); - expect(result2.unwrapErr().message).toBe('Some error message'); - }); - - it('should resultify an async function with error type specified', async () => { - const fn = resultify()(asyncFn); - - const [result1, result2] = await Promise.all([fn(false), fn(true)]); - - expect(result1).toBeInstanceOf(RustlikeResult); - expect(result2).toBeInstanceOf(RustlikeResult); - expect(result1.isOk()).toBe(true); - expect(result1.unwrap()).toBe('hello world'); - expect(result2.isErr()).toBe(true); - expect(result2.unwrapErr()).toBeInstanceOf(Error); - expect(result2.unwrapErr().message).toBe('Some error message'); - }); -}); - describe(`Test fn \`${resultifyAsync.name}\``, () => { it('should resultify a sync function', async () => { const fn = resultifyAsync(syncFn); @@ -170,30 +112,6 @@ describe(`Test fn \`${resultifySync.name}\``, () => { expect(result2.unwrapErr()).toBeInstanceOf(Error); expect(result2.unwrapErr().message).toBe('Some error message'); }); - - it('should be the same as resultify.sync', () => { - expect(resultifySync).toBe(resultify.sync); - }); -}); - -describe(`Test fn \`${resultify.promise.name}\``, () => { - it('should resultify a promise', async () => { - const promise1 = asyncFn(false); - const promise2 = asyncFn(true); - - const [result1, result2] = await Promise.all([ - resultify.promise(promise1), - resultify.promise(promise2), - ]); - - expect(result1).toBeInstanceOf(RustlikeResult); - expect(result2).toBeInstanceOf(RustlikeResult); - expect(result1.isOk()).toBe(true); - expect(result1.unwrap()).toBe('hello world'); - expect(result2.isErr()).toBe(true); - expect(result2.unwrapErr()).toBeInstanceOf(Error); - expect(result2.unwrapErr().message).toBe('Some error message'); - }); }); describe(`Test fn \`${resultifyPromise.name}\``, () => { diff --git a/src/resultify.ts b/src/resultify.ts index 713abb6..8c49543 100644 --- a/src/resultify.ts +++ b/src/resultify.ts @@ -5,14 +5,6 @@ import { RustlikeResultAsync } from './RustlikeResultAsync'; type NoVoid = T extends void ? undefined : T; -async function resultifyPromiseLegacy(promise: Promise): Promise, E>> { - try { - return Ok((await promise) as NoVoid); - } catch (err) { - return Err(err as E); - } -} - /** * Takes a promise and returns an async `Result`. * @@ -96,122 +88,6 @@ export function resultifySync( return fn ? curriedResultify(fn) : curriedResultify; } -type CurriedResultify = ( - fn: (...args: Args) => T | Promise, -) => (...args: Args) => Promise>, E>>; - -interface ResultifySignature { - /** - * @deprecated Please use `resultifyAsync` instead. - * - * Takes a function and returns a version that returns results asynchronously. - * - * Examples: - * ```ts - * import fs from 'node:fs/promises'; - * - * const copyFile = resultify(fs.copyFile); - * ``` - * - * If you need the error value and want to specify its type, please use another overloaded function. - */ - ( - fn: (...args: Args) => T | Promise, - ): (...args: Args) => Promise>, E>>; - /** - * @deprecated Please use `resultifyAsync` instead. - * - * Takes a function and returns a version that returns results asynchronously. - * This overloaded function allows you to specify the error type. - * - * Examples: - * ```ts - * import fs from 'node:fs/promises'; - * - * const copyFile = resultify()(fs.copyFile); - * ``` - */ - (): CurriedResultify; - - /** - * @deprecated Please use `resultifySync` instead. - * - * Takes a function and returns a version that returns results synchronously. - * - * Examples: - * ```ts - * function fn(): string { - * // throws error if failed - * } - * const fn1 = resultify.sync(fn); - * ``` - * - * In the context where async functions are not allowed, you can use this function to resultify the sync function. - * If you want to resultify an async function, please use `resultify` instead. - * - * If you need the error value and want to specify its type, please use another overloaded function. - */ - sync(fn: (...args: Args) => T): (...args: Args) => Result, E>; - /** - * @deprecated Please use `resultifySync` instead. - * - * Takes a function and returns a version that returns results synchronously. - * - * Examples: - * ```ts - * function fn(): string { - * // throws error if failed - * } - * const fn1 = resultify.sync()(fn); - * ``` - * - * In the context where async functions are not allowed, you can use this function to resultify the sync function. - * If you want to resultify an async function, please use `resultify` instead. - */ - sync(): CurriedResultifySync; - - /** - * @deprecated Please use `resultifyPromise` instead. - * - * Takes a promise and returns a new promise that contains a result. - * - * Examples: - * ```ts - * const result = await resultify.promise(promise); - * ``` - * - * Due to the limit of TypeScript,it's impossible to resultify overloaded functions perfectly that - * the returned functions are still overloaded. - * This function allows you to resultify the promise that the overloaded functions return. - */ - promise(promise: Promise): Promise, E>>; -} - -function resultifyLegacy( - fn: (...args: Args) => T | Promise, -): (...args: Args) => Promise>, E>>; - -function resultifyLegacy(): CurriedResultify; -function resultifyLegacy( - fn?: (...args: Args) => T | Promise, -): CurriedResultify | ((...args: Args) => Promise>, E>>) { - function curriedResultify(_fn: (...args: TArgs) => TT | Promise) { - return async function resultifiedFn(...args: TArgs): Promise>, E>> { - try { - return Ok((await _fn(...args)) as NoVoid>); - } catch (err) { - return Err(err as E); - } - }; - } - - return fn ? curriedResultify(fn) : curriedResultify; -} - -export const resultify = resultifyLegacy as ResultifySignature; -resultify.sync = resultifySync; -resultify.promise = resultifyPromiseLegacy; - type CurriedResultifyAsync = ( fn: (...args: Args) => T | Promise, ) => (...args: Args) => ResultAsync>, E>; From 51683ca8333bf2e66dad4ca654347940a612ba53 Mon Sep 17 00:00:00 2001 From: yifanwww Date: Tue, 20 Aug 2024 23:01:19 +0800 Subject: [PATCH 2/2] feat: remove deprecated async methods of Result --- src/Result.ts | 278 ----------- src/RustlikeResult.ts | 50 -- src/__tests__/RustlikeResult.test.ts | 663 --------------------------- 3 files changed, 991 deletions(-) diff --git a/src/Result.ts b/src/Result.ts index b7b7898..74a722b 100644 --- a/src/Result.ts +++ b/src/Result.ts @@ -53,30 +53,6 @@ export interface Result { */ isOkAnd(fn: (value: T) => boolean): boolean; - /** - * @deprecated Please use `.async().isOkAnd(fn)` instead. - * - * 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; - /** * Returns `true` if the result is `Err`. * @@ -123,35 +99,6 @@ export interface Result { */ isErrAnd(fn: (err: E) => boolean): boolean; - /** - * @deprecated Please use `.async().isErrAnd(fn)` instead. - * - * 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; - /** * Converts from `Result` to `Optional` and discarding the error, if any. * @@ -209,27 +156,6 @@ export interface Result { */ map(op: (value: T) => U): Result; - /** - * @deprecated Please use `.async().map(op)` instead. - * - * 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: - * - * ``` - * 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>; - /** * Returns the provided `fallback` (if `Err`), or applies a function to the contained value (if `Ok`). * @@ -253,32 +179,6 @@ export interface Result { */ mapOr(fallback: U, map: (value: T) => U): U; - /** - * @deprecated Please use `.async().mapOr(fallback, map)` instead. - * - * 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: - * - * ``` - * 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; - /** * Maps a `Result` to `U` by applying fallback function `fallback` to a contained `Err` value, * or function `map` to a contained `Ok` value. @@ -303,32 +203,6 @@ export interface Result { */ mapOrElse(fallback: (err: E) => U, map: (value: T) => U): U; - /** - * @deprecated Please use `.async().mapOrElse(fallback, map)` instead. - * - * 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: - * - * ``` - * 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; - /** * Maps a `Result` to `Result` by applying a function to a contained `Err` value, * leaving an `Ok` value untouched. @@ -348,27 +222,6 @@ export interface Result { */ mapErr(op: (err: E) => F): Result; - /** - * @deprecated Please use `.async().mapErr(op)` instead. - * - * 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: - * - * ``` - * 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>; - /** * Calls the provided closure with a reference to the contained value if `Ok`. * @@ -388,30 +241,6 @@ export interface Result { */ inspect(fn: (value: T) => void): this; - /** - * @deprecated Please use `.async().inspect(fn)` instead. - * - * Asynchronously calls the provided closure with a reference to the contained value if `Ok`. - * - * Examples: - * - * ``` - * import { resultifySync } from 'rustlike-result'; - * - * const num = await resultifySync()(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; - /** * Calls the provided closure with a reference to the contained value if `Err`. * @@ -429,28 +258,6 @@ export interface Result { */ inspectErr(fn: (err: E) => void): this; - /** - * @deprecated Please use `.async().inspectErr(fn)` instead. - * - * Asynchronously calls the provided closure with a reference to the contained value if `Err`. - * - * Examples: - * - * ``` - * import { resultifySync } from 'rustlike-result'; - * - * const num = await resultifySync()(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; - /** * Returns the contained `Ok` value. * @@ -577,25 +384,6 @@ export interface Result { */ unwrapOrElse(op: (err: E) => T): T; - /** - * @deprecated Please use `.async().unwrapOrElse(op)` instead. - * - * 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; - /** * Returns the contained `Ok` value, without checking that the value is not an `Err`. * @@ -700,37 +488,6 @@ export interface Result { */ andThen(op: (value: T) => Result): Result; - /** - * @deprecated Please use `.async().andThen(op)` instead. - * - * 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: - * - * ``` - * import { Err, Ok, resultifySync } from 'rustlike-result'; - * - * const parseJSON = (json: string) => - * Promise.resolve( - * resultifySync()(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>; - /** * Returns `res` if itself is `Err`, otherwise returns the `Ok` value of itself. * @@ -789,41 +546,6 @@ export interface Result { */ orElse(op: (err: E) => Result): Result; - /** - * @deprecated Please use `.async().orElse(op)` instead. - * - * 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: - * - * ``` - * 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`. * diff --git a/src/RustlikeResult.ts b/src/RustlikeResult.ts index 34cb900..84005c1 100644 --- a/src/RustlikeResult.ts +++ b/src/RustlikeResult.ts @@ -47,10 +47,6 @@ export class RustlikeResult implements Result { return this.isOk() && fn(this._value!); } - async isOkAndAsync(fn: (value: T) => boolean | Promise): Promise { - return this.isOk() && fn(this._value!); - } - isErr(): this is Result { return this._type === 'err'; } @@ -59,10 +55,6 @@ export class RustlikeResult implements Result { return this.isErr() && fn(this._error!); } - async isErrAndAsync(fn: (err: E) => boolean | Promise): Promise { - return this.isErr() && fn(this._error!); - } - ok(): Optional { return this.isOk() ? this._value : undefined; } @@ -75,34 +67,18 @@ export class RustlikeResult implements Result { return this.isOk() ? RustlikeResult.Ok(op(this._value!)) : RustlikeResult.Err(this._error!); } - async mapAsync(op: (value: T) => U | Promise): Promise> { - return this.isOk() ? RustlikeResult.Ok(await op(this._value!)) : RustlikeResult.Err(this._error!); - } - mapOr(fallback: U, map: (value: T) => U): U { return this.isOk() ? map(this._value!) : fallback; } - async mapOrAsync(fallback: U, map: (value: T) => U | Promise): Promise { - return this.isOk() ? map(this._value!) : fallback; - } - mapOrElse(fallback: (err: E) => U, map: (value: T) => U): U { return this.isOk() ? map(this._value!) : fallback(this._error!); } - async mapOrElseAsync(fallback: (err: E) => U | Promise, map: (value: T) => U | Promise): Promise { - return this.isOk() ? map(this._value!) : fallback(this._error!); - } - mapErr(op: (err: E) => F): Result { return this.isOk() ? RustlikeResult.Ok(this._value!) : RustlikeResult.Err(op(this._error!)); } - async mapErrAsync(op: (err: E) => F | Promise): Promise> { - return this.isOk() ? RustlikeResult.Ok(this._value!) : RustlikeResult.Err(await op(this._error!)); - } - inspect(fn: (value: T) => void): this { if (this.isOk()) { fn(this._value!); @@ -110,13 +86,6 @@ export class RustlikeResult implements Result { return this; } - async inspectAsync(fn: (value: T) => void | Promise): Promise { - if (this.isOk()) { - await fn(this._value!); - } - return this; - } - inspectErr(fn: (err: E) => void): this { if (this.isErr()) { fn(this._error!); @@ -124,13 +93,6 @@ export class RustlikeResult implements Result { return this; } - async inspectErrAsync(fn: (err: E) => void | Promise): Promise { - if (this.isErr()) { - await fn(this._error!); - } - return this; - } - private _unwrapFailed(msg: string, err: unknown): never { throw new Error(`${msg}: ${String(err)}`); } @@ -161,10 +123,6 @@ export class RustlikeResult implements Result { return this.isOk() ? this._value! : op(this._error!); } - async unwrapOrElseAsync(op: (err: E) => T | Promise): Promise { - return this.isOk() ? this._value! : op(this._error!); - } - // TODO: find a way to do the check in debug/development mode. unwrapUnchecked(): T { return this._value!; @@ -183,10 +141,6 @@ export class RustlikeResult implements Result { return this.isOk() ? op(this._value!) : RustlikeResult.Err(this._error!); } - async andThenAsync(op: (value: T) => Result | Promise>): Promise> { - return this.isOk() ? op(this._value!) : RustlikeResult.Err(this._error!); - } - or(res: Result): Result { return this.isOk() ? RustlikeResult.Ok(this._value!) : res; } @@ -195,10 +149,6 @@ export class RustlikeResult implements Result { return this.isOk() ? RustlikeResult.Ok(this._value!) : op(this._error!); } - async orElseAsync(op: (err: E) => Result | Promise>): Promise> { - return this.isOk() ? RustlikeResult.Ok(this._value!) : op(this._error!); - } - transpose(): Optional, E>> { if (this.isOk()) { return this._value === undefined || this._value === null ? undefined : RustlikeResult.Ok(this._value); diff --git a/src/__tests__/RustlikeResult.test.ts b/src/__tests__/RustlikeResult.test.ts index 2730be8..60a542a 100644 --- a/src/__tests__/RustlikeResult.test.ts +++ b/src/__tests__/RustlikeResult.test.ts @@ -13,10 +13,6 @@ function panicFn1(): never { throw new Error('error'); } -function panicFn2() { - return Promise.reject(new Error('error')); -} - describe(`Test static method \`${RustlikeResult.name}.${RustlikeResult.Ok.name}\``, () => { it('should create `Ok` result', () => { const result = RustlikeResult.Ok(1); @@ -103,64 +99,6 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot }); }); -describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.isOkAndAsync.name}\``, () => { - const fnFactory1 = () => jest.fn((num: number) => num > 1); - const fnFactory2 = () => jest.fn((num: number) => Promise.resolve(num > 1)); - - it('should return if itself is `Ok` and the value inside of it matches a predicate', async () => { - const _it = async (fn: (num: number) => boolean | Promise) => { - await expect(Ok(2).isOkAndAsync(fn)).resolves.toBe(true); - await expect(Ok(0).isOkAndAsync(fn)).resolves.toBe(false); - await expect(Err('Some error message').isOkAndAsync(fn)).resolves.toBe(false); - }; - - await _it(fnFactory1()); - await _it(fnFactory2()); - }); - - it('should call fn only once if itself is `Ok`', async () => { - const _it = async (fn: (num: number) => boolean | Promise) => { - expect(fn).toHaveBeenCalledTimes(0); - await Ok(2).isOkAndAsync(fn); - expect(fn).toHaveBeenCalledTimes(1); - }; - - await _it(fnFactory1()); - await _it(fnFactory2()); - }); - - it('should not call fn if itself is `Err`', async () => { - const _it = async (fn: (num: number) => boolean | Promise) => { - expect(fn).toHaveBeenCalledTimes(0); - await Err('Some error message').isOkAndAsync(fn); - expect(fn).toHaveBeenCalledTimes(0); - }; - - await _it(fnFactory1()); - await _it(fnFactory2()); - }); - - it('should panic if fn panic', async () => { - 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}\``, () => { it('should return if itself is `Err`', () => { expect(Ok(1).isErr()).toBe(false); @@ -238,69 +176,6 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot }); }); -describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.isErrAndAsync.name}\``, () => { - enum ErrorKind { - NOT_FOUND, - PERMISSION_DENIED, - } - - const fnFactory1 = () => jest.fn((err: ErrorKind) => err === ErrorKind.NOT_FOUND); - const fnFactory2 = () => jest.fn((err: ErrorKind) => Promise.resolve(err === ErrorKind.NOT_FOUND)); - - it('should return if itself is `Err` and the value inside of it matches a predicate', async () => { - const _it = async (fn: (err: ErrorKind) => boolean | Promise) => { - await expect(Err(ErrorKind.NOT_FOUND).isErrAndAsync(fn)).resolves.toBe(true); - await expect(Err(ErrorKind.PERMISSION_DENIED).isErrAndAsync(fn)).resolves.toBe(false); - await expect(Ok(123).isErrAndAsync(fn)).resolves.toBe(false); - }; - - await _it(fnFactory1()); - await _it(fnFactory2()); - }); - - it('should call fn only once if itself is `Err`', async () => { - const _it = async (fn: (err: ErrorKind) => boolean | Promise) => { - expect(fn).toHaveBeenCalledTimes(0); - await Err(ErrorKind.NOT_FOUND).isErrAndAsync(fn); - expect(fn).toHaveBeenCalledTimes(1); - }; - - await _it(fnFactory1()); - await _it(fnFactory2()); - }); - - it('should not call fn if itself is `Ok`', async () => { - const _it = async (fn: (err: ErrorKind) => boolean | Promise) => { - expect(fn).toHaveBeenCalledTimes(0); - await Ok(123).isErrAndAsync(fn); - expect(fn).toHaveBeenCalledTimes(0); - }; - - await _it(fnFactory1()); - await _it(fnFactory2()); - }); - - it('should panic if fn panic', async () => { - 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}\``, () => { it('should convert itself to an optional value', () => { expect(Ok(1).ok()).toBe(1); @@ -376,57 +251,6 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot }); }); -describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.mapAsync.name}\``, () => { - const mapFactory1 = () => jest.fn((num: number) => String(num)); - const mapFactory2 = () => jest.fn((num: number) => Promise.resolve(String(num))); - - it('should map itself to another result', async () => { - const _it = async (map: (num: number) => string | Promise) => { - await expect(Ok(1).mapAsync(map)).resolves.toStrictEqual(Ok('1')); - await expect(Err('Some error message').mapAsync(map)).resolves.toStrictEqual(Err('Some error message')); - }; - - await _it(mapFactory1()); - await _it(mapFactory2()); - }); - - it('should call map fn only once if itself is `Ok`', async () => { - const _it = async (map: (num: number) => string | Promise) => { - expect(map).toHaveBeenCalledTimes(0); - await Ok(1).mapAsync(map); - expect(map).toHaveBeenCalledTimes(1); - }; - - await _it(mapFactory1()); - await _it(mapFactory2()); - }); - - it('should not call map fn if itself is `Err`', async () => { - const _it = async (map: (num: number) => string | Promise) => { - expect(map).toHaveBeenCalledTimes(0); - await Err('Some error message').mapAsync(map); - expect(map).toHaveBeenCalledTimes(0); - }; - - await _it(mapFactory1()); - await _it(mapFactory2()); - }); - - it('should panic if fn panic', async () => { - 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}\``, () => { const mapFactory = () => jest.fn((num: number) => num * 2); @@ -467,60 +291,6 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot }); }); -describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.mapOrAsync.name}\``, () => { - const mapFactory1 = () => jest.fn((num: number) => num * 2); - const mapFactory2 = () => jest.fn((num: number) => Promise.resolve(num * 2)); - - it('should map itself to another result', async () => { - const _it = async (map: (num: number) => number | Promise) => { - await expect(Ok(1).mapOrAsync(-1, map)).resolves.toBe(2); - await expect(Err('Some error message').mapOrAsync(-1, map)).resolves.toBe(-1); - }; - - await _it(mapFactory1()); - await _it(mapFactory2()); - }); - - it('should call map fn only once if itself is `Ok`', async () => { - const _it = async (map: (num: number) => number | Promise) => { - expect(map).toHaveBeenCalledTimes(0); - await Ok(1).mapOrAsync(-1, map); - expect(map).toHaveBeenCalledTimes(1); - }; - - await _it(mapFactory1()); - await _it(mapFactory2()); - }); - - it('should not call map fn if itself is `Err`', async () => { - const _it = async (map: (num: number) => number | Promise) => { - expect(map).toHaveBeenCalledTimes(0); - await Err('Some error message').mapOrAsync(-1, map); - expect(map).toHaveBeenCalledTimes(0); - }; - - await _it(mapFactory1()); - await _it(mapFactory2()); - }); - - it('should panic if fn panic', async () => { - 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}\``, () => { const mapFactory = () => jest.fn(jest.fn((num: number) => String(num))); const fallbackFactory = () => jest.fn(jest.fn((str: string) => str)); @@ -584,89 +354,6 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot }); }); -describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.mapOrElseAsync.name}\``, () => { - const mapFactory1 = () => jest.fn(jest.fn((num: number) => String(num))); - const mapFactory2 = () => jest.fn(jest.fn((num: number) => Promise.resolve(String(num)))); - const fallbackFactory1 = () => jest.fn(jest.fn((str: string) => str)); - const fallbackFactory2 = () => jest.fn(jest.fn((str: string) => Promise.resolve(str))); - - it('should map itself to another value', async () => { - const _it = async ( - map: (num: number) => string | Promise, - fallback: (str: string) => string | Promise, - ) => { - await expect(Ok(1).mapOrElseAsync(fallback, map)).resolves.toBe('1'); - await expect(Err('Some error message').mapOrElseAsync(fallback, map)).resolves.toBe('Some error message'); - }; - - await _it(mapFactory1(), fallbackFactory1()); - await _it(mapFactory2(), fallbackFactory2()); - }); - - it('should call map fn only once if itself is `Ok`', async () => { - const _it = async ( - map: (num: number) => string | Promise, - fallback: (str: string) => string | Promise, - ) => { - expect(map).toHaveBeenCalledTimes(0); - expect(fallback).toHaveBeenCalledTimes(0); - await Ok(1).mapOrElseAsync(fallback, map); - expect(map).toHaveBeenCalledTimes(1); - expect(fallback).toHaveBeenCalledTimes(0); - }; - - await _it(mapFactory1(), fallbackFactory1()); - await _it(mapFactory2(), fallbackFactory2()); - }); - - it('should call fallback fn only once if itself is `Err`', async () => { - const _it = async ( - map: (num: number) => string | Promise, - fallback: (str: string) => string | Promise, - ) => { - expect(map).toHaveBeenCalledTimes(0); - expect(fallback).toHaveBeenCalledTimes(0); - await Err('Some error message').mapOrElseAsync(fallback, map); - expect(map).toHaveBeenCalledTimes(0); - expect(fallback).toHaveBeenCalledTimes(1); - }; - - await _it(mapFactory1(), fallbackFactory1()); - await _it(mapFactory2(), fallbackFactory2()); - }); - - it('should panic if fn panic', async () => { - await expect(() => Ok(1).mapOrElseAsync(panicFn1, panicFn1)).rejects.toThrow(Error('error')); - await expect(() => Err('err').mapOrElseAsync(panicFn1, panicFn1)).rejects.toThrow(Error('error')); - 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}\``, () => { const mapFactory = () => jest.fn((num: number) => `error code: ${num}`); @@ -704,57 +391,6 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot }); }); -describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.mapErrAsync.name}\``, () => { - const mapFactory1 = () => jest.fn((num: number) => `error code: ${num}`); - const mapFactory2 = () => jest.fn((num: number) => Promise.resolve(`error code: ${num}`)); - - it('should map itself to another result', async () => { - const _it = async (map: (num: number) => string | Promise) => { - await expect(Ok(1).mapErrAsync(map)).resolves.toStrictEqual(Ok(1)); - await expect(Err(2).mapErrAsync(map)).resolves.toStrictEqual(Err('error code: 2')); - }; - - await _it(mapFactory1()); - await _it(mapFactory2()); - }); - - it('should call map fn only once if itself is `Err`', async () => { - const _it = async (map: (num: number) => string | Promise) => { - expect(map).toHaveBeenCalledTimes(0); - await Err(2).mapErrAsync(map); - expect(map).toHaveBeenCalledTimes(1); - }; - - await _it(mapFactory1()); - await _it(mapFactory2()); - }); - - it('should not call map fn if itself is `Ok`', async () => { - const _it = async (map: (num: number) => string | Promise) => { - expect(map).toHaveBeenCalledTimes(0); - await Ok(1).mapErrAsync(map); - expect(map).toHaveBeenCalledTimes(0); - }; - - await _it(mapFactory1()); - await _it(mapFactory2()); - }); - - it('should panic if fn panic', async () => { - 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}\``, () => { it('should return itself', () => { const fn = () => { @@ -801,71 +437,6 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot }); }); -describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.inspectAsync.name}\``, () => { - it('should return itself', async () => { - const fn1 = () => { - // do something - }; - const fn2 = () => { - // do something - return Promise.resolve(); - }; - - const okResult = Ok(1); - const errResult = Err(0); - - await expect(okResult.inspectAsync(fn1)).resolves.toBe(okResult); - await expect(errResult.inspectAsync(fn1)).resolves.toBe(errResult); - await expect(okResult.inspectAsync(fn2)).resolves.toBe(okResult); - await expect(errResult.inspectAsync(fn2)).resolves.toBe(errResult); - }); - - it('should inspect ok value', async () => { - const fn1 = jest.fn((value: number) => expect(value).toBe(1)); - const fn2 = jest.fn((value: number) => { - expect(value).toBe(1); - return Promise.resolve(); - }); - expect(fn1).toHaveBeenCalledTimes(0); - expect(fn2).toHaveBeenCalledTimes(0); - await Ok(1).inspectAsync(fn1); - await Ok(1).inspectAsync(fn2); - expect(fn1).toHaveBeenCalledTimes(1); - expect(fn2).toHaveBeenCalledTimes(1); - }); - - it('should not inspect err value', async () => { - const fn = jest.fn(() => { - // do something - }); - expect(fn).toHaveBeenCalledTimes(0); - await Err(1).inspectAsync(fn); - expect(fn).toHaveBeenCalledTimes(0); - }); - - it('should panic if fn panic', async () => { - 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 resultifySync()(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}\``, () => { it('should return itself', () => { const fn = () => { @@ -911,68 +482,6 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot }); }); -describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.inspectErrAsync.name}\``, () => { - it('should return itself', async () => { - const fn1 = () => { - // do something - }; - const fn2 = () => { - // do something - return Promise.resolve(); - }; - - const okResult = Ok(1); - const errResult = Err(0); - - await expect(okResult.inspectErrAsync(fn1)).resolves.toBe(okResult); - await expect(errResult.inspectErrAsync(fn1)).resolves.toBe(errResult); - await expect(okResult.inspectErrAsync(fn2)).resolves.toBe(okResult); - await expect(errResult.inspectErrAsync(fn2)).resolves.toBe(errResult); - }); - - it('should not inspect ok value', async () => { - const fn = jest.fn(() => { - // do something - }); - expect(fn).toHaveBeenCalledTimes(0); - await Ok(1).inspectErrAsync(fn); - expect(fn).toHaveBeenCalledTimes(0); - }); - - it('should inspect err value', async () => { - const fn1 = jest.fn((value: number) => expect(value).toBe(1)); - const fn2 = jest.fn((value: number) => { - expect(value).toBe(1); - return Promise.resolve(); - }); - expect(fn1).toHaveBeenCalledTimes(0); - expect(fn2).toHaveBeenCalledTimes(0); - await Err(1).inspectErrAsync(fn1); - await Err(1).inspectErrAsync(fn2); - expect(fn1).toHaveBeenCalledTimes(1); - expect(fn2).toHaveBeenCalledTimes(1); - }); - - it('should panic if fn panic', async () => { - 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 resultifySync()(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}\``, () => { it('should unwrap itself to get the contained `Ok` value', () => { expect(Ok(1).expect('Operation type should be correct')).toBe(1); @@ -1108,66 +617,6 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot }); }); -describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.unwrapOrElseAsync.name}\``, () => { - const fnFactory1 = () => - jest.fn((msg: string) => { - if (msg === 'I got this.') return 50; - throw new Error('BadBad'); - }); - const fnFactory2 = () => - jest.fn((msg: string) => { - if (msg === 'I got this.') return Promise.resolve(50); - throw new Error('BadBad'); - }); - - it('should unwrap itself to get the contained `Ok` value or computes it from a closure', async () => { - const _it = async (op: (msg: string) => number | Promise) => { - await expect(Ok(100).unwrapOrElseAsync(op)).resolves.toBe(100); - await expect(Err('I got this.').unwrapOrElseAsync(op)).resolves.toBe(50); - }; - - await _it(fnFactory1()); - await _it(fnFactory2()); - }); - - it('should call op only once if itself if `Err`', async () => { - const _it = async (op: (msg: string) => number | Promise) => { - expect(op).toHaveBeenCalledTimes(0); - await Err('I got this.').unwrapOrElseAsync(op); - expect(op).toHaveBeenCalledTimes(1); - }; - - await _it(fnFactory1()); - await _it(fnFactory2()); - }); - - it('should not call op if itself if `Ok`', async () => { - const _it = async (op: (msg: string) => number | Promise) => { - expect(op).toHaveBeenCalledTimes(0); - await Ok(100).unwrapOrElseAsync(op); - expect(op).toHaveBeenCalledTimes(0); - }; - - await _it(fnFactory1()); - await _it(fnFactory2()); - }); - - it('should panic if fn panic', async () => { - 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); @@ -1296,59 +745,6 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot }); }); -describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.andThenAsync.name}\``, () => { - it('should return `res`', async () => { - await expect(op1().andThenAsync((num) => Ok(num + 1))).resolves.toStrictEqual(Ok(667)); - await expect(op1().andThenAsync((num) => Promise.resolve(Ok(num + 1)))).resolves.toStrictEqual(Ok(667)); - await expect(op1().andThenAsync(() => Err('bad'))).resolves.toStrictEqual(Err('bad')); - await expect(op1().andThenAsync(() => Promise.resolve(Err('bad')))).resolves.toStrictEqual(Err('bad')); - }); - - it('should return the `Err` result', async () => { - await expect(op2().andThenAsync((num) => Ok(num + 1))).resolves.toStrictEqual(Err('sadface')); - await expect(op2().andThenAsync((num) => Promise.resolve(Ok(num + 1)))).resolves.toStrictEqual(Err('sadface')); - await expect(op2().andThenAsync(() => Err('bad'))).resolves.toStrictEqual(Err('sadface')); - await expect(op2().andThenAsync(() => Promise.resolve(Err('bad')))).resolves.toStrictEqual(Err('sadface')); - }); - - it('should call op fn only once if itself is `Ok`', async () => { - const fn = jest.fn((num: number) => Promise.resolve(Ok(num + 1))); - expect(fn).toHaveBeenCalledTimes(0); - await op1().andThenAsync(fn); - expect(fn).toHaveBeenCalledTimes(1); - }); - - it('should not call op fn if itself is `Err`', async () => { - const fn = jest.fn((num: number) => Promise.resolve(Ok(num + 1))); - expect(fn).toHaveBeenCalledTimes(0); - await op2().andThenAsync(fn); - expect(fn).toHaveBeenCalledTimes(0); - }); - - it('should panic if fn panic', async () => { - 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(resultifySync()(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}\``, () => { it('should return the `Ok` result', () => { expect(op1().or(Ok(667))).toStrictEqual(Ok(666)); @@ -1430,65 +826,6 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot }); }); -describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.orElseAsync.name}\``, () => { - it('should return the `Ok` result', async () => { - await expect(op1().orElseAsync(() => Ok(667))).resolves.toStrictEqual(Ok(666)); - await expect(op1().orElseAsync(() => Promise.resolve(Ok(667)))).resolves.toStrictEqual(Ok(666)); - await expect(op1().orElseAsync((err) => Err(err))).resolves.toStrictEqual(Ok(666)); - await expect(op1().orElseAsync((err) => Promise.resolve(Err(err)))).resolves.toStrictEqual(Ok(666)); - }); - - it('should return `res`', async () => { - await expect(op2().orElseAsync(() => Ok(667))).resolves.toStrictEqual(Ok(667)); - await expect(op2().orElseAsync(() => Promise.resolve(Ok(667)))).resolves.toStrictEqual(Ok(667)); - await expect(op2().orElseAsync((err) => Err(err))).resolves.toStrictEqual(Err('sadface')); - await expect(op2().orElseAsync((err) => Promise.resolve(Err(err)))).resolves.toStrictEqual(Err('sadface')); - }); - - it('should call op fn only once if itself is `Err`', async () => { - const fn = jest.fn((err: string) => Promise.resolve(Err(err))); - expect(fn).toHaveBeenCalledTimes(0); - await op2().orElseAsync(fn); - expect(fn).toHaveBeenCalledTimes(1); - }); - - it('should not call op fn if itself is `Ok`', async () => { - const fn = jest.fn((err: string) => Promise.resolve(Err(err))); - expect(fn).toHaveBeenCalledTimes(0); - await op1().orElseAsync(fn); - expect(fn).toHaveBeenCalledTimes(0); - }); - - it('should panic if fn panic', async () => { - 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}\``, () => { it('should transpose itself to an optional of a `Result`', () => { expect(Ok(1).transpose()).toStrictEqual(Ok(1));