1
+ import isNumber from 'lodash/isNumber' ;
2
+
3
+ /**
4
+ * The base for the whole library. Run predicate on the value.
5
+ * If predicate returns true, returns the value as is. Otherwise, throws
6
+ * with the given message.
7
+ * If you just want a condition, not a type assertion, use `beTrue`
8
+ * @param val {any} The value itself.
9
+ * @param predicate {(a: any) => a is T}. As you can see, the predicate should
10
+ * assert a type
11
+ * @param errorMessage {string}
12
+ */
13
+ export function be < T > (
14
+ val : any ,
15
+ predicate : ( a : any ) => a is T ,
16
+ errorMessage : string ,
17
+ ) : T {
18
+ if ( predicate ( val ) ) return val ;
19
+
20
+ throw new TypeError ( errorMessage ) ;
21
+ }
22
+
23
+ /**
24
+ * Checks for a condition that is not a type assertion. Ergo cannot
25
+ * narrow done the value type and returns the same type it gets.
26
+ * If you want to assert and narrow down types, use `be`.
27
+ * @param val {T} The value itself.
28
+ * @param predicate: {(a: T) => boolean}.
29
+ * @param errorMessage {string}
30
+ */
31
+ export function beTrue < T > (
32
+ val : T ,
33
+ predicate : ( a : T ) => boolean ,
34
+ errorMessage : string ,
35
+ ) : T {
36
+ if ( predicate ( val ) ) return val ;
37
+
38
+ throw new Error ( errorMessage ) ;
39
+ }
40
+
41
+ type CatchOptions = {
42
+ logger ?: ( e : Error ) => void ;
43
+ }
44
+
45
+ const noop = ( ) => { }
46
+
47
+ /**
48
+ * Runs a decoding function, and if all the validations succeed, returns
49
+ * the value. If something fails, falls back to another value (and optionally
50
+ * logs the error).
51
+ * @param make {() => T} The function that generates the expected type (and throws on invalid data)
52
+ * @param fallback {U} The fallback value (probably different from T)
53
+ * @param options {CatchOptions}
54
+ */
55
+ export function orBe < T , U > (
56
+ make : ( ) => T ,
57
+ fallback : U ,
58
+ { logger = noop } : CatchOptions = { }
59
+ ) : T | U {
60
+ try {
61
+ return make ( )
62
+ } catch ( e ) {
63
+ /*
64
+ If we ever add a custom error, we should replace all the
65
+ `new TypeError` invocations. But frankly, why not catch all
66
+ exceptions indiscriminately, even those not foreseen
67
+ by a programmer.
68
+ */
69
+ logger ( e )
70
+ return fallback
71
+ }
72
+ }
0 commit comments