You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+45-38Lines changed: 45 additions & 38 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,28 +1,28 @@
1
1
# maybe-result - Safe function return handling in Typescript and Javascript
2
2
3
-
Deciding when a function should return an undefined, throw an `Error`, or returning some other sort of
4
-
"something isn't right" is tough. That's because we don't always know how users _calling_ our function
5
-
will work, and because we want to be clear, clean, and safe.
3
+
Deciding when a function should return `undefined`, throw an `Error`, or return some other indicator that
4
+
"something isn't right" is tough. We don't always know how users _calling_ our function
5
+
will use it, and we want to be clear, clean, and safe.
6
6
7
7
This library provides two approaches for wrapping function results:
8
8
9
9
-[Maybe](#maybe) for when something may or may not exist
10
-
-[Result](#result) for when you want to return an error, but let the caller decide how to handle it
10
+
-[Result](#result) for when you might have an error, but want to let the caller decide how to handle it
11
11
12
12
## Maybe
13
13
14
-
In many languages, we have concepts of exceptions but also a `null`value of some sort.
14
+
In many languages, we have concepts of exceptions and `null`values.
15
15
(JavaScript has both `null` and `undefined`. Ugh!)
16
16
17
17
Often a function will need to indicate when a value _maybe_ exists, or it does not.
18
18
In JavaScript, the "does not" is usually returned as `undefined` or `null`, but sometimes
19
-
a function will *throw* an `Error` type instead. Thus, the developer needs to figure out
19
+
a function will _throw_ an `Error` type instead. Thus, the developer needs to figure out
20
20
how that particular function behaves and adapt to that if they want to handle
21
21
the missing value.
22
22
23
23
Finally, throwing Errors in TypeScript can be expensive, as a stack trace must be
24
24
generated and cross-referenced to the `.js.map` files. These stack traces to your
25
-
TypeScript source are immensely useful to trace actual errors, but are wasted
25
+
TypeScript source are immensely useful for tracing actual errors, but they are wasted
26
26
processing when ignored.
27
27
28
28
The `Maybe` type makes this cleaner. Elm was an early language that defined this.
@@ -44,9 +44,9 @@ and immutable alternative to `undefined` and `null`.
44
44
Here's a nice introduction to the concept:
45
45
[Implementing a Maybe Pattern using a TypeScript Type Guard](https://medium.com/@sitapati/implementing-a-maybe-pattern-using-a-typescript-type-guard-81b55efc0af0)
46
46
47
-
### Example by story
47
+
### Example by Story
48
48
49
-
You might have defined a data repository class (access to a data store) like this:
49
+
You might define a data repository class (access to a data store) like this:
50
50
51
51
```ts
52
52
classWidgetRepository {
@@ -56,21 +56,22 @@ class WidgetRepository {
56
56
}
57
57
```
58
58
59
-
If the Widget isn't found, you throw a `NotFoundError`. All is well, until you start _expecting_
59
+
If the Widget isn't found, you throw a `NotFoundError`. All is well until you start _expecting_
60
60
a Widget not to be found. That becomes valid flow, so you find yourself writing this a lot:
61
61
62
62
```ts
63
-
let widget:Widget|undefined;
64
-
try {
65
-
widget=awaitwidgetRepo.get(widgetID);
63
+
let widget:Widget|undefined;
64
+
try {
65
+
widget=awaitwidgetRepo.get(widgetID);
66
+
} catch (error) {
67
+
if (!(errorinstanceofNotFoundError)) {
68
+
throwerror;
66
69
}
67
-
catch (error) {
68
-
if (!(errorinstanceofNotFoundError)) {
69
-
throwerror;
70
-
}
71
-
}
72
-
73
-
if (widget) { /* ... */ }
70
+
}
71
+
72
+
if (widget) {
73
+
/* ... */
74
+
}
74
75
```
75
76
76
77
You may be willing to do that once... but not more. So you first try to change the repository:
@@ -83,7 +84,7 @@ class WidgetRepository {
83
84
}
84
85
```
85
86
86
-
Now it returns `undefined` instead of throwing. Oh, but what a hassle now you have to _check_ for
87
+
Now it returns `undefined` instead of throwing. Oh, but what a hassle - now you have to _check_ for
87
88
`undefined`_every time_ you call the function! So instead, you define _two_ functions:
88
89
89
90
```ts
@@ -99,7 +100,7 @@ class WidgetRepository {
99
100
100
101
That makes it easier. It works. You just have to write _two_ functions every time you write a get function. 🙄
0 commit comments