|
1 | | - |
2 | 1 |  |
3 | 2 |  |
4 | 3 |  |
5 | 4 |
|
6 | 5 | # 📛 TryResult |
7 | 6 |
|
8 | | -A typescript library to get rid of try catches, and replace them with result types, inspired by Rust and Go error handling. |
| 7 | +A tiny typescript library to get rid of try catches, and replace them with result types, inspired by Rust and Go error handling. |
9 | 8 |
|
10 | | - |
| 9 | + |
11 | 10 |
|
12 | | -Providing simple, easier, and more elegeant error handling, TryResult gives you functions that act as wrappers and catch errors in your own functions. |
13 | | - |
14 | | -It also currently provides functions to assert if a result has an error in it, and to use a default value in case of errors. |
15 | | - |
16 | | -<br> |
| 11 | +Under 400 bytes and with no dependencies, TryResult only provides you with more elegant error handling and gives you functions that act as wrappers and catch errors in your own functions. |
17 | 12 |
|
18 | 13 | ## Install |
19 | 14 |
|
20 | | -As with any npm package: |
| 15 | +As with any package, install using your favorite package manager: |
21 | 16 |
|
22 | 17 | ```sh |
23 | | -npm i tryresult |
| 18 | +pnpm i tryresult |
24 | 19 | ``` |
25 | 20 |
|
26 | | -Or use Yarn: |
| 21 | +## Usage |
27 | 22 |
|
28 | | -```sh |
29 | | -yarn add tryresult |
30 | | -``` |
| 23 | +The base functionality of TryResult revolves around the `Result` type, which can either be an `Ok` or an `Err`. You can create these results using the `ok` and `err` functions. |
31 | 24 |
|
32 | | -<br> |
| 25 | +```ts |
| 26 | +import { ok, err, Result, isOk, isErr } from "tryresult"; |
33 | 27 |
|
34 | | -## Usage |
| 28 | +// You can create a Result with a value or an error |
35 | 29 |
|
36 | | -Import from the package: |
| 30 | +const success = ok("Success!"); // Result<string, Error> |
| 31 | +const failure = err(new Error("Something went wrong")); // Result<string, Error> |
37 | 32 |
|
38 | | -```typescript |
39 | | -import { tryAsync, isError } from "tryresult"; |
| 33 | +// You can do typesafe checks of a Result |
| 34 | + |
| 35 | +if (isOk(success)) { |
| 36 | + console.log(success.value); // "Success!" |
| 37 | +} |
| 38 | +if (isErr(failure)) { |
| 39 | + console.error(failure.error); // Error: Something went wrong |
| 40 | +} |
40 | 41 | ``` |
41 | 42 |
|
42 | | -Wrap your async function with `tryAsync`: |
| 43 | +### Wrapping Functions |
43 | 44 |
|
44 | | -```typescript |
45 | | -let users = await tryAsync( |
46 | | - // get a list of users from the database |
47 | | - db.user.findMany(), |
48 | | -); |
49 | | -``` |
| 45 | +To do away with try-catch blocks around functions you can't control, you can use wrapping functions to automatically get a `Result` type. |
| 46 | + |
| 47 | +```ts |
| 48 | +import { tryFn, isErr } from "tryresult"; |
| 49 | + |
| 50 | +// Capture throws from async or sync functions |
50 | 51 |
|
51 | | -This will make the `users` variable be of type `T | Error`, meaning it can be either a value or an error (a union of types). |
| 52 | +const result = tryFn(() => { |
| 53 | + return JSON.parse('{"message": "Hello!"}'); |
| 54 | +}); |
52 | 55 |
|
53 | | -Then check for error in the variable with `isError`, and then handle the error: |
| 56 | +const asyncResult = await tryFn(async () => { |
| 57 | + const response = await fetch('https://api.example.com/data'); |
| 58 | + return response.json(); |
| 59 | +}); |
54 | 60 |
|
55 | | -```typescript |
56 | | -if (isError(users)) { |
57 | | - return "Could not get users from db"; |
| 61 | +// As shown above, the `Result` can be checked |
| 62 | + |
| 63 | +if (isErr(result)) { |
| 64 | + console.error("An error occurred:", result.error); // Guaranteed to be an Error object |
| 65 | +} else { |
| 66 | + console.log(result.value.message); // "Hello!" |
58 | 67 | } |
| 68 | + |
59 | 69 | ``` |
60 | 70 |
|
61 | | -This is a type guard and all code after the `isError` will consider result's type to be `T`. |
| 71 | +### Working with Results |
62 | 72 |
|
63 | | -**[v1.2.x onwards]** |
| 73 | +Several utilities are provided to make working with `Result` types easier, and abstract common functionality. |
64 | 74 |
|
65 | | -Let's say you're fetching something like a user's role from the db: |
| 75 | +```ts |
| 76 | +import { match, okOr, okOrThrow, mapOk, mapErr } from "tryresult"; |
66 | 77 |
|
67 | | -```typescript |
68 | | -const result = await tryAsync(db.user.find(id).role); |
69 | | -``` |
| 78 | +// Match on the Result type to run different logic or return different values based on whether it's Ok or Err |
70 | 79 |
|
71 | | -If you want to get the value and set a default value in case of error, you can use `okOr` on the result: |
| 80 | +const greeting = match(result, { |
| 81 | + ok: (value) => `Success: ${value.message}`, |
| 82 | + err: (error) => `Error: ${error.message}`, |
| 83 | +}); |
72 | 84 |
|
73 | | -```typescript |
74 | | -const role = okOr(result, "guestUser"); |
75 | | -``` |
| 85 | +// Ignore errors and use a default value for when you don't care about the error |
| 86 | + |
| 87 | +const data = okOr(result, { message: "Default message" }); |
76 | 88 |
|
77 | | -Now `role` is gonna be either the value from the db, or if there was an error, `"guestUser"`. |
| 89 | +// If need be, you can throw an error if the Result is Err |
78 | 90 |
|
79 | | -<br> |
| 91 | +try { |
| 92 | + const value = okOrThrow(result); |
| 93 | + console.log(value.message); |
| 94 | +} catch (error) { |
| 95 | + console.error("Error was thrown:", error); |
| 96 | +} |
| 97 | + |
| 98 | +// Returned values can be transformed/mapped quickly |
| 99 | + |
| 100 | +const uppercased = mapOk(result, (value) => value.toUpperCase()); |
| 101 | + |
| 102 | +// The same is true for errors, and several mapping functions are provided |
| 103 | + |
| 104 | +const betterError = mapErr(result, (error) => `Custom error: ${error.message}`); |
| 105 | +``` |
80 | 106 |
|
81 | | -To see the library used in a project, checkout out [ahmeddots/oswald](https://github.com/ahmeddots/oswald). |
| 107 | +More information can be found as part of function documentation, which can be viewed in your editor or in the source code. |
0 commit comments