diff --git a/README.md b/README.md index 0a6db20..cab1a27 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,131 @@ # rustlike-result Rust-like Result for Javascript + +## Install + +```sh +npm install rustlike-result +yarn add rustlike-result +pnpm install rustlike-result +``` + +## Usage + +This package implement a Rust-like `Result`, nearly all methods are similar to the [Result]. + +```ts +// TODO +``` + +[result]: https://doc.rust-lang.org/std/result/enum.Result.html + +### About Rust `Option` + +This package doesn't implement Rust-like `Option`. Handling `undefined`/`null` is not as hard as it was a few years ago, because right now we already have [proposal-optional-chaining] and [proposal-nullish-coalescing] to help handle it. + +[proposal-optional-chaining]: https://github.com/tc39/proposal-optional-chaining +[proposal-nullish-coalescing]: https://github.com/tc39/proposal-nullish-coalescing + +## The Implementations for `Result` + +The Rust-like `Result` implements the following methods: + +| Rust-like `Result` method | Rust `Result` method | +| :------------------------ | :--------------------- | +| isOk | [is_ok] | +| isOkAnd | [is_ok_and] | +| isErr | [is_err] | +| isErrAnd | [is_err_and] | +| ok | [ok] | +| err | [err] | +| map | [map] | +| mapOr | [map_or] | +| mapOrElse | [map_or_else] | +| mapErr | [map_err] | +| expect | [expect] | +| unwrap | [unwrap] | +| expectErr | [expect_err] | +| unwrapErr | [unwrap_err] | +| unwrapOr | [unwrap_or] | +| unwrapOrElse | [unwrap_or_else] | +| unwrapUnchecked | [unwrap_unchecked] | +| unwrapErrUnchecked | [unwrap_err_unchecked] | +| and | [and] | +| andThen | [and_then] | +| or | [or] | +| orElse | [or_else] | +| transpose | [transpose] | + +Unlike Rust, JavaScript doesn't have the 'Ownership' feature, so some API like `as_ref` is not necessary. These implementations are not implemented: + +```md + +as_ref +as_mut +inspect (unstable) +inspect_err (unstable) +as_deref +as_deref_mut +iter +iter_mut +unwrap_or_default +into_ok (unstable) +into_err (unstable) +copied +cloned +flatten (unstable) + + +clone +clone_from +fmt +hash +``` + +[is_ok]: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_ok +[is_ok_and]: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_ok_and +[is_err]: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_err +[is_err_and]: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_err_and +[ok]: https://doc.rust-lang.org/std/result/enum.Result.html#method.ok +[err]: https://doc.rust-lang.org/std/result/enum.Result.html#method.err +[map]: https://doc.rust-lang.org/std/result/enum.Result.html#method.map +[map_or]: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or +[map_or_else]: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or_else +[map_err]: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_err +[expect]: https://doc.rust-lang.org/std/result/enum.Result.html#method.expect +[unwrap]: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap +[expect_err]: https://doc.rust-lang.org/std/result/enum.Result.html#method.expect_err +[unwrap_err]: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_err +[unwrap_or]: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or +[unwrap_or_else]: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or_else +[unwrap_unchecked]: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_unchecked +[unwrap_err_unchecked]: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_err_unchecked +[and]: https://doc.rust-lang.org/std/result/enum.Result.html#method.and +[and_then]: https://doc.rust-lang.org/std/result/enum.Result.html#method.and_then +[or]: https://doc.rust-lang.org/std/result/enum.Result.html#method.or +[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 + +## More Methods +### equal + +You can not just use `===` or `==` to compare `Result`, so `Result` itself provides an method call `equal` for that. + +```javascript +expect(Ok(1).equal(Ok(1))).toBe(true); +expect(Ok('hello').equal(Ok('hello'))).toBe(true); + +expect(Ok({ foo: 1 }).equal(Ok({ foo: 1 }))).toBe(false); +expect(Ok([1]).equal(Ok([1]))).toBe(false); +``` + +There is no built-in deep-equal support in this package for array, object and some built-in classes like `Date`. If you do want to deeply compare those complex structures, you will have to write your own helper functions. + +There is a [proposal] (stage 2) that introduces `Record` and `Tuple` which are compared by content rather than identity. In the future, we can use `Record` and `Tuple` in `Result` so that we don't need to implement custom equality comparison function. + +[proposal]: https://github.com/tc39/proposal-record-tuple + +## License + +MIT diff --git a/src/__tests__/result.test.ts b/src/__tests__/result.test.ts index edfd6b0..df658cf 100644 --- a/src/__tests__/result.test.ts +++ b/src/__tests__/result.test.ts @@ -418,5 +418,14 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot expect(Err(Ok(1)).equal(Err(Err('Some error message')))).toBe(false); expect(Err(Err('Some error message')).equal(Err(Ok(1)))).toBe(false); expect(Ok(1).equal(Err('Some error message'))).toBe(false); + + expect(Ok([1]).equal(Ok([1]))).toBe(false); + expect(Ok({ foo: 1 }).equal(Ok({ foo: 1 }))).toBe(false); + expect(Ok(Ok([1])).equal(Ok(Ok([1])))).toBe(false); + expect(Ok(Ok({ foo: 1 })).equal(Ok(Ok({ foo: 1 })))).toBe(false); + expect(Err({ message: 'Some error message' }).equal(Err({ message: 'Some error message' }))).toBe(false); + expect(Err(Err({ message: 'Some error message' })).equal(Err(Err({ message: 'Some error message' })))).toBe( + false, + ); }); }); diff --git a/src/types.ts b/src/types.ts index 5c978d5..fbeeab3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -3,7 +3,7 @@ * - https://github.com/tc39/proposal-optional-chaining * - https://github.com/tc39/proposal-nullish-coalescing * - * We don't need Rust-like Option anymore in most cases. + * We don't need Rust-like Option anymore in most cases unless we want functional programming. * * This type doesn't use the name `Option`, * by giving it a different name we can easily know that this is not Rust-like Option.