1 | # Errly
|
2 |
|
3 | [![Install size](https://packagephobia.com/badge?p=errly@latest)](https://packagephobia.com/result?p=errly@latest)
|
4 |
|
5 | Error handling in JavaScript is done using [`try...catch`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch) blocks, which can get messy and verbose very quickly. **Errly** makes the error handling experience similar to that of [Golang](https://go.dev/).
|
6 |
|
7 | ## Features
|
8 |
|
9 | - Zero dependencies. Small bundle size.
|
10 | - Written in TypeScript.
|
11 | - Seamless support for synchronous & asynchronous functions.
|
12 | - Modern [ESModules](https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/) support.
|
13 |
|
14 | ## Usage
|
15 |
|
16 | Consider the following function:
|
17 |
|
18 | ```TypeScript
|
19 | const throwIfEven = (num: number) => {
|
20 | if (!(num % 2)) throw new Error("It's even!");
|
21 | return num;
|
22 | };
|
23 | ```
|
24 |
|
25 | Here's how you would normally handle errors from calls to `throwIfEven`:
|
26 |
|
27 | ```TypeScript
|
28 | function main() {
|
29 | try {
|
30 | // Happy path:
|
31 | const data = throwIfEven(6);
|
32 | console.log(data);
|
33 | // ...
|
34 | } catch (error) {
|
35 | // Sad path:
|
36 | console.log((error as Error).message);
|
37 | return;
|
38 | }
|
39 | }
|
40 | ```
|
41 |
|
42 | One issue here is that `data` is now scoped to the `try` block, and cannot be used outside of it. Same goes for `error` being scoped to the `catch` block. Here's how the same piece of logic looks when using Errly to handle the error:
|
43 |
|
44 | ```TypeScript
|
45 | import { e } from 'errly';
|
46 |
|
47 | function main() {
|
48 | // Scoped to the function.
|
49 | const [data, err] = e(() => throwIfEven(6));
|
50 | // Write error handling logic first.
|
51 | if (err !== null) {
|
52 | // Sad path:
|
53 | console.log(err.message);
|
54 | return;
|
55 | }
|
56 | // Happy path:
|
57 |
|
58 | // TypeScript will understand that "data" is
|
59 | // definitely a number and can't be null because
|
60 | // the error path was handled above.
|
61 | console.log(data);
|
62 | // ...
|
63 | }
|
64 | ```
|
65 |
|
66 | ## With async code
|
67 |
|
68 | Usage with async functions is the same as above with only the addition of the `await` keyword.
|
69 |
|
70 | ```TypeScript
|
71 | const doStuff = async () => {
|
72 | // Wait for two seconds
|
73 | await new Promise((r) => setTimeout(r, 2e3));
|
74 | throw new Error('foo');
|
75 | };
|
76 |
|
77 | const [_, err] = await e(() => doStuff());
|
78 | if (err !== null) {
|
79 | // Handle error
|
80 | }
|
81 | ```
|
82 |
|
83 | ## Creating new functions
|
84 |
|
85 | If using `e()` all the time doesn't seem like your style, you can instead convert regular functions into Errly functions by using `func()`.
|
86 |
|
87 | ```TypeScript
|
88 | import { func } from 'errly';
|
89 |
|
90 | const add = func((n1: number, n2: number) => {
|
91 | const sum = n1 + n2;
|
92 | if (sum > 100) {
|
93 | throw new Error('Sum is massive!');
|
94 | }
|
95 |
|
96 | return sum;
|
97 | });
|
98 |
|
99 | const [sum, err] = add(1337, 420);
|
100 | if (err !== null) {
|
101 | // Handle error
|
102 | }
|
103 | ```
|