@nunofyobiz/effect-extras 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -2
- package/dist/ArrayX.d.ts +415 -0
- package/dist/ArrayX.d.ts.map +1 -0
- package/dist/ArrayX.js +547 -0
- package/dist/ArrayX.js.map +1 -0
- package/dist/BigIntX.d.ts +24 -0
- package/dist/BigIntX.d.ts.map +1 -0
- package/dist/BigIntX.js +30 -0
- package/dist/BigIntX.js.map +1 -0
- package/dist/BooleanX.d.ts +25 -0
- package/dist/BooleanX.d.ts.map +1 -0
- package/dist/BooleanX.js +25 -0
- package/dist/BooleanX.js.map +1 -0
- package/dist/DurationX.d.ts +73 -0
- package/dist/DurationX.d.ts.map +1 -0
- package/dist/DurationX.js +91 -0
- package/dist/DurationX.js.map +1 -0
- package/dist/EffectX.d.ts +120 -0
- package/dist/EffectX.d.ts.map +1 -0
- package/dist/EffectX.js +140 -0
- package/dist/EffectX.js.map +1 -0
- package/dist/FormDataX.d.ts +49 -0
- package/dist/FormDataX.d.ts.map +1 -0
- package/dist/FormDataX.js +42 -0
- package/dist/FormDataX.js.map +1 -0
- package/dist/MapX.d.ts +32 -0
- package/dist/MapX.d.ts.map +1 -0
- package/dist/MapX.js +49 -0
- package/dist/MapX.js.map +1 -0
- package/dist/NonNullableX.d.ts +174 -0
- package/dist/NonNullableX.d.ts.map +1 -0
- package/dist/NonNullableX.js +212 -0
- package/dist/NonNullableX.js.map +1 -0
- package/dist/NumberX.d.ts +178 -0
- package/dist/NumberX.d.ts.map +1 -0
- package/dist/NumberX.js +214 -0
- package/dist/NumberX.js.map +1 -0
- package/dist/OptionX.d.ts +181 -0
- package/dist/OptionX.d.ts.map +1 -0
- package/dist/OptionX.js +195 -0
- package/dist/OptionX.js.map +1 -0
- package/dist/OrderX.d.ts +32 -0
- package/dist/OrderX.d.ts.map +1 -0
- package/dist/OrderX.js +32 -0
- package/dist/OrderX.js.map +1 -0
- package/dist/PredicateX.d.ts +76 -0
- package/dist/PredicateX.d.ts.map +1 -0
- package/dist/PredicateX.js +73 -0
- package/dist/PredicateX.js.map +1 -0
- package/dist/PromiseX.d.ts +32 -0
- package/dist/PromiseX.d.ts.map +1 -0
- package/dist/PromiseX.js +32 -0
- package/dist/PromiseX.js.map +1 -0
- package/dist/RecordX.d.ts +323 -0
- package/dist/RecordX.d.ts.map +1 -0
- package/dist/RecordX.js +326 -0
- package/dist/RecordX.js.map +1 -0
- package/dist/ResultX.d.ts +50 -0
- package/dist/ResultX.d.ts.map +1 -0
- package/dist/ResultX.js +50 -0
- package/dist/ResultX.js.map +1 -0
- package/dist/SchemaX.d.ts +249 -0
- package/dist/SchemaX.d.ts.map +1 -0
- package/dist/SchemaX.js +243 -0
- package/dist/SchemaX.js.map +1 -0
- package/dist/SetX.d.ts +121 -0
- package/dist/SetX.d.ts.map +1 -0
- package/dist/SetX.js +137 -0
- package/dist/SetX.js.map +1 -0
- package/dist/StringX.d.ts +70 -0
- package/dist/StringX.d.ts.map +1 -0
- package/dist/StringX.js +81 -0
- package/dist/StringX.js.map +1 -0
- package/dist/StructX.d.ts +219 -0
- package/dist/StructX.d.ts.map +1 -0
- package/dist/StructX.js +173 -0
- package/dist/StructX.js.map +1 -0
- package/dist/WarnResult.d.ts +1146 -0
- package/dist/WarnResult.d.ts.map +1 -0
- package/dist/WarnResult.js +1060 -0
- package/dist/WarnResult.js.map +1 -0
- package/dist/index.d.ts +22 -3772
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -1011
- package/dist/index.js.map +1 -1
- package/package.json +18 -5
- package/src/{ArrayX/ArrayX.ts → ArrayX.ts} +3 -3
- package/src/{DurationX/DurationX.ts → DurationX.ts} +1 -1
- package/src/{RecordX/RecordX.ts → RecordX.ts} +1 -1
- package/src/index.ts +21 -20
- package/src/ArrayX/index.ts +0 -1
- package/src/BigIntX/index.ts +0 -1
- package/src/BooleanX/index.ts +0 -1
- package/src/DurationX/index.ts +0 -1
- package/src/EffectX/index.ts +0 -1
- package/src/FormDataX/index.ts +0 -1
- package/src/MapX/index.ts +0 -1
- package/src/NonNullableX/index.ts +0 -2
- package/src/NumberX/index.ts +0 -1
- package/src/OptionX/index.ts +0 -1
- package/src/OrderX/index.ts +0 -1
- package/src/PredicateX/index.ts +0 -1
- package/src/PromiseX/index.ts +0 -1
- package/src/RecordX/index.ts +0 -1
- package/src/ResultX/index.ts +0 -1
- package/src/SchemaX/index.ts +0 -1
- package/src/SetX/index.ts +0 -1
- package/src/StringX/index.ts +0 -1
- package/src/StructX/index.ts +0 -1
- package/src/WarnResult/index.ts +0 -1
- /package/src/{BigIntX/BigIntX.ts → BigIntX.ts} +0 -0
- /package/src/{BooleanX/BooleanX.ts → BooleanX.ts} +0 -0
- /package/src/{EffectX/EffectX.ts → EffectX.ts} +0 -0
- /package/src/{FormDataX/FormDataX.ts → FormDataX.ts} +0 -0
- /package/src/{MapX/MapX.ts → MapX.ts} +0 -0
- /package/src/{NonNullableX/NonNullableX.ts → NonNullableX.ts} +0 -0
- /package/src/{NumberX/NumberX.ts → NumberX.ts} +0 -0
- /package/src/{OptionX/OptionX.ts → OptionX.ts} +0 -0
- /package/src/{OrderX/OrderX.ts → OrderX.ts} +0 -0
- /package/src/{PredicateX/PredicateX.ts → PredicateX.ts} +0 -0
- /package/src/{PromiseX/PromiseX.ts → PromiseX.ts} +0 -0
- /package/src/{ResultX/ResultX.ts → ResultX.ts} +0 -0
- /package/src/{SchemaX/SchemaX.ts → SchemaX.ts} +0 -0
- /package/src/{SetX/SetX.ts → SetX.ts} +0 -0
- /package/src/{StringX/StringX.ts → StringX.ts} +0 -0
- /package/src/{StructX/StructX.ts → StructX.ts} +0 -0
- /package/src/{WarnResult/WarnResult.ts → WarnResult.ts} +0 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers for working with non-nullable values.
|
|
3
|
+
*
|
|
4
|
+
* @since 0.0.0
|
|
5
|
+
*/
|
|
6
|
+
import { Order } from "effect";
|
|
7
|
+
/**
|
|
8
|
+
* Returns `value` narrowed to `NonNullable<A>`, throwing an `Error` if it is
|
|
9
|
+
* `null` or `undefined`.
|
|
10
|
+
*
|
|
11
|
+
* Use it at trusted boundaries where a value is known to be present but typed as
|
|
12
|
+
* nullable, turning a silent `undefined` into a loud failure. An optional
|
|
13
|
+
* `variableName` is woven into the thrown message to aid debugging. This is the
|
|
14
|
+
* function re-exported as `nn` from the module barrel, a terse shorthand handy
|
|
15
|
+
* inside string interpolations.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* import { NonNullableX } from "@nunofyobiz/effect-extras"
|
|
20
|
+
*
|
|
21
|
+
* assert.deepStrictEqual(NonNullableX.fromNullableOrThrow("value"), "value")
|
|
22
|
+
*
|
|
23
|
+
* assert.throws(
|
|
24
|
+
* () => NonNullableX.fromNullableOrThrow(null, "varName"),
|
|
25
|
+
* /Value is nullable: null \(variable name: varName\)/
|
|
26
|
+
* )
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @category unsafe
|
|
30
|
+
* @since 0.0.0
|
|
31
|
+
*/
|
|
32
|
+
export declare const fromNullableOrThrow: <A>(value: A, variableName?: string) => NonNullable<A>;
|
|
33
|
+
/**
|
|
34
|
+
* Branches on whether `value` is nullish, passing the value narrowed to
|
|
35
|
+
* `NonNullable<A>` to the `whenNotNullable` handler.
|
|
36
|
+
*
|
|
37
|
+
* A nullable-aware sibling of `Match.value`: it folds a present-or-absent value
|
|
38
|
+
* into a single `B` without an `if`/`else` or a manual `!= null` check. Note that
|
|
39
|
+
* falsy-but-present values (`""`, `0`, `false`) take the `whenNotNullable`
|
|
40
|
+
* branch — only `null` and `undefined` are treated as absent. Supports both
|
|
41
|
+
* data-first and data-last (pipeable) call styles.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* import { NonNullableX } from "@nunofyobiz/effect-extras"
|
|
46
|
+
* import { pipe } from "effect"
|
|
47
|
+
*
|
|
48
|
+
* // Data-first — present value flows through narrowed
|
|
49
|
+
* assert.deepStrictEqual(
|
|
50
|
+
* NonNullableX.match("value", {
|
|
51
|
+
* whenNullable: () => "nullable",
|
|
52
|
+
* whenNotNullable: (value) => value
|
|
53
|
+
* }),
|
|
54
|
+
* "value"
|
|
55
|
+
* )
|
|
56
|
+
*
|
|
57
|
+
* // Data-last — null takes the whenNullable branch
|
|
58
|
+
* assert.deepStrictEqual(
|
|
59
|
+
* pipe(
|
|
60
|
+
* null,
|
|
61
|
+
* NonNullableX.match({
|
|
62
|
+
* whenNullable: () => "nullable",
|
|
63
|
+
* whenNotNullable: (value) => value
|
|
64
|
+
* })
|
|
65
|
+
* ),
|
|
66
|
+
* "nullable"
|
|
67
|
+
* )
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* @category pattern matching
|
|
71
|
+
* @since 0.0.0
|
|
72
|
+
*/
|
|
73
|
+
export declare const match: (<A, B>(handlers: {
|
|
74
|
+
whenNullable: () => B;
|
|
75
|
+
whenNotNullable: (value: NonNullable<A>) => B;
|
|
76
|
+
}) => (value: A) => B) & (<A, B>(value: A, handlers: {
|
|
77
|
+
whenNullable: () => B;
|
|
78
|
+
whenNotNullable: (value: NonNullable<A>) => B;
|
|
79
|
+
}) => B);
|
|
80
|
+
/**
|
|
81
|
+
* Applies `map` to `a` only when it is non-nullish, passing nullish inputs
|
|
82
|
+
* through unchanged.
|
|
83
|
+
*
|
|
84
|
+
* This is the nullable-preserving map: a present value is transformed to `B`,
|
|
85
|
+
* while `null` stays `null` and `undefined` stays `undefined`, so nullability is
|
|
86
|
+
* carried through the transformation. Supports both data-first and data-last
|
|
87
|
+
* (pipeable) call styles.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* import { NonNullableX } from "@nunofyobiz/effect-extras"
|
|
92
|
+
* import { pipe } from "effect"
|
|
93
|
+
*
|
|
94
|
+
* // Data-first — present value is transformed
|
|
95
|
+
* assert.deepStrictEqual(NonNullableX.map(1, (v: number) => v + 1), 2)
|
|
96
|
+
*
|
|
97
|
+
* // Data-last — nullish passes through unchanged
|
|
98
|
+
* const value: number | null = null
|
|
99
|
+
* assert.deepStrictEqual(
|
|
100
|
+
* pipe(
|
|
101
|
+
* value,
|
|
102
|
+
* NonNullableX.map<number | null, number>((v) => v + 1)
|
|
103
|
+
* ),
|
|
104
|
+
* null
|
|
105
|
+
* )
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* @category mapping
|
|
109
|
+
* @since 0.0.0
|
|
110
|
+
*/
|
|
111
|
+
export declare const map: (<A, B>(map: (a: NonNullable<A>) => B) => (a: A) => B | (null & A) | (undefined & A)) & (<A, B>(a: A, map: (a: NonNullable<A>) => B) => B | (null & A) | (undefined & A));
|
|
112
|
+
/**
|
|
113
|
+
* Lifts a total function `(a: A) => B` into one that tolerates nullish input,
|
|
114
|
+
* applying it to present values and passing `null`/`undefined` through unchanged.
|
|
115
|
+
*
|
|
116
|
+
* Where `map` operates on a value, `lift` transforms the function itself,
|
|
117
|
+
* yielding a reusable `(a: A | null | undefined) => B | null | undefined` you can
|
|
118
|
+
* drop into a `pipe`. Use it to adapt a plain transform to a nullable pipeline
|
|
119
|
+
* without wrapping each call site.
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```ts
|
|
123
|
+
* import { NonNullableX } from "@nunofyobiz/effect-extras"
|
|
124
|
+
* import { Number, pipe } from "effect"
|
|
125
|
+
*
|
|
126
|
+
* const addOne = NonNullableX.lift(Number.sum(1))
|
|
127
|
+
*
|
|
128
|
+
* assert.deepStrictEqual(pipe(1, addOne), 2)
|
|
129
|
+
* assert.deepStrictEqual(pipe(null, addOne), null)
|
|
130
|
+
* assert.deepStrictEqual(pipe(undefined, addOne), undefined)
|
|
131
|
+
* ```
|
|
132
|
+
*
|
|
133
|
+
* @category mapping
|
|
134
|
+
* @since 0.0.0
|
|
135
|
+
*/
|
|
136
|
+
export declare const lift: <A, B>(map: (a: A) => B) => (a: A | null | undefined) => B | null | undefined;
|
|
137
|
+
/**
|
|
138
|
+
* Extends an `Order.Order<A>` to an `Order.Order<A | null>`, deciding where
|
|
139
|
+
* `null` sorts relative to present values via the `behavior` argument.
|
|
140
|
+
*
|
|
141
|
+
* Pass `"value-null"` to push `null`s to the end and `"null-value"` to pull them
|
|
142
|
+
* to the front; two present values fall back to the wrapped order. Use it to sort
|
|
143
|
+
* collections that mix real values with gaps without a bespoke comparator.
|
|
144
|
+
* Supports both data-first and data-last (pipeable) call styles.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* import { NonNullableX } from "@nunofyobiz/effect-extras"
|
|
149
|
+
* import { Array, Order, pipe } from "effect"
|
|
150
|
+
*
|
|
151
|
+
* // "value-null" — nulls sorted last
|
|
152
|
+
* assert.deepStrictEqual(
|
|
153
|
+
* pipe(
|
|
154
|
+
* [null, 1, 3, null, 2],
|
|
155
|
+
* Array.sort(NonNullableX.nullableOrder(Order.Number, "value-null"))
|
|
156
|
+
* ),
|
|
157
|
+
* [1, 2, 3, null, null]
|
|
158
|
+
* )
|
|
159
|
+
*
|
|
160
|
+
* // "null-value" — nulls sorted first (data-last)
|
|
161
|
+
* assert.deepStrictEqual(
|
|
162
|
+
* pipe(
|
|
163
|
+
* [null, 1, 3, null, 2],
|
|
164
|
+
* Array.sort(pipe(Order.Number, NonNullableX.nullableOrder("null-value")))
|
|
165
|
+
* ),
|
|
166
|
+
* [null, null, 1, 2, 3]
|
|
167
|
+
* )
|
|
168
|
+
* ```
|
|
169
|
+
*
|
|
170
|
+
* @category ordering
|
|
171
|
+
* @since 0.0.0
|
|
172
|
+
*/
|
|
173
|
+
export declare const nullableOrder: ((behavior: "value-null" | "null-value") => <A>(order: Order.Order<A>) => Order.Order<A | null>) & (<A>(order: Order.Order<A>, behavior: "value-null" | "null-value") => Order.Order<A | null>);
|
|
174
|
+
//# sourceMappingURL=NonNullableX.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NonNullableX.d.ts","sourceRoot":"","sources":["../src/NonNullableX.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAGL,KAAK,EAGN,MAAM,QAAQ,CAAC;AAGhB;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,mBAAmB,GAAI,CAAC,EACnC,OAAO,CAAC,EACR,eAAe,MAAM,KACpB,WAAW,CAAC,CAAC,CAOf,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,eAAO,MAAM,KAAK,IACf,CAAC,EAAE,CAAC,YAAY;IACf,YAAY,EAAE,MAAM,CAAC,CAAC;IACtB,eAAe,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;CAC/C,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,MACpB,CAAC,EAAE,CAAC,SACI,CAAC,YACE;IACR,YAAY,EAAE,MAAM,CAAC,CAAC;IACtB,eAAe,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;CAC/C,KACE,CAAC,CAWP,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,GAAG,IACb,CAAC,EAAE,CAAC,OACE,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,KAC1B,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC,MAC9C,CAAC,EAAE,CAAC,KACA,CAAC,OACC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,KAC1B,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC,CAiBtC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,IAAI,GACd,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MACtB,GAAG,CAAC,GAAG,IAAI,GAAG,SAAS,KAAG,CAAC,GAAG,IAAI,GAAG,SAMrC,CAAC;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,aAAa,cAEZ,YAAY,GAAG,YAAY,KAClC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,MACvD,CAAC,SACO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,YACX,YAAY,GAAG,YAAY,KAClC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAwC3B,CAAC"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers for working with non-nullable values.
|
|
3
|
+
*
|
|
4
|
+
* @since 0.0.0
|
|
5
|
+
*/
|
|
6
|
+
import { Number as EffectNumber, Match, Predicate } from "effect";
|
|
7
|
+
import { dual } from "effect/Function";
|
|
8
|
+
/**
|
|
9
|
+
* Returns `value` narrowed to `NonNullable<A>`, throwing an `Error` if it is
|
|
10
|
+
* `null` or `undefined`.
|
|
11
|
+
*
|
|
12
|
+
* Use it at trusted boundaries where a value is known to be present but typed as
|
|
13
|
+
* nullable, turning a silent `undefined` into a loud failure. An optional
|
|
14
|
+
* `variableName` is woven into the thrown message to aid debugging. This is the
|
|
15
|
+
* function re-exported as `nn` from the module barrel, a terse shorthand handy
|
|
16
|
+
* inside string interpolations.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { NonNullableX } from "@nunofyobiz/effect-extras"
|
|
21
|
+
*
|
|
22
|
+
* assert.deepStrictEqual(NonNullableX.fromNullableOrThrow("value"), "value")
|
|
23
|
+
*
|
|
24
|
+
* assert.throws(
|
|
25
|
+
* () => NonNullableX.fromNullableOrThrow(null, "varName"),
|
|
26
|
+
* /Value is nullable: null \(variable name: varName\)/
|
|
27
|
+
* )
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @category unsafe
|
|
31
|
+
* @since 0.0.0
|
|
32
|
+
*/
|
|
33
|
+
export const fromNullableOrThrow = (value, variableName) => {
|
|
34
|
+
if (Predicate.isNotNullish(value)) {
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
throw new Error(`Value is nullable: ${String(value)}${Predicate.isNotNullish(variableName) ? ` (variable name: ${variableName})` : ""}`);
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Branches on whether `value` is nullish, passing the value narrowed to
|
|
41
|
+
* `NonNullable<A>` to the `whenNotNullable` handler.
|
|
42
|
+
*
|
|
43
|
+
* A nullable-aware sibling of `Match.value`: it folds a present-or-absent value
|
|
44
|
+
* into a single `B` without an `if`/`else` or a manual `!= null` check. Note that
|
|
45
|
+
* falsy-but-present values (`""`, `0`, `false`) take the `whenNotNullable`
|
|
46
|
+
* branch — only `null` and `undefined` are treated as absent. Supports both
|
|
47
|
+
* data-first and data-last (pipeable) call styles.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* import { NonNullableX } from "@nunofyobiz/effect-extras"
|
|
52
|
+
* import { pipe } from "effect"
|
|
53
|
+
*
|
|
54
|
+
* // Data-first — present value flows through narrowed
|
|
55
|
+
* assert.deepStrictEqual(
|
|
56
|
+
* NonNullableX.match("value", {
|
|
57
|
+
* whenNullable: () => "nullable",
|
|
58
|
+
* whenNotNullable: (value) => value
|
|
59
|
+
* }),
|
|
60
|
+
* "value"
|
|
61
|
+
* )
|
|
62
|
+
*
|
|
63
|
+
* // Data-last — null takes the whenNullable branch
|
|
64
|
+
* assert.deepStrictEqual(
|
|
65
|
+
* pipe(
|
|
66
|
+
* null,
|
|
67
|
+
* NonNullableX.match({
|
|
68
|
+
* whenNullable: () => "nullable",
|
|
69
|
+
* whenNotNullable: (value) => value
|
|
70
|
+
* })
|
|
71
|
+
* ),
|
|
72
|
+
* "nullable"
|
|
73
|
+
* )
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* @category pattern matching
|
|
77
|
+
* @since 0.0.0
|
|
78
|
+
*/
|
|
79
|
+
export const match = /*#__PURE__*/dual(2, (value, {
|
|
80
|
+
whenNullable,
|
|
81
|
+
whenNotNullable
|
|
82
|
+
}) => Predicate.isNotNullish(value) ? whenNotNullable(value) : whenNullable());
|
|
83
|
+
/**
|
|
84
|
+
* Applies `map` to `a` only when it is non-nullish, passing nullish inputs
|
|
85
|
+
* through unchanged.
|
|
86
|
+
*
|
|
87
|
+
* This is the nullable-preserving map: a present value is transformed to `B`,
|
|
88
|
+
* while `null` stays `null` and `undefined` stays `undefined`, so nullability is
|
|
89
|
+
* carried through the transformation. Supports both data-first and data-last
|
|
90
|
+
* (pipeable) call styles.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* import { NonNullableX } from "@nunofyobiz/effect-extras"
|
|
95
|
+
* import { pipe } from "effect"
|
|
96
|
+
*
|
|
97
|
+
* // Data-first — present value is transformed
|
|
98
|
+
* assert.deepStrictEqual(NonNullableX.map(1, (v: number) => v + 1), 2)
|
|
99
|
+
*
|
|
100
|
+
* // Data-last — nullish passes through unchanged
|
|
101
|
+
* const value: number | null = null
|
|
102
|
+
* assert.deepStrictEqual(
|
|
103
|
+
* pipe(
|
|
104
|
+
* value,
|
|
105
|
+
* NonNullableX.map<number | null, number>((v) => v + 1)
|
|
106
|
+
* ),
|
|
107
|
+
* null
|
|
108
|
+
* )
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* @category mapping
|
|
112
|
+
* @since 0.0.0
|
|
113
|
+
*/
|
|
114
|
+
export const map = /*#__PURE__*/dual(2, (a, map) => {
|
|
115
|
+
if (Predicate.isNotNullish(a)) {
|
|
116
|
+
return map(a);
|
|
117
|
+
}
|
|
118
|
+
if (Predicate.isNullish(a)) {
|
|
119
|
+
return a;
|
|
120
|
+
}
|
|
121
|
+
throw new Error(`Value is neither nullable nor non-nullable: ${String(a)}`);
|
|
122
|
+
});
|
|
123
|
+
/**
|
|
124
|
+
* Lifts a total function `(a: A) => B` into one that tolerates nullish input,
|
|
125
|
+
* applying it to present values and passing `null`/`undefined` through unchanged.
|
|
126
|
+
*
|
|
127
|
+
* Where `map` operates on a value, `lift` transforms the function itself,
|
|
128
|
+
* yielding a reusable `(a: A | null | undefined) => B | null | undefined` you can
|
|
129
|
+
* drop into a `pipe`. Use it to adapt a plain transform to a nullable pipeline
|
|
130
|
+
* without wrapping each call site.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```ts
|
|
134
|
+
* import { NonNullableX } from "@nunofyobiz/effect-extras"
|
|
135
|
+
* import { Number, pipe } from "effect"
|
|
136
|
+
*
|
|
137
|
+
* const addOne = NonNullableX.lift(Number.sum(1))
|
|
138
|
+
*
|
|
139
|
+
* assert.deepStrictEqual(pipe(1, addOne), 2)
|
|
140
|
+
* assert.deepStrictEqual(pipe(null, addOne), null)
|
|
141
|
+
* assert.deepStrictEqual(pipe(undefined, addOne), undefined)
|
|
142
|
+
* ```
|
|
143
|
+
*
|
|
144
|
+
* @category mapping
|
|
145
|
+
* @since 0.0.0
|
|
146
|
+
*/
|
|
147
|
+
export const lift = map => a => {
|
|
148
|
+
if (Predicate.isNullish(a)) {
|
|
149
|
+
return a;
|
|
150
|
+
}
|
|
151
|
+
return map(a);
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Extends an `Order.Order<A>` to an `Order.Order<A | null>`, deciding where
|
|
155
|
+
* `null` sorts relative to present values via the `behavior` argument.
|
|
156
|
+
*
|
|
157
|
+
* Pass `"value-null"` to push `null`s to the end and `"null-value"` to pull them
|
|
158
|
+
* to the front; two present values fall back to the wrapped order. Use it to sort
|
|
159
|
+
* collections that mix real values with gaps without a bespoke comparator.
|
|
160
|
+
* Supports both data-first and data-last (pipeable) call styles.
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```ts
|
|
164
|
+
* import { NonNullableX } from "@nunofyobiz/effect-extras"
|
|
165
|
+
* import { Array, Order, pipe } from "effect"
|
|
166
|
+
*
|
|
167
|
+
* // "value-null" — nulls sorted last
|
|
168
|
+
* assert.deepStrictEqual(
|
|
169
|
+
* pipe(
|
|
170
|
+
* [null, 1, 3, null, 2],
|
|
171
|
+
* Array.sort(NonNullableX.nullableOrder(Order.Number, "value-null"))
|
|
172
|
+
* ),
|
|
173
|
+
* [1, 2, 3, null, null]
|
|
174
|
+
* )
|
|
175
|
+
*
|
|
176
|
+
* // "null-value" — nulls sorted first (data-last)
|
|
177
|
+
* assert.deepStrictEqual(
|
|
178
|
+
* pipe(
|
|
179
|
+
* [null, 1, 3, null, 2],
|
|
180
|
+
* Array.sort(pipe(Order.Number, NonNullableX.nullableOrder("null-value")))
|
|
181
|
+
* ),
|
|
182
|
+
* [null, null, 1, 2, 3]
|
|
183
|
+
* )
|
|
184
|
+
* ```
|
|
185
|
+
*
|
|
186
|
+
* @category ordering
|
|
187
|
+
* @since 0.0.0
|
|
188
|
+
*/
|
|
189
|
+
export const nullableOrder = /*#__PURE__*/dual(2, (order, behavior) => {
|
|
190
|
+
// Prepare to sort them based on their nullability
|
|
191
|
+
const {
|
|
192
|
+
nullableSortCategory,
|
|
193
|
+
valueSortCategory
|
|
194
|
+
} = Match.value(behavior).pipe(Match.when("value-null", () => ({
|
|
195
|
+
nullableSortCategory: 1,
|
|
196
|
+
valueSortCategory: 0
|
|
197
|
+
})), Match.when("null-value", () => ({
|
|
198
|
+
nullableSortCategory: 0,
|
|
199
|
+
valueSortCategory: 1
|
|
200
|
+
})), Match.exhaustive);
|
|
201
|
+
return (a, b) => {
|
|
202
|
+
// Right off the bat, if they are both defined just return the regular ordering
|
|
203
|
+
if (Predicate.isNotNullish(a) && Predicate.isNotNullish(b)) {
|
|
204
|
+
return order(a, b);
|
|
205
|
+
}
|
|
206
|
+
// Otherwise figure out which category each value is
|
|
207
|
+
const aCategory = Predicate.isNotNullish(a) ? valueSortCategory : nullableSortCategory;
|
|
208
|
+
const bCategory = Predicate.isNotNullish(b) ? valueSortCategory : nullableSortCategory;
|
|
209
|
+
return EffectNumber.sign(aCategory - bCategory);
|
|
210
|
+
};
|
|
211
|
+
});
|
|
212
|
+
//# sourceMappingURL=NonNullableX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NonNullableX.js","names":["Number","EffectNumber","Match","Predicate","dual","fromNullableOrThrow","value","variableName","isNotNullish","Error","String","match","whenNullable","whenNotNullable","map","a","isNullish","lift","nullableOrder","order","behavior","nullableSortCategory","valueSortCategory","pipe","when","exhaustive","b","aCategory","bCategory","sign"],"sources":["../src/NonNullableX.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic, framework-agnostic extensions to Effect's `Number` module.
|
|
3
|
+
*
|
|
4
|
+
* @since 0.0.0
|
|
5
|
+
*/
|
|
6
|
+
import { Option } from "effect";
|
|
7
|
+
/**
|
|
8
|
+
* Computes the logarithm of `number` in the given `base`, throwing when the
|
|
9
|
+
* inputs fall outside the domain of `log`.
|
|
10
|
+
*
|
|
11
|
+
* Throws when `number <= 0`, when `base` is `<= 0` or `1`, or when `number` and
|
|
12
|
+
* `base` sit on opposite sides of `1` (a fractional base with `number >= 1`, or
|
|
13
|
+
* a base `>= 1` with `number < 1`) — cases where the real logarithm is
|
|
14
|
+
* undefined or non-finite. Reach for it only when the inputs are already known
|
|
15
|
+
* to be valid.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* import { pipe } from "effect"
|
|
20
|
+
* import { NumberX } from "@nunofyobiz/effect-extras"
|
|
21
|
+
*
|
|
22
|
+
* // data-first
|
|
23
|
+
* assert.deepStrictEqual(NumberX.unsafeLogBase(8, 2), 3)
|
|
24
|
+
* assert.deepStrictEqual(NumberX.unsafeLogBase(100, 10), 2)
|
|
25
|
+
*
|
|
26
|
+
* // data-last (piped)
|
|
27
|
+
* assert.deepStrictEqual(pipe(8, NumberX.unsafeLogBase(2)), 3)
|
|
28
|
+
*
|
|
29
|
+
* // throws outside the domain of log
|
|
30
|
+
* assert.throws(() => NumberX.unsafeLogBase(0, 2))
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @category unsafe
|
|
34
|
+
* @since 0.0.0
|
|
35
|
+
*/
|
|
36
|
+
export declare const unsafeLogBase: ((base: number) => (number: number) => number) & ((number: number, base: number) => number);
|
|
37
|
+
/**
|
|
38
|
+
* Expresses `numerator` as a percentage of `total`, throwing on division by
|
|
39
|
+
* zero.
|
|
40
|
+
*
|
|
41
|
+
* Returns `(numerator / total) * 100`. When `total` is `0` the percentage is
|
|
42
|
+
* undefined, so this throws rather than returning `Infinity` or `NaN` — use it
|
|
43
|
+
* only when `total` is known to be non-zero.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* import { pipe } from "effect"
|
|
48
|
+
* import { NumberX } from "@nunofyobiz/effect-extras"
|
|
49
|
+
*
|
|
50
|
+
* // data-first
|
|
51
|
+
* assert.deepStrictEqual(NumberX.unsafeToPercentOf(1, 2), 50)
|
|
52
|
+
* assert.deepStrictEqual(NumberX.unsafeToPercentOf(2, 1), 200)
|
|
53
|
+
*
|
|
54
|
+
* // data-last (piped)
|
|
55
|
+
* assert.deepStrictEqual(pipe(1, NumberX.unsafeToPercentOf(2)), 50)
|
|
56
|
+
*
|
|
57
|
+
* // throws on division by zero
|
|
58
|
+
* assert.throws(() => NumberX.unsafeToPercentOf(1, 0))
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @category unsafe
|
|
62
|
+
* @since 0.0.0
|
|
63
|
+
*/
|
|
64
|
+
export declare const unsafeToPercentOf: ((total: number) => (numerator: number) => number) & ((numerator: number, total: number) => number);
|
|
65
|
+
/**
|
|
66
|
+
* Formats `number` with a fixed number of decimal places, returning a `string`.
|
|
67
|
+
*
|
|
68
|
+
* A pipeable wrapper around `Number.prototype.toFixed` — the result is rounded
|
|
69
|
+
* (not truncated) to `numberDigits` decimals and always carries exactly that
|
|
70
|
+
* many digits after the point.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* import { pipe } from "effect"
|
|
75
|
+
* import { NumberX } from "@nunofyobiz/effect-extras"
|
|
76
|
+
*
|
|
77
|
+
* // data-first
|
|
78
|
+
* assert.deepStrictEqual(NumberX.toFixed(3.236242, 2), "3.24")
|
|
79
|
+
*
|
|
80
|
+
* // data-last (piped)
|
|
81
|
+
* assert.deepStrictEqual(pipe(3.236242, NumberX.toFixed(0)), "3")
|
|
82
|
+
* ```
|
|
83
|
+
*
|
|
84
|
+
* @category conversions
|
|
85
|
+
* @since 0.0.0
|
|
86
|
+
*/
|
|
87
|
+
export declare const toFixed: ((numberDigits: number) => (number: number) => string) & ((number: number, numberDigits: number) => string);
|
|
88
|
+
/**
|
|
89
|
+
* Rounds `number` to a fixed number of decimal places, returning a `number`.
|
|
90
|
+
*
|
|
91
|
+
* Unlike {@link toFixed}, the result stays a `number` (no trailing zeroes) — it
|
|
92
|
+
* formats via `toFixed` then parses back, which sidesteps the usual
|
|
93
|
+
* floating-point rounding artifacts. See
|
|
94
|
+
* https://stackoverflow.com/a/29494612/22875620.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```ts
|
|
98
|
+
* import { pipe } from "effect"
|
|
99
|
+
* import { NumberX } from "@nunofyobiz/effect-extras"
|
|
100
|
+
*
|
|
101
|
+
* // data-first
|
|
102
|
+
* assert.deepStrictEqual(NumberX.roundToDigits(3.236242, 2), 3.24)
|
|
103
|
+
*
|
|
104
|
+
* // data-last (piped)
|
|
105
|
+
* assert.deepStrictEqual(pipe(3.736242, NumberX.roundToDigits(0)), 4)
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* @category mapping
|
|
109
|
+
* @since 0.0.0
|
|
110
|
+
*/
|
|
111
|
+
export declare const roundToDigits: ((numberDigits: number) => (number: number) => number) & ((number: number, numberDigits: number) => number);
|
|
112
|
+
/**
|
|
113
|
+
* Renders `number` as a `string`, left-padded with zeroes to at least
|
|
114
|
+
* `numberDigits` characters.
|
|
115
|
+
*
|
|
116
|
+
* If the number's string representation is already as long as (or longer than)
|
|
117
|
+
* `numberDigits`, it is returned unchanged.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* import { pipe } from "effect"
|
|
122
|
+
* import { NumberX } from "@nunofyobiz/effect-extras"
|
|
123
|
+
*
|
|
124
|
+
* // data-first
|
|
125
|
+
* assert.deepStrictEqual(NumberX.padLeftZeroes(1, 3), "001")
|
|
126
|
+
*
|
|
127
|
+
* // longer than the target width is returned unchanged
|
|
128
|
+
* assert.deepStrictEqual(NumberX.padLeftZeroes(1000, 3), "1000")
|
|
129
|
+
*
|
|
130
|
+
* // data-last (piped)
|
|
131
|
+
* assert.deepStrictEqual(pipe(10, NumberX.padLeftZeroes(3)), "010")
|
|
132
|
+
* ```
|
|
133
|
+
*
|
|
134
|
+
* @category conversions
|
|
135
|
+
* @since 0.0.0
|
|
136
|
+
*/
|
|
137
|
+
export declare const padLeftZeroes: ((numberDigits: number) => (number: number) => string) & ((number: number, numberDigits: number) => string);
|
|
138
|
+
/**
|
|
139
|
+
* Converts a `0`-indexed value to its `1`-indexed rank by adding `1`.
|
|
140
|
+
*
|
|
141
|
+
* Handy for presentation where humans count from one (e.g. the element at
|
|
142
|
+
* index `0` is shown as "item 1").
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* import { NumberX } from "@nunofyobiz/effect-extras"
|
|
147
|
+
*
|
|
148
|
+
* assert.deepStrictEqual(NumberX.indexToRank(0), 1)
|
|
149
|
+
* assert.deepStrictEqual(NumberX.indexToRank(4), 5)
|
|
150
|
+
* ```
|
|
151
|
+
*
|
|
152
|
+
* @category mapping
|
|
153
|
+
* @since 0.0.0
|
|
154
|
+
*/
|
|
155
|
+
export declare const indexToRank: (index: number) => number;
|
|
156
|
+
/**
|
|
157
|
+
* Converts a `0`-indexed column number into its bijective base-26 spreadsheet
|
|
158
|
+
* label (`A`, `B`, …, `Z`, `AA`, `AB`, …).
|
|
159
|
+
*
|
|
160
|
+
* Returns `None` for a negative `index`; every non-negative index maps to a
|
|
161
|
+
* `Some` label. Indexing is `0`-based here, so `0` is `"A"` and `25` is `"Z"`,
|
|
162
|
+
* unlike the `1`-based numbering shown in most spreadsheet references.
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* ```ts
|
|
166
|
+
* import { Option } from "effect"
|
|
167
|
+
* import { NumberX } from "@nunofyobiz/effect-extras"
|
|
168
|
+
*
|
|
169
|
+
* assert.deepStrictEqual(NumberX.indexToExcel(0), Option.some("A"))
|
|
170
|
+
* assert.deepStrictEqual(NumberX.indexToExcel(26), Option.some("AA"))
|
|
171
|
+
* assert.deepStrictEqual(NumberX.indexToExcel(-1), Option.none())
|
|
172
|
+
* ```
|
|
173
|
+
*
|
|
174
|
+
* @category conversions
|
|
175
|
+
* @since 0.0.0
|
|
176
|
+
*/
|
|
177
|
+
export declare const indexToExcel: (index: number) => Option.Option<string>;
|
|
178
|
+
//# sourceMappingURL=NumberX.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NumberX.d.ts","sourceRoot":"","sources":["../src/NumberX.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAA0B,MAAM,EAAQ,MAAM,QAAQ,CAAC;AA6B9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,aAAa,UACjB,MAAM,KAAK,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,cACnC,MAAM,QAAQ,MAAM,KAAK,MAAM,CAMzC,CAAC;AAqBF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,iBAAiB,WAEpB,MAAM,KAAK,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,iBAEpC,MAAM,SAAS,MAAM,KAAK,MAAM,CAM7C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,OAAO,kBACH,MAAM,KAAK,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,cAC3C,MAAM,gBAAgB,MAAM,KAAK,MAAM,CAGjD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,aAAa,kBAET,MAAM,KAAK,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,cAE3C,MAAM,gBAAgB,MAAM,KAAK,MAAM,CAGjD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,aAAa,kBACT,MAAM,KAAK,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,cAC3C,MAAM,gBAAgB,MAAM,KAAK,MAAM,CAGjD,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,KAAG,MAAmB,CAAC;AAIhE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAehE,CAAC"}
|