@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.
Files changed (127) hide show
  1. package/README.md +36 -2
  2. package/dist/ArrayX.d.ts +415 -0
  3. package/dist/ArrayX.d.ts.map +1 -0
  4. package/dist/ArrayX.js +547 -0
  5. package/dist/ArrayX.js.map +1 -0
  6. package/dist/BigIntX.d.ts +24 -0
  7. package/dist/BigIntX.d.ts.map +1 -0
  8. package/dist/BigIntX.js +30 -0
  9. package/dist/BigIntX.js.map +1 -0
  10. package/dist/BooleanX.d.ts +25 -0
  11. package/dist/BooleanX.d.ts.map +1 -0
  12. package/dist/BooleanX.js +25 -0
  13. package/dist/BooleanX.js.map +1 -0
  14. package/dist/DurationX.d.ts +73 -0
  15. package/dist/DurationX.d.ts.map +1 -0
  16. package/dist/DurationX.js +91 -0
  17. package/dist/DurationX.js.map +1 -0
  18. package/dist/EffectX.d.ts +120 -0
  19. package/dist/EffectX.d.ts.map +1 -0
  20. package/dist/EffectX.js +140 -0
  21. package/dist/EffectX.js.map +1 -0
  22. package/dist/FormDataX.d.ts +49 -0
  23. package/dist/FormDataX.d.ts.map +1 -0
  24. package/dist/FormDataX.js +42 -0
  25. package/dist/FormDataX.js.map +1 -0
  26. package/dist/MapX.d.ts +32 -0
  27. package/dist/MapX.d.ts.map +1 -0
  28. package/dist/MapX.js +49 -0
  29. package/dist/MapX.js.map +1 -0
  30. package/dist/NonNullableX.d.ts +174 -0
  31. package/dist/NonNullableX.d.ts.map +1 -0
  32. package/dist/NonNullableX.js +212 -0
  33. package/dist/NonNullableX.js.map +1 -0
  34. package/dist/NumberX.d.ts +178 -0
  35. package/dist/NumberX.d.ts.map +1 -0
  36. package/dist/NumberX.js +214 -0
  37. package/dist/NumberX.js.map +1 -0
  38. package/dist/OptionX.d.ts +181 -0
  39. package/dist/OptionX.d.ts.map +1 -0
  40. package/dist/OptionX.js +195 -0
  41. package/dist/OptionX.js.map +1 -0
  42. package/dist/OrderX.d.ts +32 -0
  43. package/dist/OrderX.d.ts.map +1 -0
  44. package/dist/OrderX.js +32 -0
  45. package/dist/OrderX.js.map +1 -0
  46. package/dist/PredicateX.d.ts +76 -0
  47. package/dist/PredicateX.d.ts.map +1 -0
  48. package/dist/PredicateX.js +73 -0
  49. package/dist/PredicateX.js.map +1 -0
  50. package/dist/PromiseX.d.ts +32 -0
  51. package/dist/PromiseX.d.ts.map +1 -0
  52. package/dist/PromiseX.js +32 -0
  53. package/dist/PromiseX.js.map +1 -0
  54. package/dist/RecordX.d.ts +323 -0
  55. package/dist/RecordX.d.ts.map +1 -0
  56. package/dist/RecordX.js +326 -0
  57. package/dist/RecordX.js.map +1 -0
  58. package/dist/ResultX.d.ts +50 -0
  59. package/dist/ResultX.d.ts.map +1 -0
  60. package/dist/ResultX.js +50 -0
  61. package/dist/ResultX.js.map +1 -0
  62. package/dist/SchemaX.d.ts +249 -0
  63. package/dist/SchemaX.d.ts.map +1 -0
  64. package/dist/SchemaX.js +243 -0
  65. package/dist/SchemaX.js.map +1 -0
  66. package/dist/SetX.d.ts +121 -0
  67. package/dist/SetX.d.ts.map +1 -0
  68. package/dist/SetX.js +137 -0
  69. package/dist/SetX.js.map +1 -0
  70. package/dist/StringX.d.ts +70 -0
  71. package/dist/StringX.d.ts.map +1 -0
  72. package/dist/StringX.js +81 -0
  73. package/dist/StringX.js.map +1 -0
  74. package/dist/StructX.d.ts +219 -0
  75. package/dist/StructX.d.ts.map +1 -0
  76. package/dist/StructX.js +173 -0
  77. package/dist/StructX.js.map +1 -0
  78. package/dist/WarnResult.d.ts +1146 -0
  79. package/dist/WarnResult.d.ts.map +1 -0
  80. package/dist/WarnResult.js +1060 -0
  81. package/dist/WarnResult.js.map +1 -0
  82. package/dist/index.d.ts +22 -3772
  83. package/dist/index.d.ts.map +1 -0
  84. package/dist/index.js +21 -1011
  85. package/dist/index.js.map +1 -1
  86. package/package.json +18 -5
  87. package/src/{ArrayX/ArrayX.ts → ArrayX.ts} +3 -3
  88. package/src/{DurationX/DurationX.ts → DurationX.ts} +1 -1
  89. package/src/{RecordX/RecordX.ts → RecordX.ts} +1 -1
  90. package/src/index.ts +21 -20
  91. package/src/ArrayX/index.ts +0 -1
  92. package/src/BigIntX/index.ts +0 -1
  93. package/src/BooleanX/index.ts +0 -1
  94. package/src/DurationX/index.ts +0 -1
  95. package/src/EffectX/index.ts +0 -1
  96. package/src/FormDataX/index.ts +0 -1
  97. package/src/MapX/index.ts +0 -1
  98. package/src/NonNullableX/index.ts +0 -2
  99. package/src/NumberX/index.ts +0 -1
  100. package/src/OptionX/index.ts +0 -1
  101. package/src/OrderX/index.ts +0 -1
  102. package/src/PredicateX/index.ts +0 -1
  103. package/src/PromiseX/index.ts +0 -1
  104. package/src/RecordX/index.ts +0 -1
  105. package/src/ResultX/index.ts +0 -1
  106. package/src/SchemaX/index.ts +0 -1
  107. package/src/SetX/index.ts +0 -1
  108. package/src/StringX/index.ts +0 -1
  109. package/src/StructX/index.ts +0 -1
  110. package/src/WarnResult/index.ts +0 -1
  111. /package/src/{BigIntX/BigIntX.ts → BigIntX.ts} +0 -0
  112. /package/src/{BooleanX/BooleanX.ts → BooleanX.ts} +0 -0
  113. /package/src/{EffectX/EffectX.ts → EffectX.ts} +0 -0
  114. /package/src/{FormDataX/FormDataX.ts → FormDataX.ts} +0 -0
  115. /package/src/{MapX/MapX.ts → MapX.ts} +0 -0
  116. /package/src/{NonNullableX/NonNullableX.ts → NonNullableX.ts} +0 -0
  117. /package/src/{NumberX/NumberX.ts → NumberX.ts} +0 -0
  118. /package/src/{OptionX/OptionX.ts → OptionX.ts} +0 -0
  119. /package/src/{OrderX/OrderX.ts → OrderX.ts} +0 -0
  120. /package/src/{PredicateX/PredicateX.ts → PredicateX.ts} +0 -0
  121. /package/src/{PromiseX/PromiseX.ts → PromiseX.ts} +0 -0
  122. /package/src/{ResultX/ResultX.ts → ResultX.ts} +0 -0
  123. /package/src/{SchemaX/SchemaX.ts → SchemaX.ts} +0 -0
  124. /package/src/{SetX/SetX.ts → SetX.ts} +0 -0
  125. /package/src/{StringX/StringX.ts → StringX.ts} +0 -0
  126. /package/src/{StructX/StructX.ts → StructX.ts} +0 -0
  127. /package/src/{WarnResult/WarnResult.ts → WarnResult.ts} +0 -0
package/dist/index.d.ts CHANGED
@@ -1,3772 +1,22 @@
1
- import { Data, Effect, Option, Equivalence, Array, Predicate, Order, DateTime, Duration, Cause, Schema, Result } from 'effect';
2
- import * as effect_Unify from 'effect/Unify';
3
-
4
- /**
5
- * A result that may come with a success value and may come with warnings — both
6
- * are optional, but never both absent.
7
- *
8
- * Where `Result<A, E>` models an exclusive choice (success _or_ failure),
9
- * `WarnResult` is an "inclusive or": the success value and the warnings can each
10
- * be present independently. It is a tagged enum with three constructors:
11
- * `SuccessOnly` (only a `success` value), `WarningsOnly` (only `warnings`), and
12
- * `SuccessWithWarnings` (both). Reach for it when an operation can succeed, warn,
13
- * or do both at once — e.g. a parse that yields a value _and_ a list of warnings,
14
- * or that only produces warnings.
15
- *
16
- * @example
17
- * ```ts
18
- * import { WarnResult } from "@nunofyobiz/effect-extras"
19
- *
20
- * const both: WarnResult.WarnResult<string, number> =
21
- * WarnResult.SuccessWithWarnings({
22
- * warnings: "rounded down",
23
- * success: 1
24
- * })
25
- *
26
- * assert.deepStrictEqual(both._tag, "SuccessWithWarnings")
27
- * ```
28
- *
29
- * @category models
30
- * @since 0.0.0
31
- */
32
- type WarnResult<W, A> = Data.TaggedEnum<{
33
- WarningsOnly: {
34
- readonly warnings: W;
35
- };
36
- SuccessOnly: {
37
- readonly success: A;
38
- };
39
- SuccessWithWarnings: {
40
- readonly warnings: W;
41
- readonly success: A;
42
- };
43
- }>;
44
- /**
45
- * The `WarningsOnly` member of `WarnResult` — a result that carries only
46
- * `warnings` and no `success` value.
47
- *
48
- * @example
49
- * ```ts
50
- * import { WarnResult } from "@nunofyobiz/effect-extras"
51
- *
52
- * const value: WarnResult.WarningsOnly<string> = WarnResult.WarningsOnly({
53
- * warnings: "skipped 2 rows"
54
- * })
55
- *
56
- * assert.deepStrictEqual(value.warnings, "skipped 2 rows")
57
- * ```
58
- *
59
- * @category models
60
- * @since 0.0.0
61
- */
62
- type WarningsOnly<W> = WarnResult<W, never> & {
63
- _tag: "WarningsOnly";
64
- };
65
- /**
66
- * Constructs a `WarningsOnly` — a `WarnResult` that carries only `warnings`.
67
- *
68
- * @example
69
- * ```ts
70
- * import { WarnResult } from "@nunofyobiz/effect-extras"
71
- *
72
- * const value = WarnResult.WarningsOnly({ warnings: "skipped 2 rows" })
73
- *
74
- * assert.deepStrictEqual(value._tag, "WarningsOnly")
75
- * assert.deepStrictEqual(value.warnings, "skipped 2 rows")
76
- * ```
77
- *
78
- * @category constructors
79
- * @since 0.0.0
80
- */
81
- declare const WarningsOnly: <A, B>(args: {
82
- readonly warnings: A;
83
- }) => {
84
- readonly _tag: "WarningsOnly";
85
- readonly warnings: A;
86
- };
87
- /**
88
- * The `SuccessOnly` member of `WarnResult` — a result that carries only a
89
- * `success` value and no `warnings`.
90
- *
91
- * @example
92
- * ```ts
93
- * import { WarnResult } from "@nunofyobiz/effect-extras"
94
- *
95
- * const value: WarnResult.SuccessOnly<number> = WarnResult.SuccessOnly({
96
- * success: 1
97
- * })
98
- *
99
- * assert.deepStrictEqual(value.success, 1)
100
- * ```
101
- *
102
- * @category models
103
- * @since 0.0.0
104
- */
105
- type SuccessOnly<A> = WarnResult<never, A> & {
106
- _tag: "SuccessOnly";
107
- };
108
- /**
109
- * Constructs a `SuccessOnly` — a `WarnResult` that carries only a `success` value.
110
- *
111
- * @example
112
- * ```ts
113
- * import { WarnResult } from "@nunofyobiz/effect-extras"
114
- *
115
- * const value = WarnResult.SuccessOnly({ success: 1 })
116
- *
117
- * assert.deepStrictEqual(value._tag, "SuccessOnly")
118
- * assert.deepStrictEqual(value.success, 1)
119
- * ```
120
- *
121
- * @category constructors
122
- * @since 0.0.0
123
- */
124
- declare const SuccessOnly: <A, B>(args: {
125
- readonly success: B;
126
- }) => {
127
- readonly _tag: "SuccessOnly";
128
- readonly success: B;
129
- };
130
- /**
131
- * The `SuccessWithWarnings` member of `WarnResult` — a result that carries both a
132
- * `success` value and `warnings`.
133
- *
134
- * @example
135
- * ```ts
136
- * import { WarnResult } from "@nunofyobiz/effect-extras"
137
- *
138
- * const value: WarnResult.SuccessWithWarnings<string, number> =
139
- * WarnResult.SuccessWithWarnings({
140
- * warnings: "rounded down",
141
- * success: 1
142
- * })
143
- *
144
- * assert.deepStrictEqual(value, {
145
- * _tag: "SuccessWithWarnings",
146
- * warnings: "rounded down",
147
- * success: 1
148
- * })
149
- * ```
150
- *
151
- * @category models
152
- * @since 0.0.0
153
- */
154
- type SuccessWithWarnings<W, A> = WarnResult<W, A> & {
155
- _tag: "SuccessWithWarnings";
156
- };
157
- /**
158
- * Constructs a `SuccessWithWarnings` — a `WarnResult` that carries both a
159
- * `success` value and `warnings`.
160
- *
161
- * @example
162
- * ```ts
163
- * import { WarnResult } from "@nunofyobiz/effect-extras"
164
- *
165
- * const value = WarnResult.SuccessWithWarnings({
166
- * warnings: "rounded down",
167
- * success: 1
168
- * })
169
- *
170
- * assert.deepStrictEqual(value._tag, "SuccessWithWarnings")
171
- * assert.deepStrictEqual(value.warnings, "rounded down")
172
- * assert.deepStrictEqual(value.success, 1)
173
- * ```
174
- *
175
- * @category constructors
176
- * @since 0.0.0
177
- */
178
- declare const SuccessWithWarnings: <A, B>(args: {
179
- readonly warnings: A;
180
- readonly success: B;
181
- }) => {
182
- readonly _tag: "SuccessWithWarnings";
183
- readonly warnings: A;
184
- readonly success: B;
185
- };
186
- /**
187
- * Builds per-tag refinements for `WarnResult`. `is("WarningsOnly")` is a type
188
- * guard that narrows a `WarnResult` to its `WarningsOnly` member, and likewise for
189
- * `"SuccessOnly"` and `"SuccessWithWarnings"`.
190
- *
191
- * @example
192
- * ```ts
193
- * import { WarnResult } from "@nunofyobiz/effect-extras"
194
- *
195
- * assert.deepStrictEqual(
196
- * WarnResult.is("WarningsOnly")(WarnResult.WarningsOnly({ warnings: "w" })),
197
- * true
198
- * )
199
- * assert.deepStrictEqual(
200
- * WarnResult.is("WarningsOnly")(WarnResult.SuccessOnly({ success: 1 })),
201
- * false
202
- * )
203
- * ```
204
- *
205
- * @category guards
206
- * @since 0.0.0
207
- */
208
- declare const is: <Tag extends "WarningsOnly" | "SuccessOnly" | "SuccessWithWarnings">(tag: Tag) => {
209
- <T extends {
210
- readonly _tag: "WarningsOnly";
211
- readonly warnings: any;
212
- } | {
213
- readonly _tag: "SuccessOnly";
214
- readonly success: any;
215
- } | {
216
- readonly _tag: "SuccessWithWarnings";
217
- readonly warnings: any;
218
- readonly success: any;
219
- }>(u: T): u is T & {
220
- readonly _tag: Tag;
221
- };
222
- (u: unknown): u is Extract<{
223
- readonly _tag: "WarningsOnly";
224
- readonly warnings: unknown;
225
- }, {
226
- readonly _tag: Tag;
227
- }> | Extract<{
228
- readonly _tag: "SuccessOnly";
229
- readonly success: unknown;
230
- }, {
231
- readonly _tag: Tag;
232
- }> | Extract<{
233
- readonly _tag: "SuccessWithWarnings";
234
- readonly warnings: unknown;
235
- readonly success: unknown;
236
- }, {
237
- readonly _tag: Tag;
238
- }>;
239
- };
240
- /**
241
- * Folds a `WarnResult` over its three tags. Provide a handler for `WarningsOnly`,
242
- * `SuccessOnly`, and `SuccessWithWarnings` and `match` returns a function from a
243
- * `WarnResult` to the handlers' common result type.
244
- *
245
- * @example
246
- * ```ts
247
- * import { WarnResult } from "@nunofyobiz/effect-extras"
248
- *
249
- * const describe = WarnResult.match({
250
- * WarningsOnly: ({ warnings }) => `warnings ${warnings}`,
251
- * SuccessOnly: ({ success }) => `success ${success}`,
252
- * SuccessWithWarnings: ({ warnings, success }) => `both ${warnings}/${success}`
253
- * })
254
- *
255
- * assert.deepStrictEqual(
256
- * describe(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })),
257
- * "both w/1"
258
- * )
259
- * ```
260
- *
261
- * @category pattern matching
262
- * @since 0.0.0
263
- */
264
- declare const match$1: {
265
- <A, B, C, D, Cases extends {
266
- readonly WarningsOnly: (args: {
267
- readonly _tag: "WarningsOnly";
268
- readonly warnings: A;
269
- }) => any;
270
- readonly SuccessOnly: (args: {
271
- readonly _tag: "SuccessOnly";
272
- readonly success: B;
273
- }) => any;
274
- readonly SuccessWithWarnings: (args: {
275
- readonly _tag: "SuccessWithWarnings";
276
- readonly warnings: A;
277
- readonly success: B;
278
- }) => any;
279
- }>(cases: Cases): (self: {
280
- readonly _tag: "WarningsOnly";
281
- readonly warnings: A;
282
- } | {
283
- readonly _tag: "SuccessOnly";
284
- readonly success: B;
285
- } | {
286
- readonly _tag: "SuccessWithWarnings";
287
- readonly warnings: A;
288
- readonly success: B;
289
- }) => effect_Unify.Unify<ReturnType<Cases["WarningsOnly" | "SuccessOnly" | "SuccessWithWarnings"]>>;
290
- <A, B, C, D, Cases extends {
291
- readonly WarningsOnly: (args: {
292
- readonly _tag: "WarningsOnly";
293
- readonly warnings: A;
294
- }) => any;
295
- readonly SuccessOnly: (args: {
296
- readonly _tag: "SuccessOnly";
297
- readonly success: B;
298
- }) => any;
299
- readonly SuccessWithWarnings: (args: {
300
- readonly _tag: "SuccessWithWarnings";
301
- readonly warnings: A;
302
- readonly success: B;
303
- }) => any;
304
- }>(self: {
305
- readonly _tag: "WarningsOnly";
306
- readonly warnings: A;
307
- } | {
308
- readonly _tag: "SuccessOnly";
309
- readonly success: B;
310
- } | {
311
- readonly _tag: "SuccessWithWarnings";
312
- readonly warnings: A;
313
- readonly success: B;
314
- }, cases: Cases): effect_Unify.Unify<ReturnType<Cases["WarningsOnly" | "SuccessOnly" | "SuccessWithWarnings"]>>;
315
- };
316
- /**
317
- * Any `WarnResult` that is guaranteed to carry `warnings` — either `WarningsOnly`
318
- * or `SuccessWithWarnings`.
319
- *
320
- * @example
321
- * ```ts
322
- * import { WarnResult } from "@nunofyobiz/effect-extras"
323
- *
324
- * const value: WarnResult.WithWarnings<string, number> = WarnResult.WarningsOnly({
325
- * warnings: "skipped 2 rows"
326
- * })
327
- *
328
- * assert.deepStrictEqual(value.warnings, "skipped 2 rows")
329
- * ```
330
- *
331
- * @category models
332
- * @since 0.0.0
333
- */
334
- type WithWarnings<W, A> = WarningsOnly<W> | SuccessWithWarnings<W, A>;
335
- /**
336
- * Builds a `WarnResult` known to carry `warnings`, choosing `SuccessWithWarnings`
337
- * when a `success` value is present and `WarningsOnly` otherwise.
338
- *
339
- * Use it when the `warnings` are mandatory and the `success` value is an optional
340
- * companion: pass an absent (`null`/`undefined`) `success` to get a
341
- * `WarningsOnly`, or a present one to get a `SuccessWithWarnings`. The return type
342
- * `WithWarnings<W, A>` reflects that `warnings` are always present.
343
- *
344
- * @example
345
- * ```ts
346
- * import { WarnResult } from "@nunofyobiz/effect-extras"
347
- *
348
- * assert.deepStrictEqual(
349
- * WarnResult.WithWarnings({ warnings: "w", success: 1 }),
350
- * WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })
351
- * )
352
- *
353
- * assert.deepStrictEqual(
354
- * WarnResult.WithWarnings({ warnings: "w" }),
355
- * WarnResult.WarningsOnly({ warnings: "w" })
356
- * )
357
- * ```
358
- *
359
- * @category constructors
360
- * @since 0.0.0
361
- */
362
- declare const WithWarnings: <W, A>({ warnings, success, }: {
363
- warnings: W;
364
- success?: A | undefined;
365
- }) => WithWarnings<W, A>;
366
- /**
367
- * Any `WarnResult` that is guaranteed to carry a `success` value — either
368
- * `SuccessOnly` or `SuccessWithWarnings`.
369
- *
370
- * @example
371
- * ```ts
372
- * import { WarnResult } from "@nunofyobiz/effect-extras"
373
- *
374
- * const value: WarnResult.WithSuccess<string, number> = WarnResult.SuccessOnly({
375
- * success: 1
376
- * })
377
- *
378
- * assert.deepStrictEqual(value.success, 1)
379
- * ```
380
- *
381
- * @category models
382
- * @since 0.0.0
383
- */
384
- type WithSuccess<W, A> = SuccessOnly<A> | SuccessWithWarnings<W, A>;
385
- /**
386
- * Builds a `WarnResult` known to carry a `success` value, choosing
387
- * `SuccessWithWarnings` when `warnings` are present and `SuccessOnly` otherwise.
388
- *
389
- * The mirror of `WithWarnings`: the `success` value is mandatory and the
390
- * `warnings` are an optional companion. Pass absent (`null`/`undefined`)
391
- * `warnings` to get a `SuccessOnly`, or present ones to get a
392
- * `SuccessWithWarnings`. The return type `WithSuccess<W, A>` reflects that a
393
- * `success` value is always present.
394
- *
395
- * @example
396
- * ```ts
397
- * import { WarnResult } from "@nunofyobiz/effect-extras"
398
- *
399
- * assert.deepStrictEqual(
400
- * WarnResult.WithSuccess({ warnings: "w", success: 1 }),
401
- * WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })
402
- * )
403
- *
404
- * assert.deepStrictEqual(
405
- * WarnResult.WithSuccess({ success: 1 }),
406
- * WarnResult.SuccessOnly({ success: 1 })
407
- * )
408
- * ```
409
- *
410
- * @category constructors
411
- * @since 0.0.0
412
- */
413
- declare const WithSuccess: <W, A>({ warnings, success, }: {
414
- warnings?: W | undefined;
415
- success: A;
416
- }) => WithSuccess<W, A>;
417
- /**
418
- * Builds a `WarnResult` from a pair of possibly-nullish inputs, wrapping the
419
- * result in an `Option` so the all-absent case is expressible.
420
- *
421
- * Returns `Option.some(SuccessWithWarnings)` when both are present,
422
- * `Option.some(WarningsOnly)` or `Option.some(SuccessOnly)` when exactly one is
423
- * present, and `Option.none()` when both are nullish. Use it as the total entry
424
- * point for turning an optional success value and optional warnings into a
425
- * `WarnResult`.
426
- *
427
- * @example
428
- * ```ts
429
- * import { WarnResult } from "@nunofyobiz/effect-extras"
430
- * import { Option } from "effect"
431
- *
432
- * assert.deepStrictEqual(
433
- * WarnResult.optionFromNullables({ warnings: "w", success: 1 }),
434
- * Option.some(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 }))
435
- * )
436
- *
437
- * assert.deepStrictEqual(
438
- * WarnResult.optionFromNullables({ warnings: "w", success: null }),
439
- * Option.some(WarnResult.WarningsOnly({ warnings: "w" }))
440
- * )
441
- *
442
- * assert.deepStrictEqual(
443
- * WarnResult.optionFromNullables({ warnings: null, success: undefined }),
444
- * Option.none()
445
- * )
446
- * ```
447
- *
448
- * @category constructors
449
- * @since 0.0.0
450
- */
451
- declare const optionFromNullables: <W, A>({ warnings, success, }: {
452
- warnings?: W | null | undefined;
453
- success?: A | null | undefined;
454
- }) => Option.Option<WarnResult<W, A>>;
455
- /**
456
- * Builds a `WarnResult` from a pair of possibly-nullish inputs, falling back to
457
- * the `orElse` thunk when both are absent.
458
- *
459
- * The non-optional companion to `optionFromNullables`: it unwraps the same logic
460
- * but resolves the all-absent case with `orElse` instead of an `Option`. The
461
- * default `orElse` throws, so omit it only when at least one side is guaranteed
462
- * present.
463
- *
464
- * @example
465
- * ```ts
466
- * import { WarnResult } from "@nunofyobiz/effect-extras"
467
- *
468
- * assert.deepStrictEqual(
469
- * WarnResult.fromNullables({ warnings: "w", success: 1 }),
470
- * WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })
471
- * )
472
- *
473
- * // Both absent — fall back via orElse instead of throwing
474
- * assert.deepStrictEqual(
475
- * WarnResult.fromNullables({
476
- * warnings: null,
477
- * success: null,
478
- * orElse: () => WarnResult.WarningsOnly({ warnings: "none" })
479
- * }),
480
- * WarnResult.WarningsOnly({ warnings: "none" })
481
- * )
482
- * ```
483
- *
484
- * @category constructors
485
- * @since 0.0.0
486
- */
487
- declare const fromNullables: <W, A>({ warnings, success, orElse, }: {
488
- warnings?: W | null | undefined;
489
- success?: A | null | undefined;
490
- orElse?: () => WarnResult<W, A>;
491
- }) => WarnResult<W, A>;
492
- /**
493
- * Folds a `WarnResult` from the warnings' perspective, collapsing the three tags
494
- * into two handlers.
495
- *
496
- * Both `WarningsOnly` and `SuccessWithWarnings` carry `warnings`, so they route to
497
- * the `Warnings` handler; only `SuccessOnly` lacks `warnings` and routes to
498
- * `SuccessOnly`. Use it when you care about the `warnings` and treat the
499
- * success-only case as the exception.
500
- *
501
- * @example
502
- * ```ts
503
- * import { WarnResult } from "@nunofyobiz/effect-extras"
504
- *
505
- * const onWarnings = WarnResult.matchWarnings({
506
- * Warnings: (warnings: string) => `warnings ${warnings}`,
507
- * SuccessOnly: (success: number) => `success ${success}`
508
- * })
509
- *
510
- * assert.deepStrictEqual(
511
- * onWarnings(WarnResult.WarningsOnly({ warnings: "w" })),
512
- * "warnings w"
513
- * )
514
- * assert.deepStrictEqual(
515
- * onWarnings(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })),
516
- * "warnings w"
517
- * )
518
- * assert.deepStrictEqual(
519
- * onWarnings(WarnResult.SuccessOnly({ success: 1 })),
520
- * "success 1"
521
- * )
522
- * ```
523
- *
524
- * @category pattern matching
525
- * @since 0.0.0
526
- */
527
- declare const matchWarnings: <W, A, Z>({ Warnings, SuccessOnly, }: {
528
- Warnings: (warnings: W) => Z;
529
- SuccessOnly: (success: A) => Z;
530
- }) => (warnResult: WarnResult<W, A>) => Z;
531
- /**
532
- * Folds a `WarnResult` from the success value's perspective, collapsing the three
533
- * tags into two handlers.
534
- *
535
- * The mirror of `matchWarnings`: both `SuccessOnly` and `SuccessWithWarnings`
536
- * carry a `success` value, so they route to the `Success` handler; only
537
- * `WarningsOnly` lacks a `success` value and routes to `WarningsOnly`. Use it when
538
- * you care about the `success` value and treat the warnings-only case as the
539
- * exception.
540
- *
541
- * @example
542
- * ```ts
543
- * import { WarnResult } from "@nunofyobiz/effect-extras"
544
- *
545
- * const onSuccess = WarnResult.matchSuccess({
546
- * WarningsOnly: (warnings: string) => `warnings ${warnings}`,
547
- * Success: (success: number) => `success ${success}`
548
- * })
549
- *
550
- * assert.deepStrictEqual(
551
- * onSuccess(WarnResult.SuccessOnly({ success: 1 })),
552
- * "success 1"
553
- * )
554
- * assert.deepStrictEqual(
555
- * onSuccess(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })),
556
- * "success 1"
557
- * )
558
- * assert.deepStrictEqual(
559
- * onSuccess(WarnResult.WarningsOnly({ warnings: "w" })),
560
- * "warnings w"
561
- * )
562
- * ```
563
- *
564
- * @category pattern matching
565
- * @since 0.0.0
566
- */
567
- declare const matchSuccess: <W, A, Z>({ WarningsOnly, Success, }: {
568
- WarningsOnly: (warnings: W) => Z;
569
- Success: (success: A) => Z;
570
- }) => (warnResult: WarnResult<W, A>) => Z;
571
- /**
572
- * Completes a `WarnResult` into a guaranteed `SuccessWithWarnings` by filling
573
- * whichever side is missing from the matching `orElse` thunk.
574
- *
575
- * A `SuccessWithWarnings` passes through unchanged; a `WarningsOnly` gains a
576
- * `success` value from `orElseSuccess`; a `SuccessOnly` gains `warnings` from
577
- * `orElseWarnings`. Use it to normalise a partial `WarnResult` into the
578
- * both-present shape before reading both sides.
579
- *
580
- * @example
581
- * ```ts
582
- * import { WarnResult } from "@nunofyobiz/effect-extras"
583
- *
584
- * const fill = WarnResult.orElse({
585
- * orElseWarnings: () => "no warnings",
586
- * orElseSuccess: () => 0
587
- * })
588
- *
589
- * assert.deepStrictEqual(
590
- * fill(WarnResult.WarningsOnly({ warnings: "w" })),
591
- * WarnResult.SuccessWithWarnings({ warnings: "w", success: 0 })
592
- * )
593
- * assert.deepStrictEqual(
594
- * fill(WarnResult.SuccessOnly({ success: 1 })),
595
- * WarnResult.SuccessWithWarnings({ warnings: "no warnings", success: 1 })
596
- * )
597
- * ```
598
- *
599
- * @category getters
600
- * @since 0.0.0
601
- */
602
- declare const orElse: <W2, A2>({ orElseWarnings, orElseSuccess, }: {
603
- orElseWarnings: () => W2;
604
- orElseSuccess: () => A2;
605
- }) => (<W, A>(warnResult: WarnResult<W, A>) => SuccessWithWarnings<W | W2, A | A2>);
606
- /**
607
- * Completes a `WarnResult` into a `SuccessWithWarnings` whose missing side is
608
- * filled with `undefined`.
609
- *
610
- * A specialisation of `orElse` that supplies `undefined` for whichever side is
611
- * absent, so the result always exposes both `warnings` and `success` keys (each
612
- * possibly `undefined`). Use it when you want to destructure both sides without
613
- * branching on the tag.
614
- *
615
- * @example
616
- * ```ts
617
- * import { WarnResult } from "@nunofyobiz/effect-extras"
618
- *
619
- * assert.deepStrictEqual(
620
- * WarnResult.orUndefined(WarnResult.WarningsOnly({ warnings: "w" })),
621
- * WarnResult.SuccessWithWarnings({ warnings: "w", success: undefined })
622
- * )
623
- * assert.deepStrictEqual(
624
- * WarnResult.orUndefined(WarnResult.SuccessOnly({ success: 1 })),
625
- * WarnResult.SuccessWithWarnings({ warnings: undefined, success: 1 })
626
- * )
627
- * ```
628
- *
629
- * @category getters
630
- * @since 0.0.0
631
- */
632
- declare const orUndefined: <W, A>(warnResult: {
633
- readonly _tag: "WarningsOnly";
634
- readonly warnings: W;
635
- } | {
636
- readonly _tag: "SuccessOnly";
637
- readonly success: A;
638
- } | {
639
- readonly _tag: "SuccessWithWarnings";
640
- readonly warnings: W;
641
- readonly success: A;
642
- }) => {
643
- readonly _tag: "SuccessWithWarnings";
644
- readonly warnings: W | undefined;
645
- readonly success: A | undefined;
646
- } & {
647
- _tag: "SuccessWithWarnings";
648
- };
649
- /**
650
- * Extracts the `warnings` of a `WarnResult`, falling back to `orElseReturn` when
651
- * no `warnings` are present.
652
- *
653
- * `WarningsOnly` and `SuccessWithWarnings` return their `warnings`; `SuccessOnly`
654
- * returns the result of `orElseReturn`. Use it to read the warnings with a default
655
- * in one step.
656
- *
657
- * @example
658
- * ```ts
659
- * import { WarnResult } from "@nunofyobiz/effect-extras"
660
- *
661
- * const warningsOrNone = WarnResult.warningsOrElse(() => "no warnings")
662
- *
663
- * assert.deepStrictEqual(
664
- * warningsOrNone(WarnResult.WarningsOnly({ warnings: "w" })),
665
- * "w"
666
- * )
667
- * assert.deepStrictEqual(
668
- * warningsOrNone(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })),
669
- * "w"
670
- * )
671
- * assert.deepStrictEqual(
672
- * warningsOrNone(WarnResult.SuccessOnly({ success: 1 })),
673
- * "no warnings"
674
- * )
675
- * ```
676
- *
677
- * @category getters
678
- * @since 0.0.0
679
- */
680
- declare const warningsOrElse: <Z>(orElseReturn: () => Z) => <W, A>(warnResult: WarnResult<W, A>) => W | Z;
681
- /**
682
- * Extracts the `warnings` of a `WarnResult`, returning `undefined` when no
683
- * `warnings` are present.
684
- *
685
- * A specialisation of `warningsOrElse` whose fallback is `undefined`:
686
- * `WarningsOnly` and `SuccessWithWarnings` yield their `warnings`, while
687
- * `SuccessOnly` yields `undefined`.
688
- *
689
- * @example
690
- * ```ts
691
- * import { WarnResult } from "@nunofyobiz/effect-extras"
692
- *
693
- * assert.deepStrictEqual(
694
- * WarnResult.warningsOrUndefined(WarnResult.WarningsOnly({ warnings: "w" })),
695
- * "w"
696
- * )
697
- * assert.deepStrictEqual(
698
- * WarnResult.warningsOrUndefined(WarnResult.SuccessOnly({ success: 1 })),
699
- * undefined
700
- * )
701
- * ```
702
- *
703
- * @category getters
704
- * @since 0.0.0
705
- */
706
- declare const warningsOrUndefined: <W, A>(warnResult: {
707
- readonly _tag: "WarningsOnly";
708
- readonly warnings: W;
709
- } | {
710
- readonly _tag: "SuccessOnly";
711
- readonly success: A;
712
- } | {
713
- readonly _tag: "SuccessWithWarnings";
714
- readonly warnings: W;
715
- readonly success: A;
716
- }) => W | undefined;
717
- /**
718
- * Extracts the `success` value of a `WarnResult`, falling back to `orElseReturn`
719
- * when no `success` value is present.
720
- *
721
- * The mirror of `warningsOrElse`: `SuccessOnly` and `SuccessWithWarnings` return
722
- * their `success` value; `WarningsOnly` returns the result of `orElseReturn`.
723
- *
724
- * @example
725
- * ```ts
726
- * import { WarnResult } from "@nunofyobiz/effect-extras"
727
- *
728
- * const successOrZero = WarnResult.successOrElse(() => 0)
729
- *
730
- * assert.deepStrictEqual(
731
- * successOrZero(WarnResult.SuccessOnly({ success: 1 })),
732
- * 1
733
- * )
734
- * assert.deepStrictEqual(
735
- * successOrZero(WarnResult.WarningsOnly({ warnings: "w" })),
736
- * 0
737
- * )
738
- * ```
739
- *
740
- * @category getters
741
- * @since 0.0.0
742
- */
743
- declare const successOrElse: <Z>(orElseReturn: () => Z) => <W, A>(warnResult: WarnResult<W, A>) => A | Z;
744
- /**
745
- * Extracts the `success` value of a `WarnResult`, returning `undefined` when no
746
- * `success` value is present.
747
- *
748
- * A specialisation of `successOrElse` whose fallback is `undefined`: `SuccessOnly`
749
- * and `SuccessWithWarnings` yield their `success` value, while `WarningsOnly`
750
- * yields `undefined`.
751
- *
752
- * @example
753
- * ```ts
754
- * import { WarnResult } from "@nunofyobiz/effect-extras"
755
- *
756
- * assert.deepStrictEqual(
757
- * WarnResult.successOrUndefined(WarnResult.SuccessOnly({ success: 1 })),
758
- * 1
759
- * )
760
- * assert.deepStrictEqual(
761
- * WarnResult.successOrUndefined(WarnResult.WarningsOnly({ warnings: "w" })),
762
- * undefined
763
- * )
764
- * ```
765
- *
766
- * @category getters
767
- * @since 0.0.0
768
- */
769
- declare const successOrUndefined: <W, A>(warnResult: {
770
- readonly _tag: "WarningsOnly";
771
- readonly warnings: W;
772
- } | {
773
- readonly _tag: "SuccessOnly";
774
- readonly success: A;
775
- } | {
776
- readonly _tag: "SuccessWithWarnings";
777
- readonly warnings: W;
778
- readonly success: A;
779
- }) => A | undefined;
780
- /**
781
- * Extracts the `success` value of a `WarnResult` as an `Option`.
782
- *
783
- * `SuccessOnly` and `SuccessWithWarnings` yield `Option.some(success)`;
784
- * `WarningsOnly` yields `Option.none()`. Use it when you want to chain the success
785
- * value through `Option` combinators rather than fall back to a default eagerly.
786
- *
787
- * @example
788
- * ```ts
789
- * import { WarnResult } from "@nunofyobiz/effect-extras"
790
- * import { Option } from "effect"
791
- *
792
- * assert.deepStrictEqual(
793
- * WarnResult.successOption(WarnResult.SuccessOnly({ success: 1 })),
794
- * Option.some(1)
795
- * )
796
- * assert.deepStrictEqual(
797
- * WarnResult.successOption(WarnResult.WarningsOnly({ warnings: "w" })),
798
- * Option.none()
799
- * )
800
- * ```
801
- *
802
- * @category getters
803
- * @since 0.0.0
804
- */
805
- declare const successOption: <W, A>(warnResult: WarnResult<W, A>) => Option.Option<A>;
806
- /**
807
- * Extracts the `warnings` of a `WarnResult` as an `Option`.
808
- *
809
- * The mirror of `successOption`: `WarningsOnly` and `SuccessWithWarnings` yield
810
- * `Option.some(warnings)`, while `SuccessOnly` yields `Option.none()`.
811
- *
812
- * @example
813
- * ```ts
814
- * import { WarnResult } from "@nunofyobiz/effect-extras"
815
- * import { Option } from "effect"
816
- *
817
- * assert.deepStrictEqual(
818
- * WarnResult.warningsOption(WarnResult.WarningsOnly({ warnings: "w" })),
819
- * Option.some("w")
820
- * )
821
- * assert.deepStrictEqual(
822
- * WarnResult.warningsOption(WarnResult.SuccessOnly({ success: 1 })),
823
- * Option.none()
824
- * )
825
- * ```
826
- *
827
- * @category getters
828
- * @since 0.0.0
829
- */
830
- declare const warningsOption: <W, A>(warnResult: WarnResult<W, A>) => Option.Option<W>;
831
- /**
832
- * Transforms both sides of a `WarnResult`, applying `mapWarnings` to any
833
- * `warnings` and `mapSuccess` to any `success` value.
834
- *
835
- * Each constructor is rebuilt with its mapped contents, so `WarningsOnly` maps
836
- * only the warnings, `SuccessOnly` only the success value, and
837
- * `SuccessWithWarnings` both. The tag is preserved. Use it as the bifunctor map
838
- * over `WarnResult`.
839
- *
840
- * @example
841
- * ```ts
842
- * import { WarnResult } from "@nunofyobiz/effect-extras"
843
- *
844
- * const both = WarnResult.mapBoth({
845
- * mapWarnings: (warnings: string) => warnings.toUpperCase(),
846
- * mapSuccess: (success: number) => success + 1
847
- * })
848
- *
849
- * assert.deepStrictEqual(
850
- * both(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })),
851
- * WarnResult.SuccessWithWarnings({ warnings: "W", success: 2 })
852
- * )
853
- * assert.deepStrictEqual(
854
- * both(WarnResult.WarningsOnly({ warnings: "w" })),
855
- * WarnResult.WarningsOnly({ warnings: "W" })
856
- * )
857
- * ```
858
- *
859
- * @category mapping
860
- * @since 0.0.0
861
- */
862
- declare const mapBoth: <W1, A1, W2, A2>({ mapWarnings, mapSuccess, }: {
863
- mapWarnings: (warnings: W1) => W2;
864
- mapSuccess: (success: A1) => A2;
865
- }) => ((warnResult: WarnResult<W1, A1>) => WarnResult<W2, A2>);
866
- /**
867
- * Effectful `mapBoth`: transforms each present side through an `Effect`,
868
- * reassembling the results into a `WarnResult` inside an `Effect`.
869
- *
870
- * For `SuccessWithWarnings` both effects run via `Effect.all` and their results
871
- * are combined; `WarningsOnly`/`SuccessOnly` run only the relevant effect. Errors
872
- * and requirements from both mappers are unioned into the result type. Use it when
873
- * mapping a `WarnResult`'s sides requires effects (validation, IO).
874
- *
875
- * @example
876
- * ```ts
877
- * import { WarnResult } from "@nunofyobiz/effect-extras"
878
- * import { Effect } from "effect"
879
- *
880
- * const both = WarnResult.mapBothEffect({
881
- * mapWarnings: (warnings: string) => Effect.succeed(warnings.toUpperCase()),
882
- * mapSuccess: (success: number) => Effect.succeed(success + 1)
883
- * })
884
- *
885
- * assert.deepStrictEqual(
886
- * Effect.runSync(
887
- * both(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 }))
888
- * ),
889
- * WarnResult.SuccessWithWarnings({ warnings: "W", success: 2 })
890
- * )
891
- * ```
892
- *
893
- * @category sequencing
894
- * @since 0.0.0
895
- */
896
- declare const mapBothEffect: <W1, A1, W2, A2, EW, EA, RW, RA>({ mapWarnings, mapSuccess, }: {
897
- mapWarnings: (warnings: W1) => Effect.Effect<W2, EW, RW>;
898
- mapSuccess: (success: A1) => Effect.Effect<A2, EA, RA>;
899
- }) => ((warnResult: WarnResult<W1, A1>) => Effect.Effect<WarnResult<W2, A2>, EW | EA, RW | RA>);
900
- /**
901
- * Transforms the `warnings` of a `WarnResult`, leaving any `success` value
902
- * untouched.
903
- *
904
- * A specialisation of `mapBoth` with the success mapper set to `identity`:
905
- * `WarningsOnly` and `SuccessWithWarnings` have their `warnings` mapped, while
906
- * `SuccessOnly` passes through unchanged.
907
- *
908
- * @example
909
- * ```ts
910
- * import { WarnResult } from "@nunofyobiz/effect-extras"
911
- *
912
- * const shout = WarnResult.mapWarnings((warnings: string) =>
913
- * warnings.toUpperCase()
914
- * )
915
- *
916
- * assert.deepStrictEqual(
917
- * shout(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })),
918
- * WarnResult.SuccessWithWarnings({ warnings: "W", success: 1 })
919
- * )
920
- * assert.deepStrictEqual(
921
- * shout(WarnResult.SuccessOnly({ success: 1 })),
922
- * WarnResult.SuccessOnly({ success: 1 })
923
- * )
924
- * ```
925
- *
926
- * @category mapping
927
- * @since 0.0.0
928
- */
929
- declare const mapWarnings: <W1, W2>(mapWarnings: (warnings: W1) => W2) => (<A>(warnResult: WarnResult<W1, A>) => WarnResult<W2, A>);
930
- /**
931
- * Chains the `warnings` of a `WarnResult` into a new `WarnResult`, flattening the
932
- * result.
933
- *
934
- * Whenever `warnings` are present (`WarningsOnly` or `SuccessWithWarnings`) they
935
- * are passed to `mapWarnings`, whose returned `WarnResult` replaces the original;
936
- * `SuccessOnly` passes through unchanged. Use it to sequence warnings-driven
937
- * computations that themselves produce a `WarnResult`.
938
- *
939
- * @example
940
- * ```ts
941
- * import { WarnResult } from "@nunofyobiz/effect-extras"
942
- *
943
- * const chain = WarnResult.flatMapWarnings((warnings: string) =>
944
- * warnings.length > 0
945
- * ? WarnResult.WarningsOnly({ warnings: warnings.toUpperCase() })
946
- * : WarnResult.SuccessOnly({ success: 0 })
947
- * )
948
- *
949
- * assert.deepStrictEqual(
950
- * chain(WarnResult.WarningsOnly({ warnings: "w" })),
951
- * WarnResult.WarningsOnly({ warnings: "W" })
952
- * )
953
- * assert.deepStrictEqual(
954
- * chain(WarnResult.SuccessOnly({ success: 1 })),
955
- * WarnResult.SuccessOnly({ success: 1 })
956
- * )
957
- * ```
958
- *
959
- * @category sequencing
960
- * @since 0.0.0
961
- */
962
- declare const flatMapWarnings: <W1, W2, A2>(mapWarnings: (warnings: W1) => WarnResult<W2, A2>) => (<A1>(warnResult: WarnResult<W1, A1>) => WarnResult<W2, A1 | A2>);
963
- /**
964
- * Effectful `mapWarnings`: transforms the `warnings` of a `WarnResult` through an
965
- * `Effect`, leaving any `success` value untouched.
966
- *
967
- * A specialisation of `mapBothEffect` with the success mapper set to
968
- * `Effect.succeed`: the `warnings` (when present) are mapped effectfully and the
969
- * `success` value is carried through unchanged.
970
- *
971
- * @example
972
- * ```ts
973
- * import { WarnResult } from "@nunofyobiz/effect-extras"
974
- * import { Effect } from "effect"
975
- *
976
- * const shout = WarnResult.mapWarningsEffect((warnings: string) =>
977
- * Effect.succeed(warnings.toUpperCase())
978
- * )
979
- *
980
- * assert.deepStrictEqual(
981
- * Effect.runSync(
982
- * shout(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 }))
983
- * ),
984
- * WarnResult.SuccessWithWarnings({ warnings: "W", success: 1 })
985
- * )
986
- * ```
987
- *
988
- * @category sequencing
989
- * @since 0.0.0
990
- */
991
- declare const mapWarningsEffect: <W1, W2, EW, RW>(mapWarnings: (warnings: W1) => Effect.Effect<W2, EW, RW>) => (<A>(warnResult: WarnResult<W1, A>) => Effect.Effect<WarnResult<W2, A>, EW, RW>);
992
- /**
993
- * Effectful `flatMapWarnings`: chains the `warnings` of a `WarnResult` into an
994
- * `Effect` that yields a new `WarnResult`, flattening the result.
995
- *
996
- * When `warnings` are present they are passed to `mapWarnings`, whose effectful
997
- * `WarnResult` replaces the original; `SuccessOnly` is lifted unchanged via
998
- * `Effect.succeed`. Use it to sequence warnings-driven effectful computations that
999
- * produce a `WarnResult`.
1000
- *
1001
- * @example
1002
- * ```ts
1003
- * import { WarnResult } from "@nunofyobiz/effect-extras"
1004
- * import { Effect } from "effect"
1005
- *
1006
- * const chain = WarnResult.flatMapWarningsEffect((warnings: string) =>
1007
- * Effect.succeed(WarnResult.WarningsOnly({ warnings: warnings.toUpperCase() }))
1008
- * )
1009
- *
1010
- * assert.deepStrictEqual(
1011
- * Effect.runSync(chain(WarnResult.WarningsOnly({ warnings: "w" }))),
1012
- * WarnResult.WarningsOnly({ warnings: "W" })
1013
- * )
1014
- * assert.deepStrictEqual(
1015
- * Effect.runSync(chain(WarnResult.SuccessOnly({ success: 1 }))),
1016
- * WarnResult.SuccessOnly({ success: 1 })
1017
- * )
1018
- * ```
1019
- *
1020
- * @category sequencing
1021
- * @since 0.0.0
1022
- */
1023
- declare const flatMapWarningsEffect: <W1, W2, A2, EW, RW>(mapWarnings: (warnings: W1) => Effect.Effect<WarnResult<W2, A2>, EW, RW>) => (<A1>(warnResult: WarnResult<W1, A1>) => Effect.Effect<WarnResult<W2, A1 | A2>, EW, RW>);
1024
- /**
1025
- * Transforms the `success` value of a `WarnResult`, leaving any `warnings`
1026
- * untouched.
1027
- *
1028
- * The mirror of `mapWarnings`: `SuccessOnly` and `SuccessWithWarnings` have their
1029
- * `success` value mapped, while `WarningsOnly` passes through unchanged.
1030
- *
1031
- * @example
1032
- * ```ts
1033
- * import { WarnResult } from "@nunofyobiz/effect-extras"
1034
- *
1035
- * const inc = WarnResult.mapSuccess((success: number) => success + 1)
1036
- *
1037
- * assert.deepStrictEqual(
1038
- * inc(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })),
1039
- * WarnResult.SuccessWithWarnings({ warnings: "w", success: 2 })
1040
- * )
1041
- * assert.deepStrictEqual(
1042
- * inc(WarnResult.WarningsOnly({ warnings: "w" })),
1043
- * WarnResult.WarningsOnly({ warnings: "w" })
1044
- * )
1045
- * ```
1046
- *
1047
- * @category mapping
1048
- * @since 0.0.0
1049
- */
1050
- declare const mapSuccess: <A1, A2>(mapSuccess: (success: A1) => A2) => (<W>(warnResult: WarnResult<W, A1>) => WarnResult<W, A2>);
1051
- /**
1052
- * Chains the `success` value of a `WarnResult` into a new `WarnResult`, flattening
1053
- * the result.
1054
- *
1055
- * The mirror of `flatMapWarnings`: whenever a `success` value is present
1056
- * (`SuccessOnly` or `SuccessWithWarnings`) it is passed to `mapSuccess`, whose
1057
- * returned `WarnResult` replaces the original; `WarningsOnly` passes through
1058
- * unchanged.
1059
- *
1060
- * @example
1061
- * ```ts
1062
- * import { WarnResult } from "@nunofyobiz/effect-extras"
1063
- *
1064
- * const chain = WarnResult.flatMapSuccess((success: number) =>
1065
- * WarnResult.SuccessOnly({ success: success + 1 })
1066
- * )
1067
- *
1068
- * assert.deepStrictEqual(
1069
- * chain(WarnResult.SuccessOnly({ success: 1 })),
1070
- * WarnResult.SuccessOnly({ success: 2 })
1071
- * )
1072
- * assert.deepStrictEqual(
1073
- * chain(WarnResult.WarningsOnly({ warnings: "w" })),
1074
- * WarnResult.WarningsOnly({ warnings: "w" })
1075
- * )
1076
- * ```
1077
- *
1078
- * @category sequencing
1079
- * @since 0.0.0
1080
- */
1081
- declare const flatMapSuccess: <W2, A1, A2>(mapSuccess: (success: A1) => WarnResult<W2, A2>) => (<W1>(warnResult: WarnResult<W1, A1>) => WarnResult<W1 | W2, A2>);
1082
- /**
1083
- * Effectful `mapSuccess`: transforms the `success` value of a `WarnResult` through
1084
- * an `Effect`, leaving any `warnings` untouched.
1085
- *
1086
- * The mirror of `mapWarningsEffect`: the `success` value (when present) is mapped
1087
- * effectfully and the `warnings` are carried through unchanged via
1088
- * `Effect.succeed`.
1089
- *
1090
- * @example
1091
- * ```ts
1092
- * import { WarnResult } from "@nunofyobiz/effect-extras"
1093
- * import { Effect } from "effect"
1094
- *
1095
- * const inc = WarnResult.mapSuccessEffect((success: number) =>
1096
- * Effect.succeed(success + 1)
1097
- * )
1098
- *
1099
- * assert.deepStrictEqual(
1100
- * Effect.runSync(
1101
- * inc(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 }))
1102
- * ),
1103
- * WarnResult.SuccessWithWarnings({ warnings: "w", success: 2 })
1104
- * )
1105
- * ```
1106
- *
1107
- * @category sequencing
1108
- * @since 0.0.0
1109
- */
1110
- declare const mapSuccessEffect: <A1, A2, EA, RA>(mapSuccess: (success: A1) => Effect.Effect<A2, EA, RA>) => (<W>(warnResult: WarnResult<W, A1>) => Effect.Effect<WarnResult<W, A2>, EA, RA>);
1111
- /**
1112
- * Effectful `flatMapSuccess`: chains the `success` value of a `WarnResult` into an
1113
- * `Effect` that yields a new `WarnResult`, flattening the result.
1114
- *
1115
- * The mirror of `flatMapWarningsEffect`: when a `success` value is present it is
1116
- * passed to `mapSuccess`, whose effectful `WarnResult` replaces the original;
1117
- * `WarningsOnly` is lifted unchanged via `Effect.succeed`.
1118
- *
1119
- * @example
1120
- * ```ts
1121
- * import { WarnResult } from "@nunofyobiz/effect-extras"
1122
- * import { Effect } from "effect"
1123
- *
1124
- * const chain = WarnResult.flatMapSuccessEffect((success: number) =>
1125
- * Effect.succeed(WarnResult.SuccessOnly({ success: success + 1 }))
1126
- * )
1127
- *
1128
- * assert.deepStrictEqual(
1129
- * Effect.runSync(chain(WarnResult.SuccessOnly({ success: 1 }))),
1130
- * WarnResult.SuccessOnly({ success: 2 })
1131
- * )
1132
- * assert.deepStrictEqual(
1133
- * Effect.runSync(chain(WarnResult.WarningsOnly({ warnings: "w" }))),
1134
- * WarnResult.WarningsOnly({ warnings: "w" })
1135
- * )
1136
- * ```
1137
- *
1138
- * @category sequencing
1139
- * @since 0.0.0
1140
- */
1141
- declare const flatMapSuccessEffect: <W2, A1, A2, EA, RA>(mapSuccess: (success: A1) => Effect.Effect<WarnResult<W2, A2>, EA, RA>) => (<W1>(warnResult: WarnResult<W1, A1>) => Effect.Effect<WarnResult<W1 | W2, A2>, EA, RA>);
1142
-
1143
- declare const WarnResult$1_SuccessOnly: typeof SuccessOnly;
1144
- declare const WarnResult$1_SuccessWithWarnings: typeof SuccessWithWarnings;
1145
- type WarnResult$1_WarnResult<W, A> = WarnResult<W, A>;
1146
- declare const WarnResult$1_WarningsOnly: typeof WarningsOnly;
1147
- declare const WarnResult$1_WithSuccess: typeof WithSuccess;
1148
- declare const WarnResult$1_WithWarnings: typeof WithWarnings;
1149
- declare const WarnResult$1_flatMapSuccess: typeof flatMapSuccess;
1150
- declare const WarnResult$1_flatMapSuccessEffect: typeof flatMapSuccessEffect;
1151
- declare const WarnResult$1_flatMapWarnings: typeof flatMapWarnings;
1152
- declare const WarnResult$1_flatMapWarningsEffect: typeof flatMapWarningsEffect;
1153
- declare const WarnResult$1_fromNullables: typeof fromNullables;
1154
- declare const WarnResult$1_is: typeof is;
1155
- declare const WarnResult$1_mapBoth: typeof mapBoth;
1156
- declare const WarnResult$1_mapBothEffect: typeof mapBothEffect;
1157
- declare const WarnResult$1_mapSuccess: typeof mapSuccess;
1158
- declare const WarnResult$1_mapSuccessEffect: typeof mapSuccessEffect;
1159
- declare const WarnResult$1_mapWarnings: typeof mapWarnings;
1160
- declare const WarnResult$1_mapWarningsEffect: typeof mapWarningsEffect;
1161
- declare const WarnResult$1_matchSuccess: typeof matchSuccess;
1162
- declare const WarnResult$1_matchWarnings: typeof matchWarnings;
1163
- declare const WarnResult$1_optionFromNullables: typeof optionFromNullables;
1164
- declare const WarnResult$1_orElse: typeof orElse;
1165
- declare const WarnResult$1_orUndefined: typeof orUndefined;
1166
- declare const WarnResult$1_successOption: typeof successOption;
1167
- declare const WarnResult$1_successOrElse: typeof successOrElse;
1168
- declare const WarnResult$1_successOrUndefined: typeof successOrUndefined;
1169
- declare const WarnResult$1_warningsOption: typeof warningsOption;
1170
- declare const WarnResult$1_warningsOrElse: typeof warningsOrElse;
1171
- declare const WarnResult$1_warningsOrUndefined: typeof warningsOrUndefined;
1172
- declare namespace WarnResult$1 {
1173
- export { WarnResult$1_SuccessOnly as SuccessOnly, WarnResult$1_SuccessWithWarnings as SuccessWithWarnings, type WarnResult$1_WarnResult as WarnResult, WarnResult$1_WarningsOnly as WarningsOnly, WarnResult$1_WithSuccess as WithSuccess, WarnResult$1_WithWarnings as WithWarnings, WarnResult$1_flatMapSuccess as flatMapSuccess, WarnResult$1_flatMapSuccessEffect as flatMapSuccessEffect, WarnResult$1_flatMapWarnings as flatMapWarnings, WarnResult$1_flatMapWarningsEffect as flatMapWarningsEffect, WarnResult$1_fromNullables as fromNullables, WarnResult$1_is as is, WarnResult$1_mapBoth as mapBoth, WarnResult$1_mapBothEffect as mapBothEffect, WarnResult$1_mapSuccess as mapSuccess, WarnResult$1_mapSuccessEffect as mapSuccessEffect, WarnResult$1_mapWarnings as mapWarnings, WarnResult$1_mapWarningsEffect as mapWarningsEffect, match$1 as match, WarnResult$1_matchSuccess as matchSuccess, WarnResult$1_matchWarnings as matchWarnings, WarnResult$1_optionFromNullables as optionFromNullables, WarnResult$1_orElse as orElse, WarnResult$1_orUndefined as orUndefined, WarnResult$1_successOption as successOption, WarnResult$1_successOrElse as successOrElse, WarnResult$1_successOrUndefined as successOrUndefined, WarnResult$1_warningsOption as warningsOption, WarnResult$1_warningsOrElse as warningsOrElse, WarnResult$1_warningsOrUndefined as warningsOrUndefined };
1174
- }
1175
-
1176
- /**
1177
- * Generic, framework-agnostic extensions to Effect's `Array` module.
1178
- *
1179
- * @since 0.0.0
1180
- */
1181
-
1182
- /**
1183
- * Returns a shallow copy of `array` between `start` (inclusive) and `end`
1184
- * (exclusive), as a pipeable, dual-form alias for `Array.prototype.slice`.
1185
- *
1186
- * `Array.prototype.slice` is already non-mutating (it returns a shallow copy),
1187
- * but it isn't pipeable. This helper makes it composable inside `pipe(...)`
1188
- * chains alongside the rest of the codebase's Effect-style utilities.
1189
- *
1190
- * @example
1191
- * ```ts
1192
- * import { pipe } from "effect"
1193
- * import { ArrayX } from "@nunofyobiz/effect-extras"
1194
- *
1195
- * // data-first
1196
- * assert.deepStrictEqual(ArrayX.slice([1, 2, 3, 4], 1, 3), [2, 3])
1197
- *
1198
- * // data-last (pipeable)
1199
- * assert.deepStrictEqual(pipe([1, 2, 3, 4], ArrayX.slice(1, 3)), [2, 3])
1200
- * ```
1201
- *
1202
- * @category getters
1203
- * @since 0.0.0
1204
- */
1205
- declare const slice: (<A>(start: number, end: number) => (array: readonly A[]) => A[]) & (<A>(array: readonly A[], start: number, end: number) => A[]);
1206
- /**
1207
- * Zips two arrays into one, calling `f` with a `WarnResult` for each index so
1208
- * that length mismatches are handled explicitly rather than truncated.
1209
- *
1210
- * Unlike `Array.zipWith` (which stops at the shorter array), this walks to the
1211
- * length of the *longer* array. The first array's element fills the `warnings`
1212
- * side and the second array's element fills the `success` side, so at each index
1213
- * `f` receives a `WarnResult.WarnResult<A, B>`: `SuccessWithWarnings` when both
1214
- * arrays have an element, `WarningsOnly` when only the first does, and
1215
- * `SuccessOnly` when only the second does. Use it when the "extra" tail of either
1216
- * array still carries meaning.
1217
- *
1218
- * @example
1219
- * ```ts
1220
- * import { ArrayX, WarnResult } from "@nunofyobiz/effect-extras"
1221
- *
1222
- * const describe = WarnResult.match({
1223
- * WarningsOnly: ({ warnings }) => `warnings ${warnings}`,
1224
- * SuccessOnly: ({ success }) => `success ${success}`,
1225
- * SuccessWithWarnings: ({ warnings, success }) => `both ${warnings}/${success}`,
1226
- * })
1227
- *
1228
- * assert.deepStrictEqual(ArrayX.zipWithWarnings([1, 2, 3], [10, 20], describe), [
1229
- * "both 1/10",
1230
- * "both 2/20",
1231
- * "warnings 3",
1232
- * ])
1233
- * ```
1234
- *
1235
- * @category combinators
1236
- * @since 0.0.0
1237
- */
1238
- declare const zipWithWarnings: (<A, B, C>(f: (ab: WarnResult<A, B>) => C) => (array1: readonly A[], array2: readonly B[]) => C[]) & (<A, B, C>(array1: readonly A[], array2: readonly B[], f: (ab: WarnResult<A, B>) => C) => C[]);
1239
- /**
1240
- * Inserts or moves a unique item in an array at a specified position.
1241
- *
1242
- * **Assumption**: Items should be unique in the array based on standard equality.
1243
- *
1244
- * **Happy case**: If the item doesn't exist in the array and the destination reference item is found:
1245
- * The new item is inserted before the destination reference item
1246
- *
1247
- * **Item not found in array**:
1248
- * - If destination reference item is found: The new item is inserted before the destination reference item
1249
- * - If destination reference item is not found: The new item is inserted at the end of the array
1250
- *
1251
- * **Item found but duplicated**:
1252
- * - If destination reference item is found: All existing copies are removed, then a single copy is inserted before the destination reference item
1253
- * - If destination reference item is not found: All existing copies are removed, then a single copy is inserted at the end of the array
1254
- *
1255
- * @param array - The input array to modify
1256
- * @param config - Configuration object containing:
1257
- * - `item`: The item to insert or update (must be a string or number)
1258
- * - `insertToBeLeftOf`: The item to position the new/updated item before,
1259
- * or null to insert at the end
1260
- *
1261
- * @returns A new array with the item inserted or moved to the specified position
1262
- *
1263
- * @example
1264
- * ```ts
1265
- * import { ArrayX } from "@nunofyobiz/effect-extras"
1266
- *
1267
- * // Move an existing item to sit just before "c"
1268
- * assert.deepStrictEqual(
1269
- * ArrayX.insertUniq(["a", "b", "c", "d"], { item: "a", insertToBeLeftOf: "c" }),
1270
- * ["b", "a", "c", "d"],
1271
- * )
1272
- *
1273
- * // Insert a brand-new item; unknown destination falls through to the end
1274
- * assert.deepStrictEqual(
1275
- * ArrayX.insertUniq(["a", "b"], { item: "new", insertToBeLeftOf: null }),
1276
- * ["a", "b", "new"],
1277
- * )
1278
- * ```
1279
- *
1280
- * @category combinators
1281
- * @since 0.0.0
1282
- */
1283
- declare const insertUniq: (<A extends string | number>(config: {
1284
- item: A;
1285
- insertToBeLeftOf: A | null;
1286
- }) => (array: readonly A[] | A[]) => A[]) & (<A extends string | number>(array: readonly A[] | A[], config: {
1287
- item: A;
1288
- insertToBeLeftOf: A | null;
1289
- }) => A[]);
1290
- /**
1291
- * Maps over `array` while threading an accumulator, iterating from right to
1292
- * left instead of left to right.
1293
- *
1294
- * Identical to `Array.mapAccum`, except the traversal order is reversed: `f` is
1295
- * called on the last element first, and the resulting array is returned in the
1296
- * original (left-to-right) order. Use it when each element's mapped value
1297
- * depends on state accumulated from the elements that follow it.
1298
- *
1299
- * @example
1300
- * ```ts
1301
- * import { ArrayX } from "@nunofyobiz/effect-extras"
1302
- *
1303
- * // Running suffix-sum: each slot holds the sum of itself and everything after it
1304
- * assert.deepStrictEqual(
1305
- * ArrayX.mapRightAccum([1, 2, 3], 0, (total, n) => [total + n, total + n]),
1306
- * [6, [6, 5, 3]],
1307
- * )
1308
- * ```
1309
- *
1310
- * @category folding
1311
- * @since 0.0.0
1312
- */
1313
- declare const mapRightAccum: (<A, B, C>(initialAccumulator: C, f: (accumulator: C, a: A, index: number) => [C, B]) => (array: A[]) => [C, B[]]) & (<A, B, C>(array: A[], initialAccumulator: C, f: (accumulator: C, a: A, index: number) => [C, B]) => [C, B[]]);
1314
- /**
1315
- * Returns the maximum element of `array` according to `order`, wrapped in an
1316
- * `Option` so that empty arrays are handled safely.
1317
- *
1318
- * Effect's `Array.max` throws on an empty array; this returns `Option.none()`
1319
- * instead, and `Option.some(max)` otherwise. Reach for it whenever the input
1320
- * array might be empty.
1321
- *
1322
- * @example
1323
- * ```ts
1324
- * import { Option, Order, pipe } from "effect"
1325
- * import { ArrayX } from "@nunofyobiz/effect-extras"
1326
- *
1327
- * assert.deepStrictEqual(
1328
- * pipe([3, 7, 2], ArrayX.maxOption(Order.Number)),
1329
- * Option.some(7),
1330
- * )
1331
- * assert.deepStrictEqual(
1332
- * pipe([], ArrayX.maxOption(Order.Number)),
1333
- * Option.none(),
1334
- * )
1335
- * ```
1336
- *
1337
- * @category getters
1338
- * @since 0.0.0
1339
- */
1340
- declare const maxOption: (<A>(order: Order.Order<A>) => (array: A[]) => Option.Option<A>) & (<A>(array: A[], order: Order.Order<A>) => Option.Option<A>);
1341
- /**
1342
- * Returns the smallest element of `array` (per `order`) that matches
1343
- * `predicate`, narrowed to the refined type `B`, or `Option.none()` if none
1344
- * match.
1345
- *
1346
- * Combines a refinement filter with `Array.min`: only elements satisfying
1347
- * `predicate` are considered, and the minimum of those (by `order`) is
1348
- * returned. The refinement narrows the element type, so the resulting `Option`
1349
- * carries the more specific `B`.
1350
- *
1351
- * @example
1352
- * ```ts
1353
- * import { Option, Order, pipe } from "effect"
1354
- * import { ArrayX } from "@nunofyobiz/effect-extras"
1355
- *
1356
- * const isEven = (n: number): n is number => n % 2 === 0
1357
- *
1358
- * assert.deepStrictEqual(
1359
- * pipe([3, 4, 1, 2, 5], ArrayX.takeFirstWhere(isEven, Order.Number)),
1360
- * Option.some(2),
1361
- * )
1362
- * assert.deepStrictEqual(
1363
- * pipe([1, 3, 5], ArrayX.takeFirstWhere(isEven, Order.Number)),
1364
- * Option.none(),
1365
- * )
1366
- * ```
1367
- *
1368
- * @category getters
1369
- * @since 0.0.0
1370
- */
1371
- declare const takeFirstWhere$1: (<A, B extends A>(predicate: Predicate.Refinement<A, B>, order: Order.Order<B>) => (array: A[]) => Option.Option<B>) & (<A, B extends A>(array: A[], predicate: Predicate.Refinement<A, B>, order: Order.Order<B>) => Option.Option<B>);
1372
- /**
1373
- * Returns the largest element of `array` (per `order`) that matches
1374
- * `predicate`, narrowed to the refined type `B`, or `Option.none()` if none
1375
- * match.
1376
- *
1377
- * The mirror of {@link takeFirstWhere}: only elements satisfying `predicate`
1378
- * are considered, and the maximum of those (by `order`) is returned. The
1379
- * refinement narrows the element type, so the resulting `Option` carries the
1380
- * more specific `B`.
1381
- *
1382
- * @example
1383
- * ```ts
1384
- * import { Option, Order, pipe } from "effect"
1385
- * import { ArrayX } from "@nunofyobiz/effect-extras"
1386
- *
1387
- * const isEven = (n: number): n is number => n % 2 === 0
1388
- *
1389
- * assert.deepStrictEqual(
1390
- * pipe([3, 4, 1, 2, 5], ArrayX.takeLastWhere(isEven, Order.Number)),
1391
- * Option.some(4),
1392
- * )
1393
- * assert.deepStrictEqual(
1394
- * pipe([1, 3, 5], ArrayX.takeLastWhere(isEven, Order.Number)),
1395
- * Option.none(),
1396
- * )
1397
- * ```
1398
- *
1399
- * @category getters
1400
- * @since 0.0.0
1401
- */
1402
- declare const takeLastWhere$1: (<A, B extends A>(predicate: Predicate.Refinement<A, B>, order: Order.Order<B>) => (array: A[]) => Option.Option<B>) & (<A, B extends A>(array: A[], predicate: Predicate.Refinement<A, B>, order: Order.Order<B>) => Option.Option<B>);
1403
- /**
1404
- * Groups `items` into a partial record keyed by the category each item maps to
1405
- * via `categorize`.
1406
- *
1407
- * Each item is appended to the array under its category, preserving input
1408
- * order. The result is `Partial<Record<C, A[]>>` because not every possible
1409
- * category `C` is guaranteed to appear — only categories that received at least
1410
- * one item are present.
1411
- *
1412
- * @example
1413
- * ```ts
1414
- * import { ArrayX } from "@nunofyobiz/effect-extras"
1415
- *
1416
- * const parity = (n: number) => (n % 2 === 0 ? "even" : "odd")
1417
- *
1418
- * assert.deepStrictEqual(ArrayX.categorize([1, 2, 3, 4], parity), {
1419
- * odd: [1, 3],
1420
- * even: [2, 4],
1421
- * })
1422
- * ```
1423
- *
1424
- * @category folding
1425
- * @since 0.0.0
1426
- */
1427
- declare const categorize: <A, C extends string>(items: Iterable<A>, categorize: (a: A) => C) => Partial<Record<C, A[]>>;
1428
- /**
1429
- * Removes all `null` and `undefined` elements from `array`, narrowing the
1430
- * element type to `NonNullable<A>`.
1431
- *
1432
- * Falsy-but-present values such as `0` and `""` are kept — only nullish values
1433
- * are dropped. Use it to clean up an array of optionals into a dense array of
1434
- * known-present values.
1435
- *
1436
- * @example
1437
- * ```ts
1438
- * import { ArrayX } from "@nunofyobiz/effect-extras"
1439
- *
1440
- * assert.deepStrictEqual(
1441
- * ArrayX.compactNullable([1, null, 2, undefined, 0, ""]),
1442
- * [1, 2, 0, ""],
1443
- * )
1444
- * ```
1445
- *
1446
- * @category filtering
1447
- * @since 0.0.0
1448
- */
1449
- declare const compactNullable: <A>(array: A[]) => NonNullable<A>[];
1450
- /**
1451
- * Drops the leading elements of `array` until `predicate` first holds, keeping
1452
- * everything from the first match onward.
1453
- *
1454
- * The first matching element and all subsequent elements are retained
1455
- * regardless of whether they match — only the prefix *before* the first match
1456
- * is trimmed. If nothing matches, returns an empty array.
1457
- *
1458
- * @example
1459
- * ```ts
1460
- * import { Predicate } from "effect"
1461
- * import { ArrayX } from "@nunofyobiz/effect-extras"
1462
- *
1463
- * // Trims the leading strings, then keeps everything (including the trailing "b")
1464
- * assert.deepStrictEqual(
1465
- * ArrayX.filterHead(["a", 1, 2, "b"], Predicate.isNumber),
1466
- * [1, 2, "b"],
1467
- * )
1468
- * ```
1469
- *
1470
- * @category filtering
1471
- * @since 0.0.0
1472
- */
1473
- declare const filterHead: (<A>(predicate: Predicate.Predicate<A>) => (array: A[]) => A[]) & (<A>(array: A[], predicate: Predicate.Predicate<A>) => A[]);
1474
- /**
1475
- * Drops the trailing elements of `array` after `predicate` last holds, keeping
1476
- * everything up to and including the last match.
1477
- *
1478
- * The mirror of {@link filterHead}: the last matching element and all preceding
1479
- * elements are retained regardless of whether they match — only the suffix
1480
- * *after* the last match is trimmed. If nothing matches, returns an empty
1481
- * array.
1482
- *
1483
- * @example
1484
- * ```ts
1485
- * import { Predicate } from "effect"
1486
- * import { ArrayX } from "@nunofyobiz/effect-extras"
1487
- *
1488
- * // Keeps the leading "a" and trims the trailing strings after the last number
1489
- * assert.deepStrictEqual(
1490
- * ArrayX.filterTail(["a", 1, 2, "b"], Predicate.isNumber),
1491
- * ["a", 1, 2],
1492
- * )
1493
- * ```
1494
- *
1495
- * @category filtering
1496
- * @since 0.0.0
1497
- */
1498
- declare const filterTail: (<A>(predicate: Predicate.Predicate<A>) => (array: A[]) => A[]) & (<A>(array: A[], predicate: Predicate.Predicate<A>) => A[]);
1499
- /**
1500
- * Maps `f` over `array` and drops every result that is `null` or `undefined`,
1501
- * narrowing the element type to `NonNullable<B>`.
1502
- *
1503
- * A nullable-friendly `Array.filterMap`: where `filterMap` expects `f` to
1504
- * return an `Option`, this accepts a function returning `B | null` (or
1505
- * `undefined`) and treats nullish results as "skip this element". Falsy-but-
1506
- * present values such as `0` and `""` are kept.
1507
- *
1508
- * @example
1509
- * ```ts
1510
- * import { ArrayX } from "@nunofyobiz/effect-extras"
1511
- *
1512
- * // Keep only the even numbers, mapped to their halves
1513
- * assert.deepStrictEqual(
1514
- * ArrayX.filterMapNullable([1, 2, 3, 4], (n) => (n % 2 === 0 ? n / 2 : null)),
1515
- * [1, 2],
1516
- * )
1517
- * ```
1518
- *
1519
- * @category filtering
1520
- * @since 0.0.0
1521
- */
1522
- declare const filterMapNullable: (<A, B>(f: (a: A) => B | null) => (array: A[]) => NonNullable<B>[]) & (<A, B>(array: A[], f: (a: A) => B | null) => NonNullable<B>[]);
1523
- /**
1524
- * Finds the first element of a 2-dimensional array (row-major order) matching
1525
- * `predicate`, returning it alongside its row and column indices.
1526
- *
1527
- * Scans rows top-to-bottom and, within each row, left-to-right. On a match
1528
- * returns `Option.some([value, rowIndex, columnIndex])`; if no element matches
1529
- * (or the grid is empty), returns `Option.none()`.
1530
- *
1531
- * @example
1532
- * ```ts
1533
- * import { Option } from "effect"
1534
- * import { ArrayX } from "@nunofyobiz/effect-extras"
1535
- *
1536
- * const grid = [
1537
- * ["A", "B", "C"],
1538
- * ["D", "E", "F"],
1539
- * ]
1540
- *
1541
- * assert.deepStrictEqual(
1542
- * ArrayX.findFirstWithIndex2d(grid, (cell) => cell === "E"),
1543
- * Option.some(["E", 1, 1]),
1544
- * )
1545
- * ```
1546
- *
1547
- * @category getters
1548
- * @since 0.0.0
1549
- */
1550
- declare const findFirstWithIndex2d: (<A>(predicate: Predicate.Predicate<A>) => (array: A[][]) => Option.Option<[A, number, number]>) & (<A>(array: A[][], predicate: Predicate.Predicate<A>) => Option.Option<[A, number, number]>);
1551
- /**
1552
- * Splits `array` into runs of consecutive elements that share the same group
1553
- * value, where the group is derived by `chunk` and compared with the provided
1554
- * `Equivalence`.
1555
- *
1556
- * Only *adjacent* elements are grouped: a new run starts every time the group
1557
- * value changes from the previous element. Each entry in the result carries the
1558
- * `group` value and the non-empty array of `values` that produced it, preserving
1559
- * input order. An empty input yields an empty array. Use it for run-length-style
1560
- * segmentation; reach for `Array.groupBy` instead when you want all elements
1561
- * with the same key collapsed regardless of position.
1562
- *
1563
- * @example
1564
- * ```ts
1565
- * import { Equivalence } from "effect"
1566
- * import { ArrayX } from "@nunofyobiz/effect-extras"
1567
- *
1568
- * // Group adjacent numbers by parity
1569
- * assert.deepStrictEqual(
1570
- * ArrayX.chunkBy([2, 4, 1, 3, 6], (n) => n % 2 === 0, Equivalence.Boolean),
1571
- * [
1572
- * { group: true, values: [2, 4] },
1573
- * { group: false, values: [1, 3] },
1574
- * { group: true, values: [6] },
1575
- * ],
1576
- * )
1577
- * ```
1578
- *
1579
- * @category folding
1580
- * @since 0.0.0
1581
- */
1582
- declare const chunkBy: (<A, B>(chunk: (a: A) => B, GroupEquivalence: Equivalence.Equivalence<B>) => (array: A[]) => {
1583
- group: B;
1584
- values: Array.NonEmptyArray<A>;
1585
- }[]) & (<A, B>(array: A[], chunk: (a: A) => B, GroupEquivalence: Equivalence.Equivalence<B>) => {
1586
- group: B;
1587
- values: Array.NonEmptyArray<A>;
1588
- }[]);
1589
-
1590
- declare const ArrayX_categorize: typeof categorize;
1591
- declare const ArrayX_chunkBy: typeof chunkBy;
1592
- declare const ArrayX_compactNullable: typeof compactNullable;
1593
- declare const ArrayX_filterHead: typeof filterHead;
1594
- declare const ArrayX_filterMapNullable: typeof filterMapNullable;
1595
- declare const ArrayX_filterTail: typeof filterTail;
1596
- declare const ArrayX_findFirstWithIndex2d: typeof findFirstWithIndex2d;
1597
- declare const ArrayX_insertUniq: typeof insertUniq;
1598
- declare const ArrayX_mapRightAccum: typeof mapRightAccum;
1599
- declare const ArrayX_maxOption: typeof maxOption;
1600
- declare const ArrayX_slice: typeof slice;
1601
- declare const ArrayX_zipWithWarnings: typeof zipWithWarnings;
1602
- declare namespace ArrayX {
1603
- export { ArrayX_categorize as categorize, ArrayX_chunkBy as chunkBy, ArrayX_compactNullable as compactNullable, ArrayX_filterHead as filterHead, ArrayX_filterMapNullable as filterMapNullable, ArrayX_filterTail as filterTail, ArrayX_findFirstWithIndex2d as findFirstWithIndex2d, ArrayX_insertUniq as insertUniq, ArrayX_mapRightAccum as mapRightAccum, ArrayX_maxOption as maxOption, ArrayX_slice as slice, takeFirstWhere$1 as takeFirstWhere, takeLastWhere$1 as takeLastWhere, ArrayX_zipWithWarnings as zipWithWarnings };
1604
- }
1605
-
1606
- /**
1607
- * Converts a `bigint` to a `number`, throwing when the value cannot be
1608
- * represented exactly.
1609
- *
1610
- * Delegates to Effect's `BigInt.toNumber`, which returns `None` once the
1611
- * `bigint` falls outside the safe integer range (`Number.MAX_SAFE_INTEGER`).
1612
- * This unwraps that `Option`, throwing instead of silently losing precision —
1613
- * use it only when the value is known to fit.
1614
- *
1615
- * @example
1616
- * ```ts
1617
- * import { BigIntX } from "@nunofyobiz/effect-extras"
1618
- *
1619
- * assert.deepStrictEqual(BigIntX.toNumberOrThrow(42n), 42)
1620
- *
1621
- * // throws when outside the safe integer range
1622
- * assert.throws(() => BigIntX.toNumberOrThrow(9007199254740993n))
1623
- * ```
1624
- *
1625
- * @category unsafe
1626
- * @since 0.0.0
1627
- */
1628
- declare const toNumberOrThrow: (value: bigint) => number;
1629
-
1630
- declare const BigIntX_toNumberOrThrow: typeof toNumberOrThrow;
1631
- declare namespace BigIntX {
1632
- export { BigIntX_toNumberOrThrow as toNumberOrThrow };
1633
- }
1634
-
1635
- /**
1636
- * Generic, framework-agnostic extensions to Effect's `Boolean` module.
1637
- *
1638
- * @since 0.0.0
1639
- */
1640
- /**
1641
- * Converts a `boolean` to its binary digit: `1` for `true`, `0` for `false`.
1642
- *
1643
- * Useful when a numeric flag is required — summing booleans to count how many
1644
- * predicates hold, or feeding a bit into bitwise math or an external API that
1645
- * expects `0`/`1` rather than `false`/`true`.
1646
- *
1647
- * @example
1648
- * ```ts
1649
- * import { BooleanX } from "@nunofyobiz/effect-extras"
1650
- *
1651
- * assert.deepStrictEqual(BooleanX.toBinary(true), 1)
1652
- * assert.deepStrictEqual(BooleanX.toBinary(false), 0)
1653
- * ```
1654
- *
1655
- * @category conversions
1656
- * @since 0.0.0
1657
- */
1658
- declare const toBinary: (value: boolean) => 0 | 1;
1659
-
1660
- declare const BooleanX_toBinary: typeof toBinary;
1661
- declare namespace BooleanX {
1662
- export { BooleanX_toBinary as toBinary };
1663
- }
1664
-
1665
- /**
1666
- * Generic, framework-agnostic extensions to Effect's `Duration` module.
1667
- *
1668
- * @since 0.0.0
1669
- */
1670
-
1671
- /**
1672
- * Computes the elapsed `Duration` from `that` to `self`, clamped at zero.
1673
- *
1674
- * Represents the time that has passed since the reference instant `that`. When
1675
- * `that` lies in the future relative to `self`, the elapsed time is `zero`
1676
- * rather than a negative duration.
1677
- *
1678
- * @example
1679
- * ```ts
1680
- * import { DateTime, Duration, pipe } from "effect"
1681
- * import { DurationX } from "@nunofyobiz/effect-extras"
1682
- *
1683
- * const earlier = DateTime.makeUnsafe(1000)
1684
- * const later = DateTime.makeUnsafe(4000)
1685
- *
1686
- * // data-first
1687
- * assert.deepStrictEqual(DurationX.diff(later, earlier), Duration.seconds(3))
1688
- *
1689
- * // future reference clamps to zero
1690
- * assert.deepStrictEqual(DurationX.diff(earlier, later), Duration.zero)
1691
- *
1692
- * // data-last (piped)
1693
- * assert.deepStrictEqual(
1694
- * pipe(later, DurationX.diff(earlier)),
1695
- * Duration.seconds(3),
1696
- * )
1697
- * ```
1698
- *
1699
- * @category combinators
1700
- * @since 0.0.0
1701
- */
1702
- declare const diff: ((that: DateTime.DateTime) => (self: DateTime.DateTime) => Duration.Duration) & ((self: DateTime.DateTime, that: DateTime.DateTime) => Duration.Duration);
1703
- /**
1704
- * Transforms a `Duration` by converting it to a numeric `unit`, applying `map`,
1705
- * then converting back.
1706
- *
1707
- * Lets you operate on a duration in whatever unit is convenient — round it to
1708
- * whole minutes, halve its seconds, floor its days — without juggling
1709
- * conversions by hand. The `map` callback receives the duration expressed as a
1710
- * `number` of `unit`s and returns the new count.
1711
- *
1712
- * @example
1713
- * ```ts
1714
- * import { Duration, Number, pipe } from "effect"
1715
- * import { DurationX } from "@nunofyobiz/effect-extras"
1716
- *
1717
- * // data-first: halve a 4-second duration
1718
- * assert.deepStrictEqual(
1719
- * DurationX.mapAsUnit(Duration.seconds(4), "second", Number.divideUnsafe(2)),
1720
- * Duration.seconds(2),
1721
- * )
1722
- *
1723
- * // data-last (piped)
1724
- * assert.deepStrictEqual(
1725
- * pipe(
1726
- * Duration.minutes(10),
1727
- * DurationX.mapAsUnit("minute", (minutes) => minutes + 5),
1728
- * ),
1729
- * Duration.minutes(15),
1730
- * )
1731
- * ```
1732
- *
1733
- * @category combinators
1734
- * @since 0.0.0
1735
- */
1736
- declare const mapAsUnit: ((unit: Duration.Unit, map: (numberOfUnits: number) => number) => (duration: Duration.Duration) => Duration.Duration) & ((duration: Duration.Duration, unit: Duration.Unit, map: (numberOfUnits: number) => number) => Duration.Duration);
1737
-
1738
- declare const DurationX_diff: typeof diff;
1739
- declare const DurationX_mapAsUnit: typeof mapAsUnit;
1740
- declare namespace DurationX {
1741
- export { DurationX_diff as diff, DurationX_mapAsUnit as mapAsUnit };
1742
- }
1743
-
1744
- /**
1745
- * Generic, framework-agnostic extensions to Effect's `Effect` module.
1746
- *
1747
- * @since 0.0.0
1748
- */
1749
-
1750
- /**
1751
- * Flattens an `Effect` that succeeds with an `Option` into an `Effect` that
1752
- * fails with `onNone()` when the `Option` is `None`.
1753
- *
1754
- * When the wrapped `Option` is `Some(value)` the effect succeeds with `value`;
1755
- * when it is `None` the effect fails with the error produced by the `onNone`
1756
- * thunk. An existing failure of the source effect is preserved untouched, so the
1757
- * result's error channel is the union of the original error and the `None`
1758
- * error.
1759
- *
1760
- * @example
1761
- * ```ts
1762
- * import { Effect, Option, Result } from "effect"
1763
- * import { EffectX } from "@nunofyobiz/effect-extras"
1764
- *
1765
- * const some = EffectX.flattenOption(
1766
- * Effect.succeed(Option.some(1)),
1767
- * () => "missing",
1768
- * )
1769
- * assert.deepStrictEqual(Effect.runSync(Effect.result(some)), Result.succeed(1))
1770
- *
1771
- * const none = EffectX.flattenOption(
1772
- * Effect.succeed(Option.none<number>()),
1773
- * () => "missing",
1774
- * )
1775
- * assert.deepStrictEqual(
1776
- * Effect.runSync(Effect.result(none)),
1777
- * Result.fail("missing"),
1778
- * )
1779
- * ```
1780
- *
1781
- * @category sequencing
1782
- * @since 0.0.0
1783
- */
1784
- declare const flattenOption: (<A, E1, E2, R>(onNone: () => E2) => (effect: Effect.Effect<Option.Option<A>, E1, R>) => Effect.Effect<A, E1 | E2, R>) & (<A, E1, E2, R>(effect: Effect.Effect<Option.Option<A>, E1, R>, onNone: () => E2) => Effect.Effect<A, E1 | E2, R>);
1785
- /**
1786
- * Converts an `Option` to an `Effect`, mapping the `None` case to a caller-chosen
1787
- * error via the `onNone` thunk.
1788
- *
1789
- * Equivalent to `Effect.mapError(Effect.fromOption(option), onNone)`: it bridges
1790
- * the `NoSuchElementError` that `Effect.fromOption` produces to the caller's own
1791
- * error type, so callers never have to handle `NoSuchElementError`. This fills
1792
- * the v4 gap where `Effect.mapError` no longer accepts an `Option` directly —
1793
- * instead of
1794
- * `pipe(option, Effect.fromOption, Effect.mapError(() => new MyError()))`, write
1795
- * `pipe(option, EffectX.fromOptionOrElse(() => new MyError()))`. The `onNone`
1796
- * thunk runs only when the `Option` is `None`.
1797
- *
1798
- * @example
1799
- * ```ts
1800
- * import { Effect, Option, Result, pipe } from "effect"
1801
- * import { EffectX } from "@nunofyobiz/effect-extras"
1802
- *
1803
- * // data-first
1804
- * const some = EffectX.fromOptionOrElse(Option.some(42), () => "missing")
1805
- * assert.deepStrictEqual(Effect.runSync(Effect.result(some)), Result.succeed(42))
1806
- *
1807
- * // data-last (piped) — None maps to the chosen error
1808
- * const none = pipe(
1809
- * Option.none<number>(),
1810
- * EffectX.fromOptionOrElse(() => "missing"),
1811
- * )
1812
- * assert.deepStrictEqual(
1813
- * Effect.runSync(Effect.result(none)),
1814
- * Result.fail("missing"),
1815
- * )
1816
- * ```
1817
- *
1818
- * @category conversions
1819
- * @since 0.0.0
1820
- */
1821
- declare const fromOptionOrElse: {
1822
- <E>(onNone: () => E): <A>(option: Option.Option<A>) => Effect.Effect<A, E>;
1823
- <A, E>(option: Option.Option<A>, onNone: () => E): Effect.Effect<A, E>;
1824
- };
1825
- /**
1826
- * Repeatedly calls a synchronous `try` thunk until its result satisfies the
1827
- * `until` refinement, sleeping `sleepDuration` between attempts and failing with
1828
- * a `TimeoutError` once `maxDuration` elapses.
1829
- *
1830
- * The thunk is evaluated immediately; if its first result already passes the
1831
- * refinement the effect succeeds without any delay. Otherwise it polls on the
1832
- * `sleepDuration` interval (defaulting to 200ms — the threshold below which a
1833
- * delay reads as "instant" to a user) until either the predicate holds (the
1834
- * effect succeeds with the narrowed `B` value) or `maxDuration` is exceeded (the
1835
- * effect fails with a `Cause.TimeoutError`). Use it to await an external,
1836
- * non-effectful condition such as a flag flipped by a callback.
1837
- *
1838
- * @example
1839
- * ```ts
1840
- * import { Duration, Effect } from "effect"
1841
- * import { EffectX } from "@nunofyobiz/effect-extras"
1842
- *
1843
- * // First attempt already matches, so it resolves immediately.
1844
- * const effect = EffectX.tryUntil({
1845
- * try: () => 1,
1846
- * until: (value: number): value is number => value === 1,
1847
- * sleepDuration: Duration.millis(100),
1848
- * maxDuration: Duration.seconds(1),
1849
- * })
1850
- *
1851
- * assert.deepStrictEqual(Effect.runSync(effect), 1)
1852
- * ```
1853
- *
1854
- * @category sequencing
1855
- * @since 0.0.0
1856
- */
1857
- declare const tryUntil: <A, B extends A>({ try: doTry, until: isDone, sleepDuration, maxDuration, }: {
1858
- try: () => A;
1859
- until: Predicate.Refinement<A, B>;
1860
- sleepDuration?: Duration.Duration;
1861
- maxDuration: Duration.Duration;
1862
- }) => Effect.Effect<B, Cause.TimeoutError, never>;
1863
-
1864
- declare const EffectX_flattenOption: typeof flattenOption;
1865
- declare const EffectX_fromOptionOrElse: typeof fromOptionOrElse;
1866
- declare const EffectX_tryUntil: typeof tryUntil;
1867
- declare namespace EffectX {
1868
- export { EffectX_flattenOption as flattenOption, EffectX_fromOptionOrElse as fromOptionOrElse, EffectX_tryUntil as tryUntil };
1869
- }
1870
-
1871
- /**
1872
- * Helpers for decoding `FormData` with Effect `Schema`.
1873
- *
1874
- * @since 0.0.0
1875
- */
1876
-
1877
- /**
1878
- * Decodes a `FormData` into a typed value using a `Schema`, throwing on
1879
- * validation failure.
1880
- *
1881
- * Built on v4's native `Schema.fromFormData`, which first parses the `FormData`
1882
- * entries into a nested tree record (bracket-path notation is supported) and then
1883
- * decodes that tree with the provided inner schema. For schemas with non-string
1884
- * fields (for example `Schema.Int`), wrap the inner schema in
1885
- * `Schema.toCodecStringTree(schema, { keepDeclarations: true })` so the
1886
- * string → number/boolean coercion happens. Usable only with schemas that have
1887
- * no decoding services — this is enforced at the type level via
1888
- * `S["DecodingServices"] = never` — and it throws synchronously when the input
1889
- * fails validation.
1890
- *
1891
- * @example
1892
- * ```ts
1893
- * import { Schema } from "effect"
1894
- * import { FormDataX } from "@nunofyobiz/effect-extras"
1895
- *
1896
- * const formData = new FormData()
1897
- * formData.append("name", "John")
1898
- * formData.append("age", "30")
1899
- *
1900
- * const result = FormDataX.decodeSync(
1901
- * formData,
1902
- * Schema.Struct({ name: Schema.String, age: Schema.NumberFromString }),
1903
- * )
1904
- *
1905
- * assert.deepStrictEqual(result, { name: "John", age: 30 })
1906
- * ```
1907
- *
1908
- * @category conversions
1909
- * @since 0.0.0
1910
- */
1911
- declare const decodeSync: {
1912
- <S extends Schema.Top & {
1913
- readonly DecodingServices: never;
1914
- }>(formData: FormData, schema: S): S["Type"];
1915
- <S extends Schema.Top & {
1916
- readonly DecodingServices: never;
1917
- }>(schema: S): (formData: FormData) => S["Type"];
1918
- };
1919
-
1920
- declare const FormDataX_decodeSync: typeof decodeSync;
1921
- declare namespace FormDataX {
1922
- export { FormDataX_decodeSync as decodeSync };
1923
- }
1924
-
1925
- /**
1926
- * Like `Map.prototype.get`, but when the key is absent it stores the computed
1927
- * fallback at that key and returns it. Mutates the input map in place.
1928
- *
1929
- * Use it for memoization-style caches where a miss should both populate the map
1930
- * and yield the value in one step. Throws if the resolved value is nullish (only
1931
- * possible when `fallbackIfNotFound` returns `null`/`undefined` for a value type
1932
- * that admits them — treated as a programmer error). Supports both data-first and
1933
- * data-last (pipeable) call styles.
1934
- *
1935
- * @example
1936
- * ```ts
1937
- * import { MapX } from "@nunofyobiz/effect-extras"
1938
- * import { pipe } from "effect"
1939
- *
1940
- * // Miss: stores the fallback and returns it (data-first)
1941
- * const map = new Map<string, number>()
1942
- * assert.deepStrictEqual(MapX.getOrElseSetGet(map, "a", () => 1), 1)
1943
- * assert.deepStrictEqual(map.get("a"), 1)
1944
- *
1945
- * // Hit: returns the existing value, fallback is ignored (data-last)
1946
- * assert.deepStrictEqual(
1947
- * pipe(map, MapX.getOrElseSetGet("a", () => 99)),
1948
- * 1
1949
- * )
1950
- * ```
1951
- *
1952
- * @category combinators
1953
- * @since 0.0.0
1954
- */
1955
- declare const getOrElseSetGet: (<K, V>(key: K, fallbackIfNotFound: () => V) => (map: Map<K, V>) => V) & (<K, V>(map: Map<K, V>, key: K, fallbackIfNotFound: () => V) => V);
1956
-
1957
- declare const MapX_getOrElseSetGet: typeof getOrElseSetGet;
1958
- declare namespace MapX {
1959
- export { MapX_getOrElseSetGet as getOrElseSetGet };
1960
- }
1961
-
1962
- /**
1963
- * Helpers for working with non-nullable values.
1964
- *
1965
- * @since 0.0.0
1966
- */
1967
-
1968
- /**
1969
- * Returns `value` narrowed to `NonNullable<A>`, throwing an `Error` if it is
1970
- * `null` or `undefined`.
1971
- *
1972
- * Use it at trusted boundaries where a value is known to be present but typed as
1973
- * nullable, turning a silent `undefined` into a loud failure. An optional
1974
- * `variableName` is woven into the thrown message to aid debugging. This is the
1975
- * function re-exported as `nn` from the module barrel, a terse shorthand handy
1976
- * inside string interpolations.
1977
- *
1978
- * @example
1979
- * ```ts
1980
- * import { NonNullableX } from "@nunofyobiz/effect-extras"
1981
- *
1982
- * assert.deepStrictEqual(NonNullableX.fromNullableOrThrow("value"), "value")
1983
- *
1984
- * assert.throws(
1985
- * () => NonNullableX.fromNullableOrThrow(null, "varName"),
1986
- * /Value is nullable: null \(variable name: varName\)/
1987
- * )
1988
- * ```
1989
- *
1990
- * @category unsafe
1991
- * @since 0.0.0
1992
- */
1993
- declare const fromNullableOrThrow: <A>(value: A, variableName?: string) => NonNullable<A>;
1994
- /**
1995
- * Branches on whether `value` is nullish, passing the value narrowed to
1996
- * `NonNullable<A>` to the `whenNotNullable` handler.
1997
- *
1998
- * A nullable-aware sibling of `Match.value`: it folds a present-or-absent value
1999
- * into a single `B` without an `if`/`else` or a manual `!= null` check. Note that
2000
- * falsy-but-present values (`""`, `0`, `false`) take the `whenNotNullable`
2001
- * branch — only `null` and `undefined` are treated as absent. Supports both
2002
- * data-first and data-last (pipeable) call styles.
2003
- *
2004
- * @example
2005
- * ```ts
2006
- * import { NonNullableX } from "@nunofyobiz/effect-extras"
2007
- * import { pipe } from "effect"
2008
- *
2009
- * // Data-first — present value flows through narrowed
2010
- * assert.deepStrictEqual(
2011
- * NonNullableX.match("value", {
2012
- * whenNullable: () => "nullable",
2013
- * whenNotNullable: (value) => value
2014
- * }),
2015
- * "value"
2016
- * )
2017
- *
2018
- * // Data-last — null takes the whenNullable branch
2019
- * assert.deepStrictEqual(
2020
- * pipe(
2021
- * null,
2022
- * NonNullableX.match({
2023
- * whenNullable: () => "nullable",
2024
- * whenNotNullable: (value) => value
2025
- * })
2026
- * ),
2027
- * "nullable"
2028
- * )
2029
- * ```
2030
- *
2031
- * @category pattern matching
2032
- * @since 0.0.0
2033
- */
2034
- declare const match: (<A, B>(handlers: {
2035
- whenNullable: () => B;
2036
- whenNotNullable: (value: NonNullable<A>) => B;
2037
- }) => (value: A) => B) & (<A, B>(value: A, handlers: {
2038
- whenNullable: () => B;
2039
- whenNotNullable: (value: NonNullable<A>) => B;
2040
- }) => B);
2041
- /**
2042
- * Applies `map` to `a` only when it is non-nullish, passing nullish inputs
2043
- * through unchanged.
2044
- *
2045
- * This is the nullable-preserving map: a present value is transformed to `B`,
2046
- * while `null` stays `null` and `undefined` stays `undefined`, so nullability is
2047
- * carried through the transformation. Supports both data-first and data-last
2048
- * (pipeable) call styles.
2049
- *
2050
- * @example
2051
- * ```ts
2052
- * import { NonNullableX } from "@nunofyobiz/effect-extras"
2053
- * import { pipe } from "effect"
2054
- *
2055
- * // Data-first — present value is transformed
2056
- * assert.deepStrictEqual(NonNullableX.map(1, (v: number) => v + 1), 2)
2057
- *
2058
- * // Data-last — nullish passes through unchanged
2059
- * const value: number | null = null
2060
- * assert.deepStrictEqual(
2061
- * pipe(
2062
- * value,
2063
- * NonNullableX.map<number | null, number>((v) => v + 1)
2064
- * ),
2065
- * null
2066
- * )
2067
- * ```
2068
- *
2069
- * @category mapping
2070
- * @since 0.0.0
2071
- */
2072
- 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));
2073
- /**
2074
- * Lifts a total function `(a: A) => B` into one that tolerates nullish input,
2075
- * applying it to present values and passing `null`/`undefined` through unchanged.
2076
- *
2077
- * Where `map` operates on a value, `lift` transforms the function itself,
2078
- * yielding a reusable `(a: A | null | undefined) => B | null | undefined` you can
2079
- * drop into a `pipe`. Use it to adapt a plain transform to a nullable pipeline
2080
- * without wrapping each call site.
2081
- *
2082
- * @example
2083
- * ```ts
2084
- * import { NonNullableX } from "@nunofyobiz/effect-extras"
2085
- * import { Number, pipe } from "effect"
2086
- *
2087
- * const addOne = NonNullableX.lift(Number.sum(1))
2088
- *
2089
- * assert.deepStrictEqual(pipe(1, addOne), 2)
2090
- * assert.deepStrictEqual(pipe(null, addOne), null)
2091
- * assert.deepStrictEqual(pipe(undefined, addOne), undefined)
2092
- * ```
2093
- *
2094
- * @category mapping
2095
- * @since 0.0.0
2096
- */
2097
- declare const lift: <A, B>(map: (a: A) => B) => (a: A | null | undefined) => B | null | undefined;
2098
- /**
2099
- * Extends an `Order.Order<A>` to an `Order.Order<A | null>`, deciding where
2100
- * `null` sorts relative to present values via the `behavior` argument.
2101
- *
2102
- * Pass `"value-null"` to push `null`s to the end and `"null-value"` to pull them
2103
- * to the front; two present values fall back to the wrapped order. Use it to sort
2104
- * collections that mix real values with gaps without a bespoke comparator.
2105
- * Supports both data-first and data-last (pipeable) call styles.
2106
- *
2107
- * @example
2108
- * ```ts
2109
- * import { NonNullableX } from "@nunofyobiz/effect-extras"
2110
- * import { Array, Order, pipe } from "effect"
2111
- *
2112
- * // "value-null" — nulls sorted last
2113
- * assert.deepStrictEqual(
2114
- * pipe(
2115
- * [null, 1, 3, null, 2],
2116
- * Array.sort(NonNullableX.nullableOrder(Order.Number, "value-null"))
2117
- * ),
2118
- * [1, 2, 3, null, null]
2119
- * )
2120
- *
2121
- * // "null-value" — nulls sorted first (data-last)
2122
- * assert.deepStrictEqual(
2123
- * pipe(
2124
- * [null, 1, 3, null, 2],
2125
- * Array.sort(pipe(Order.Number, NonNullableX.nullableOrder("null-value")))
2126
- * ),
2127
- * [null, null, 1, 2, 3]
2128
- * )
2129
- * ```
2130
- *
2131
- * @category ordering
2132
- * @since 0.0.0
2133
- */
2134
- 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>);
2135
-
2136
- declare const NonNullableX_fromNullableOrThrow: typeof fromNullableOrThrow;
2137
- declare const NonNullableX_lift: typeof lift;
2138
- declare const NonNullableX_map: typeof map;
2139
- declare const NonNullableX_match: typeof match;
2140
- declare const NonNullableX_nullableOrder: typeof nullableOrder;
2141
- declare namespace NonNullableX {
2142
- export { NonNullableX_fromNullableOrThrow as fromNullableOrThrow, NonNullableX_lift as lift, NonNullableX_map as map, NonNullableX_match as match, NonNullableX_nullableOrder as nullableOrder };
2143
- }
2144
-
2145
- /**
2146
- * Generic, framework-agnostic extensions to Effect's `Number` module.
2147
- *
2148
- * @since 0.0.0
2149
- */
2150
-
2151
- /**
2152
- * Computes the logarithm of `number` in the given `base`, throwing when the
2153
- * inputs fall outside the domain of `log`.
2154
- *
2155
- * Throws when `number <= 0`, when `base` is `<= 0` or `1`, or when `number` and
2156
- * `base` sit on opposite sides of `1` (a fractional base with `number >= 1`, or
2157
- * a base `>= 1` with `number < 1`) — cases where the real logarithm is
2158
- * undefined or non-finite. Reach for it only when the inputs are already known
2159
- * to be valid.
2160
- *
2161
- * @example
2162
- * ```ts
2163
- * import { pipe } from "effect"
2164
- * import { NumberX } from "@nunofyobiz/effect-extras"
2165
- *
2166
- * // data-first
2167
- * assert.deepStrictEqual(NumberX.unsafeLogBase(8, 2), 3)
2168
- * assert.deepStrictEqual(NumberX.unsafeLogBase(100, 10), 2)
2169
- *
2170
- * // data-last (piped)
2171
- * assert.deepStrictEqual(pipe(8, NumberX.unsafeLogBase(2)), 3)
2172
- *
2173
- * // throws outside the domain of log
2174
- * assert.throws(() => NumberX.unsafeLogBase(0, 2))
2175
- * ```
2176
- *
2177
- * @category unsafe
2178
- * @since 0.0.0
2179
- */
2180
- declare const unsafeLogBase: ((base: number) => (number: number) => number) & ((number: number, base: number) => number);
2181
- /**
2182
- * Expresses `numerator` as a percentage of `total`, throwing on division by
2183
- * zero.
2184
- *
2185
- * Returns `(numerator / total) * 100`. When `total` is `0` the percentage is
2186
- * undefined, so this throws rather than returning `Infinity` or `NaN` — use it
2187
- * only when `total` is known to be non-zero.
2188
- *
2189
- * @example
2190
- * ```ts
2191
- * import { pipe } from "effect"
2192
- * import { NumberX } from "@nunofyobiz/effect-extras"
2193
- *
2194
- * // data-first
2195
- * assert.deepStrictEqual(NumberX.unsafeToPercentOf(1, 2), 50)
2196
- * assert.deepStrictEqual(NumberX.unsafeToPercentOf(2, 1), 200)
2197
- *
2198
- * // data-last (piped)
2199
- * assert.deepStrictEqual(pipe(1, NumberX.unsafeToPercentOf(2)), 50)
2200
- *
2201
- * // throws on division by zero
2202
- * assert.throws(() => NumberX.unsafeToPercentOf(1, 0))
2203
- * ```
2204
- *
2205
- * @category unsafe
2206
- * @since 0.0.0
2207
- */
2208
- declare const unsafeToPercentOf: ((total: number) => (numerator: number) => number) & ((numerator: number, total: number) => number);
2209
- /**
2210
- * Formats `number` with a fixed number of decimal places, returning a `string`.
2211
- *
2212
- * A pipeable wrapper around `Number.prototype.toFixed` — the result is rounded
2213
- * (not truncated) to `numberDigits` decimals and always carries exactly that
2214
- * many digits after the point.
2215
- *
2216
- * @example
2217
- * ```ts
2218
- * import { pipe } from "effect"
2219
- * import { NumberX } from "@nunofyobiz/effect-extras"
2220
- *
2221
- * // data-first
2222
- * assert.deepStrictEqual(NumberX.toFixed(3.236242, 2), "3.24")
2223
- *
2224
- * // data-last (piped)
2225
- * assert.deepStrictEqual(pipe(3.236242, NumberX.toFixed(0)), "3")
2226
- * ```
2227
- *
2228
- * @category conversions
2229
- * @since 0.0.0
2230
- */
2231
- declare const toFixed: ((numberDigits: number) => (number: number) => string) & ((number: number, numberDigits: number) => string);
2232
- /**
2233
- * Rounds `number` to a fixed number of decimal places, returning a `number`.
2234
- *
2235
- * Unlike {@link toFixed}, the result stays a `number` (no trailing zeroes) — it
2236
- * formats via `toFixed` then parses back, which sidesteps the usual
2237
- * floating-point rounding artifacts. See
2238
- * https://stackoverflow.com/a/29494612/22875620.
2239
- *
2240
- * @example
2241
- * ```ts
2242
- * import { pipe } from "effect"
2243
- * import { NumberX } from "@nunofyobiz/effect-extras"
2244
- *
2245
- * // data-first
2246
- * assert.deepStrictEqual(NumberX.roundToDigits(3.236242, 2), 3.24)
2247
- *
2248
- * // data-last (piped)
2249
- * assert.deepStrictEqual(pipe(3.736242, NumberX.roundToDigits(0)), 4)
2250
- * ```
2251
- *
2252
- * @category mapping
2253
- * @since 0.0.0
2254
- */
2255
- declare const roundToDigits: ((numberDigits: number) => (number: number) => number) & ((number: number, numberDigits: number) => number);
2256
- /**
2257
- * Renders `number` as a `string`, left-padded with zeroes to at least
2258
- * `numberDigits` characters.
2259
- *
2260
- * If the number's string representation is already as long as (or longer than)
2261
- * `numberDigits`, it is returned unchanged.
2262
- *
2263
- * @example
2264
- * ```ts
2265
- * import { pipe } from "effect"
2266
- * import { NumberX } from "@nunofyobiz/effect-extras"
2267
- *
2268
- * // data-first
2269
- * assert.deepStrictEqual(NumberX.padLeftZeroes(1, 3), "001")
2270
- *
2271
- * // longer than the target width is returned unchanged
2272
- * assert.deepStrictEqual(NumberX.padLeftZeroes(1000, 3), "1000")
2273
- *
2274
- * // data-last (piped)
2275
- * assert.deepStrictEqual(pipe(10, NumberX.padLeftZeroes(3)), "010")
2276
- * ```
2277
- *
2278
- * @category conversions
2279
- * @since 0.0.0
2280
- */
2281
- declare const padLeftZeroes: ((numberDigits: number) => (number: number) => string) & ((number: number, numberDigits: number) => string);
2282
- /**
2283
- * Converts a `0`-indexed value to its `1`-indexed rank by adding `1`.
2284
- *
2285
- * Handy for presentation where humans count from one (e.g. the element at
2286
- * index `0` is shown as "item 1").
2287
- *
2288
- * @example
2289
- * ```ts
2290
- * import { NumberX } from "@nunofyobiz/effect-extras"
2291
- *
2292
- * assert.deepStrictEqual(NumberX.indexToRank(0), 1)
2293
- * assert.deepStrictEqual(NumberX.indexToRank(4), 5)
2294
- * ```
2295
- *
2296
- * @category mapping
2297
- * @since 0.0.0
2298
- */
2299
- declare const indexToRank: (index: number) => number;
2300
- /**
2301
- * Converts a `0`-indexed column number into its bijective base-26 spreadsheet
2302
- * label (`A`, `B`, …, `Z`, `AA`, `AB`, …).
2303
- *
2304
- * Returns `None` for a negative `index`; every non-negative index maps to a
2305
- * `Some` label. Indexing is `0`-based here, so `0` is `"A"` and `25` is `"Z"`,
2306
- * unlike the `1`-based numbering shown in most spreadsheet references.
2307
- *
2308
- * @example
2309
- * ```ts
2310
- * import { Option } from "effect"
2311
- * import { NumberX } from "@nunofyobiz/effect-extras"
2312
- *
2313
- * assert.deepStrictEqual(NumberX.indexToExcel(0), Option.some("A"))
2314
- * assert.deepStrictEqual(NumberX.indexToExcel(26), Option.some("AA"))
2315
- * assert.deepStrictEqual(NumberX.indexToExcel(-1), Option.none())
2316
- * ```
2317
- *
2318
- * @category conversions
2319
- * @since 0.0.0
2320
- */
2321
- declare const indexToExcel: (index: number) => Option.Option<string>;
2322
-
2323
- declare const NumberX_indexToExcel: typeof indexToExcel;
2324
- declare const NumberX_indexToRank: typeof indexToRank;
2325
- declare const NumberX_padLeftZeroes: typeof padLeftZeroes;
2326
- declare const NumberX_roundToDigits: typeof roundToDigits;
2327
- declare const NumberX_toFixed: typeof toFixed;
2328
- declare const NumberX_unsafeLogBase: typeof unsafeLogBase;
2329
- declare const NumberX_unsafeToPercentOf: typeof unsafeToPercentOf;
2330
- declare namespace NumberX {
2331
- export { NumberX_indexToExcel as indexToExcel, NumberX_indexToRank as indexToRank, NumberX_padLeftZeroes as padLeftZeroes, NumberX_roundToDigits as roundToDigits, NumberX_toFixed as toFixed, NumberX_unsafeLogBase as unsafeLogBase, NumberX_unsafeToPercentOf as unsafeToPercentOf };
2332
- }
2333
-
2334
- /**
2335
- * Generic, framework-agnostic extensions to Effect's `Option` module.
2336
- *
2337
- * @since 0.0.0
2338
- */
2339
-
2340
- /**
2341
- * Combines two `Option`s into an `Option` of a tuple, succeeding only when both
2342
- * are `Some`.
2343
- *
2344
- * Returns `Some([a, b])` when both inputs are `Some`, and `None` if either is
2345
- * `None`. Useful when an operation needs two optional values present at once.
2346
- *
2347
- * @example
2348
- * ```ts
2349
- * import { Option } from "effect"
2350
- * import { OptionX } from "@nunofyobiz/effect-extras"
2351
- *
2352
- * // Both Some — succeeds with the pair
2353
- * assert.deepStrictEqual(
2354
- * OptionX.tupleOf(Option.some(1), Option.some("a")),
2355
- * Option.some([1, "a"]),
2356
- * )
2357
- *
2358
- * // Either None collapses to None
2359
- * assert.deepStrictEqual(
2360
- * OptionX.tupleOf(Option.some(1), Option.none()),
2361
- * Option.none(),
2362
- * )
2363
- * ```
2364
- *
2365
- * @category combinators
2366
- * @since 0.0.0
2367
- */
2368
- declare const tupleOf: (<A>(a: Option.Option<A>) => <B>(b: Option.Option<B>) => Option.Option<[A, B]>) & (<A, B>(a: Option.Option<A>, b: Option.Option<B>) => Option.Option<[A, B]>);
2369
- /**
2370
- * Runs a side effect with the value of an `Option` when it is `Some`, doing
2371
- * nothing when it is `None`.
2372
- *
2373
- * A shorthand for the "if Some, do something" branch of `Option.match` where the
2374
- * `None` case is a no-op. The callback's return value is ignored — `ifSome`
2375
- * always returns `void`.
2376
- *
2377
- * @example
2378
- * ```ts
2379
- * import { Option } from "effect"
2380
- * import { OptionX } from "@nunofyobiz/effect-extras"
2381
- *
2382
- * const log: Array<number> = []
2383
- * OptionX.ifSome(Option.some(1), (value) => log.push(value))
2384
- * OptionX.ifSome(Option.none<number>(), (value) => log.push(value))
2385
- *
2386
- * assert.deepStrictEqual(log, [1])
2387
- * ```
2388
- *
2389
- * @category sequencing
2390
- * @since 0.0.0
2391
- */
2392
- declare const ifSome: (<A>(ifSome: (value: A) => void) => (self: Option.Option<A>) => void) & (<A>(self: Option.Option<A>, ifSome: (value: A) => void) => void);
2393
- /**
2394
- * Runs a side effect with the value of an `Option` when it is `Some`, then
2395
- * returns the `Option` unchanged.
2396
- *
2397
- * The pass-through counterpart of {@link ifSome}: it taps into a `Some` value
2398
- * (for logging, metrics, debugging) without breaking a `pipe` chain, since it
2399
- * returns the original `Option`. For `None` it is a no-op.
2400
- *
2401
- * @example
2402
- * ```ts
2403
- * import { Option, pipe } from "effect"
2404
- * import { OptionX } from "@nunofyobiz/effect-extras"
2405
- *
2406
- * const log: Array<number> = []
2407
- * const result = pipe(
2408
- * Option.some(1),
2409
- * OptionX.inspectSome((value) => log.push(value)),
2410
- * Option.map((value) => value + 1),
2411
- * )
2412
- *
2413
- * assert.deepStrictEqual(result, Option.some(2))
2414
- * assert.deepStrictEqual(log, [1])
2415
- * ```
2416
- *
2417
- * @category sequencing
2418
- * @since 0.0.0
2419
- */
2420
- declare const inspectSome: (<A>(function_: (value: A) => void) => (self: Option.Option<A>) => Option.Option<A>) & (<A>(self: Option.Option<A>, function_: (value: A) => void) => Option.Option<A>);
2421
- /**
2422
- * Normalizes a possibly-nullish `Option` into a plain `Option`, mapping `null`
2423
- * and `undefined` to `None`.
2424
- *
2425
- * Handy at boundaries where an `Option` value might itself arrive as `null` or
2426
- * `undefined` (for example an optional field that holds an `Option`): the result
2427
- * is always a well-formed `Option`, never `null`/`undefined`.
2428
- *
2429
- * @example
2430
- * ```ts
2431
- * import { Option } from "effect"
2432
- * import { OptionX } from "@nunofyobiz/effect-extras"
2433
- *
2434
- * assert.deepStrictEqual(OptionX.fromNullableOption(Option.some(1)), Option.some(1))
2435
- * assert.deepStrictEqual(OptionX.fromNullableOption(null), Option.none())
2436
- * assert.deepStrictEqual(OptionX.fromNullableOption(undefined), Option.none())
2437
- * ```
2438
- *
2439
- * @category constructors
2440
- * @since 0.0.0
2441
- */
2442
- declare const fromNullableOption: <A>(nullableOption: Option.Option<A> | null | undefined) => Option.Option<A>;
2443
- /**
2444
- * Maps the value of an `Option` when it is `Some`, returning `null` when it is
2445
- * `None`.
2446
- *
2447
- * A shorthand for `pipe(self, Option.map(map), Option.getOrNull)`. The `null`
2448
- * fallback makes it especially convenient in JSX/React, where rendering `null`
2449
- * skips output — `mapSomeOrNull(value, (v) => render(v))` replaces a more verbose
2450
- * `Option.match` with `onNone: () => null`.
2451
- *
2452
- * @example
2453
- * ```ts
2454
- * import { Option, pipe } from "effect"
2455
- * import { OptionX } from "@nunofyobiz/effect-extras"
2456
- *
2457
- * // data-first
2458
- * assert.deepStrictEqual(OptionX.mapSomeOrNull(Option.some(1), (v) => v + 1), 2)
2459
- *
2460
- * // None maps to null
2461
- * assert.deepStrictEqual(
2462
- * OptionX.mapSomeOrNull(Option.none<number>(), (v) => v + 1),
2463
- * null,
2464
- * )
2465
- *
2466
- * // data-last (piped)
2467
- * assert.deepStrictEqual(
2468
- * pipe(Option.some(1), OptionX.mapSomeOrNull((v) => v + 1)),
2469
- * 2,
2470
- * )
2471
- * ```
2472
- *
2473
- * @category mapping
2474
- * @since 0.0.0
2475
- */
2476
- declare const mapSomeOrNull: (<A, B>(map: (a: A) => B) => (self: Option.Option<A>) => B | null) & (<A, B>(self: Option.Option<A>, map: (a: A) => B) => B | null);
2477
- /**
2478
- * Maps the value of an `Option` when it is `Some`, returning `undefined` when it
2479
- * is `None`.
2480
- *
2481
- * The `undefined`-returning counterpart of {@link mapSomeOrNull}: a shorthand for
2482
- * `pipe(self, Option.map(map), Option.getOrUndefined)`. Reach for it when the
2483
- * consuming API expects `undefined` rather than `null` for "absent" (for example
2484
- * an optional prop or a value spread into an object).
2485
- *
2486
- * @example
2487
- * ```ts
2488
- * import { Option, pipe } from "effect"
2489
- * import { OptionX } from "@nunofyobiz/effect-extras"
2490
- *
2491
- * // data-first
2492
- * assert.deepStrictEqual(
2493
- * OptionX.mapSomeOrUndefined(Option.some(1), (v) => v + 1),
2494
- * 2,
2495
- * )
2496
- *
2497
- * // None maps to undefined
2498
- * assert.deepStrictEqual(
2499
- * OptionX.mapSomeOrUndefined(Option.none<number>(), (v) => v + 1),
2500
- * undefined,
2501
- * )
2502
- *
2503
- * // data-last (piped)
2504
- * assert.deepStrictEqual(
2505
- * pipe(Option.some(1), OptionX.mapSomeOrUndefined((v) => v + 1)),
2506
- * 2,
2507
- * )
2508
- * ```
2509
- *
2510
- * @category mapping
2511
- * @since 0.0.0
2512
- */
2513
- declare const mapSomeOrUndefined: (<A, B>(map: (a: A) => B) => (self: Option.Option<A>) => B | undefined) & (<A, B>(self: Option.Option<A>, map: (a: A) => B) => B | undefined);
2514
-
2515
- declare const OptionX_fromNullableOption: typeof fromNullableOption;
2516
- declare const OptionX_ifSome: typeof ifSome;
2517
- declare const OptionX_inspectSome: typeof inspectSome;
2518
- declare const OptionX_mapSomeOrNull: typeof mapSomeOrNull;
2519
- declare const OptionX_mapSomeOrUndefined: typeof mapSomeOrUndefined;
2520
- declare const OptionX_tupleOf: typeof tupleOf;
2521
- declare namespace OptionX {
2522
- export { OptionX_fromNullableOption as fromNullableOption, OptionX_ifSome as ifSome, OptionX_inspectSome as inspectSome, OptionX_mapSomeOrNull as mapSomeOrNull, OptionX_mapSomeOrUndefined as mapSomeOrUndefined, OptionX_tupleOf as tupleOf };
2523
- }
2524
-
2525
- /**
2526
- * Generic, framework-agnostic extensions to Effect's `Order` module.
2527
- *
2528
- * @since 0.0.0
2529
- */
2530
-
2531
- /**
2532
- * Builds an `Order.Order` for an enum-like set of values from an explicit rank
2533
- * table, sorting each value by its assigned numeric rank.
2534
- *
2535
- * Use it when a union of string (or other `PropertyKey`) literals has a natural
2536
- * priority that isn't its alphabetical order — pass a record mapping every
2537
- * member to a rank and the resulting order sorts ascending by that rank.
2538
- *
2539
- * @example
2540
- * ```ts
2541
- * import { OrderX } from "@nunofyobiz/effect-extras"
2542
- * import { Array } from "effect"
2543
- *
2544
- * const byAge = OrderX.rankedEnum({ child: 0, parent: 1, grandparent: 2 })
2545
- *
2546
- * assert.deepStrictEqual(
2547
- * Array.sort(["parent", "grandparent", "child"], byAge),
2548
- * ["child", "parent", "grandparent"]
2549
- * )
2550
- * ```
2551
- *
2552
- * @category ordering
2553
- * @since 0.0.0
2554
- */
2555
- declare const rankedEnum: <const A extends PropertyKey>(ranks: Record<A, number>) => Order.Order<A>;
2556
-
2557
- declare const OrderX_rankedEnum: typeof rankedEnum;
2558
- declare namespace OrderX {
2559
- export { OrderX_rankedEnum as rankedEnum };
2560
- }
2561
-
2562
- /**
2563
- * Generic, framework-agnostic extensions to Effect's `Predicate` module.
2564
- *
2565
- * @since 0.0.0
2566
- */
2567
-
2568
- /**
2569
- * Runs a refinement against `value` and branches on the result, passing the
2570
- * narrowed value to the `whenTrue` handler.
2571
- *
2572
- * It pairs a `Predicate.Refinement<A, B>` with two continuations so the success
2573
- * branch receives `value` already narrowed to `B`, replacing an `if`/`else` that
2574
- * would otherwise re-check or cast. Supports both data-first and data-last
2575
- * (pipeable) call styles.
2576
- *
2577
- * @example
2578
- * ```ts
2579
- * import { PredicateX } from "@nunofyobiz/effect-extras"
2580
- * import { Predicate, pipe } from "effect"
2581
- *
2582
- * // Data-first
2583
- * assert.deepStrictEqual(
2584
- * PredicateX.matchRefine("hello", Predicate.isString, {
2585
- * whenTrue: (value) => `String: ${value}`,
2586
- * whenFalse: () => "Not a string"
2587
- * }),
2588
- * "String: hello"
2589
- * )
2590
- *
2591
- * // Data-last (pipeable)
2592
- * assert.deepStrictEqual(
2593
- * pipe(
2594
- * 42,
2595
- * PredicateX.matchRefine(Predicate.isString, {
2596
- * whenTrue: (value) => `String: ${value}`,
2597
- * whenFalse: () => "Not a string"
2598
- * })
2599
- * ),
2600
- * "Not a string"
2601
- * )
2602
- * ```
2603
- *
2604
- * @category pattern matching
2605
- * @since 0.0.0
2606
- */
2607
- declare const matchRefine: (<A, B extends A, C>(predicate: Predicate.Refinement<A, B>, handlers: {
2608
- whenFalse: () => C;
2609
- whenTrue: (value: B) => C;
2610
- }) => (value: A) => C) & (<A, B extends A, C>(value: A, predicate: Predicate.Refinement<A, B>, handlers: {
2611
- whenFalse: () => C;
2612
- whenTrue: (value: B) => C;
2613
- }) => C);
2614
- /**
2615
- * Refines an `unknown` value to a non-empty `string`, returning `true` only when
2616
- * the value is present, is a `string`, and has at least one character.
2617
- *
2618
- * This is the compound guard the repo's conventions call for: it folds
2619
- * `Predicate.isNotNullish`, `Predicate.isString`, and `String.isNonEmpty` into a
2620
- * single reusable refinement so call sites get `value is string` narrowing
2621
- * without restating the three checks.
2622
- *
2623
- * @example
2624
- * ```ts
2625
- * import { PredicateX } from "@nunofyobiz/effect-extras"
2626
- *
2627
- * assert.deepStrictEqual(PredicateX.isNonEmptyString("hello"), true)
2628
- * assert.deepStrictEqual(PredicateX.isNonEmptyString(""), false)
2629
- * assert.deepStrictEqual(PredicateX.isNonEmptyString(null), false)
2630
- * assert.deepStrictEqual(PredicateX.isNonEmptyString(123), false)
2631
- * ```
2632
- *
2633
- * @category refinements
2634
- * @since 0.0.0
2635
- */
2636
- declare function isNonEmptyString(value: unknown): value is string;
2637
-
2638
- declare const PredicateX_isNonEmptyString: typeof isNonEmptyString;
2639
- declare const PredicateX_matchRefine: typeof matchRefine;
2640
- declare namespace PredicateX {
2641
- export { PredicateX_isNonEmptyString as isNonEmptyString, PredicateX_matchRefine as matchRefine };
2642
- }
2643
-
2644
- /**
2645
- * Helpers for working with native `Promise`s.
2646
- *
2647
- * @since 0.0.0
2648
- */
2649
- /**
2650
- * Discards the resolved value of a `Promise`, returning a `Promise<void>` that
2651
- * resolves once the original settles.
2652
- *
2653
- * Useful when you await a promise only for its side effect and want the result
2654
- * type to reflect that nothing meaningful is produced — for example when an API
2655
- * expects a `Promise<void>` or when narrowing a value-bearing promise to keep
2656
- * call sites from accidentally depending on the resolved value. A rejection of
2657
- * the original promise still propagates.
2658
- *
2659
- * @example
2660
- * ```ts
2661
- * import { PromiseX } from "@nunofyobiz/effect-extras"
2662
- *
2663
- * const run = async (): Promise<void> => {
2664
- * const result = await PromiseX.asVoid(Promise.resolve(42))
2665
- * assert.deepStrictEqual(result, undefined)
2666
- * }
2667
- *
2668
- * void run()
2669
- * ```
2670
- *
2671
- * @category conversions
2672
- * @since 0.0.0
2673
- */
2674
- declare const asVoid: <T>(promise: Promise<T>) => Promise<void>;
2675
-
2676
- declare const PromiseX_asVoid: typeof asVoid;
2677
- declare namespace PromiseX {
2678
- export { PromiseX_asVoid as asVoid };
2679
- }
2680
-
2681
- /**
2682
- * Generic, framework-agnostic extensions to Effect's `Record` module.
2683
- *
2684
- * @since 0.0.0
2685
- */
2686
-
2687
- /**
2688
- * Returns `true` when `record` has at least one entry, narrowing it to a
2689
- * known-non-empty `Record`.
2690
- *
2691
- * The negation of `Record.isEmptyRecord`, packaged as a type guard so it reads
2692
- * naturally at call sites that want to branch on "this record has something in
2693
- * it" without a manual `!Record.isEmptyRecord(...)`.
2694
- *
2695
- * @example
2696
- * ```ts
2697
- * import { RecordX } from "@nunofyobiz/effect-extras"
2698
- *
2699
- * assert.deepStrictEqual(RecordX.isNonEmptyRecord({ a: 1 }), true)
2700
- * assert.deepStrictEqual(RecordX.isNonEmptyRecord({}), false)
2701
- * ```
2702
- *
2703
- * @category guards
2704
- * @since 0.0.0
2705
- */
2706
- declare const isNonEmptyRecord: <K extends PropertyKey, V>(record: Record<K, V>) => record is Record<K, V>;
2707
- /**
2708
- * Modifies the value at `key` in `self` with `f`, leaving the record unchanged
2709
- * if the key doesn't exist.
2710
- *
2711
- * v4's `Record.modify` returns `Option<Record>` — `None` when the key is
2712
- * absent. This helper picks the "do nothing if absent" semantics that v3's
2713
- * `Record.modify` had implicitly, and that most call sites assume. The modifier
2714
- * is never invoked when the key is missing.
2715
- *
2716
- * @example
2717
- * ```ts
2718
- * import { pipe } from "effect"
2719
- * import { RecordX } from "@nunofyobiz/effect-extras"
2720
- *
2721
- * // data-first
2722
- * assert.deepStrictEqual(
2723
- * RecordX.modifyIfExists({ a: 1, b: 2 }, "b", (n) => n * 10),
2724
- * { a: 1, b: 20 },
2725
- * )
2726
- *
2727
- * // a missing key leaves the record untouched
2728
- * const counts: Record<string, number> = { a: 1, b: 2 }
2729
- * assert.deepStrictEqual(
2730
- * RecordX.modifyIfExists(counts, "missing", (n) => n + 1),
2731
- * { a: 1, b: 2 },
2732
- * )
2733
- *
2734
- * // data-last (pipeable)
2735
- * assert.deepStrictEqual(
2736
- * pipe({ a: 1, b: 2 }, RecordX.modifyIfExists("a", (n) => n * 10)),
2737
- * { a: 10, b: 2 },
2738
- * )
2739
- * ```
2740
- *
2741
- * @category mapping
2742
- * @since 0.0.0
2743
- */
2744
- declare const modifyIfExists: {
2745
- <K extends string, A>(key: NoInfer<K>, f: (a: A) => A): (self: Record<K, A>) => Record<K, A>;
2746
- <K extends string, A>(self: Record<K, A>, key: NoInfer<K>, f: (a: A) => A): Record<K, A>;
2747
- };
2748
- /**
2749
- * Returns the smallest value of `record` (per `order`) that matches
2750
- * `predicate`, narrowed to the refined type `B`, or `Option.none()` if none
2751
- * match.
2752
- *
2753
- * The `Record` counterpart of `ArrayX.takeFirstWhere`: it considers only the
2754
- * record's values, keeps those satisfying `predicate`, and returns the minimum
2755
- * of them by `order`. Keys are ignored entirely.
2756
- *
2757
- * @example
2758
- * ```ts
2759
- * import { Option, Order, pipe } from "effect"
2760
- * import { RecordX } from "@nunofyobiz/effect-extras"
2761
- *
2762
- * const isEven = (n: number): n is number => n % 2 === 0
2763
- *
2764
- * // data-first
2765
- * assert.deepStrictEqual(
2766
- * RecordX.takeFirstWhere({ a: 3, b: 4, c: 2 }, isEven, Order.Number),
2767
- * Option.some(2),
2768
- * )
2769
- *
2770
- * // data-last (pipeable); no even values yields None
2771
- * assert.deepStrictEqual(
2772
- * pipe({ a: 1, b: 3 }, RecordX.takeFirstWhere(isEven, Order.Number)),
2773
- * Option.none(),
2774
- * )
2775
- * ```
2776
- *
2777
- * @category getters
2778
- * @since 0.0.0
2779
- */
2780
- declare const takeFirstWhere: (<K extends PropertyKey, A, B extends A>(predicate: Predicate.Refinement<A, B>, order: Order.Order<B>) => (record: Record<K, A>) => Option.Option<B>) & (<K extends PropertyKey, A, B extends A>(record: Record<K, A>, predicate: Predicate.Refinement<A, B>, order: Order.Order<B>) => Option.Option<B>);
2781
- /**
2782
- * Returns the largest value of `record` (per `order`) that matches `predicate`,
2783
- * narrowed to the refined type `B`, or `Option.none()` if none match.
2784
- *
2785
- * The mirror of {@link takeFirstWhere}: it considers only the record's values,
2786
- * keeps those satisfying `predicate`, and returns the maximum of them by
2787
- * `order`. Keys are ignored entirely.
2788
- *
2789
- * @example
2790
- * ```ts
2791
- * import { Option, Order, pipe } from "effect"
2792
- * import { RecordX } from "@nunofyobiz/effect-extras"
2793
- *
2794
- * const isEven = (n: number): n is number => n % 2 === 0
2795
- *
2796
- * // data-first
2797
- * assert.deepStrictEqual(
2798
- * RecordX.takeLastWhere({ a: 3, b: 4, c: 2 }, isEven, Order.Number),
2799
- * Option.some(4),
2800
- * )
2801
- *
2802
- * // data-last (pipeable); no even values yields None
2803
- * assert.deepStrictEqual(
2804
- * pipe({ a: 1, b: 3 }, RecordX.takeLastWhere(isEven, Order.Number)),
2805
- * Option.none(),
2806
- * )
2807
- * ```
2808
- *
2809
- * @category getters
2810
- * @since 0.0.0
2811
- */
2812
- declare const takeLastWhere: (<K extends PropertyKey, A, B extends A>(predicate: Predicate.Refinement<A, B>, order: Order.Order<B>) => (record: Record<K, A>) => Option.Option<B>) & (<K extends PropertyKey, A, B extends A>(record: Record<K, A>, predicate: Predicate.Refinement<A, B>, order: Order.Order<B>) => Option.Option<B>);
2813
- /**
2814
- * Returns the largest value of `record` according to `order`, wrapped in an
2815
- * `Option` so empty records are handled safely.
2816
- *
2817
- * Sorts the record's values by `order` and takes the last one, yielding
2818
- * `Option.none()` when the record is empty and `Option.some(max)` otherwise.
2819
- * Keys are ignored — only values participate in the ordering.
2820
- *
2821
- * @example
2822
- * ```ts
2823
- * import { Option, Order, pipe } from "effect"
2824
- * import { RecordX } from "@nunofyobiz/effect-extras"
2825
- *
2826
- * // data-first
2827
- * assert.deepStrictEqual(
2828
- * RecordX.takeLast({ a: 3, b: 5, c: 1 }, Order.Number),
2829
- * Option.some(5),
2830
- * )
2831
- *
2832
- * // data-last (pipeable); empty record yields None
2833
- * assert.deepStrictEqual(
2834
- * pipe({}, RecordX.takeLast(Order.Number)),
2835
- * Option.none(),
2836
- * )
2837
- * ```
2838
- *
2839
- * @category getters
2840
- * @since 0.0.0
2841
- */
2842
- declare const takeLast: (<K extends PropertyKey, A>(order: Order.Order<A>) => (record: Record<K, A>) => Option.Option<A>) & (<K extends PropertyKey, A>(record: Record<K, A>, order: Order.Order<A>) => Option.Option<A>);
2843
- /**
2844
- * Re-types the keys of a `Record` to a different key type `K2` without touching
2845
- * the runtime value.
2846
- *
2847
- * A purely type-level reinterpretation: the record is returned as-is, but the
2848
- * compiler now treats its keys as `K2` instead of the inferred `K1`. Use it at a
2849
- * boundary where you know the keys conform to a narrower branded or literal key
2850
- * type that TypeScript can't infer from the value alone. It performs no
2851
- * validation — the caller is responsible for the keys actually matching `K2`.
2852
- *
2853
- * @example
2854
- * ```ts
2855
- * import { RecordX } from "@nunofyobiz/effect-extras"
2856
- *
2857
- * type UserId = string & { readonly _brand: "UserId" }
2858
- *
2859
- * const byId: Record<string, number> = { u1: 10, u2: 20 }
2860
- * const branded = RecordX.keysAs<UserId>()(byId)
2861
- *
2862
- * // Same runtime value, keys now seen as `UserId`
2863
- * assert.deepStrictEqual(branded, { u1: 10, u2: 20 })
2864
- * ```
2865
- *
2866
- * @category conversions
2867
- * @since 0.0.0
2868
- */
2869
- declare const keysAs: <K2 extends PropertyKey>() => <K1 extends PropertyKey, V>(record: Record<K1, V>) => Record<K2, V>;
2870
- /**
2871
- * Returns the value at `key` in `record`, throwing an `Error` if the key is
2872
- * absent.
2873
- *
2874
- * The unsafe, get-or-explode counterpart to `Record.get` (which returns an
2875
- * `Option`). The thrown error names the missing key and lists the record's
2876
- * existing keys to aid debugging. Reach for {@link getOrThrowWith} when you need
2877
- * a custom error; prefer `Record.get` whenever absence is a real possibility.
2878
- *
2879
- * @example
2880
- * ```ts
2881
- * import { pipe } from "effect"
2882
- * import { RecordX } from "@nunofyobiz/effect-extras"
2883
- *
2884
- * const record: Record<string, number> = { a: 1, b: 2 }
2885
- *
2886
- * // data-first
2887
- * assert.deepStrictEqual(RecordX.getOrThrow(record, "a"), 1)
2888
- *
2889
- * // data-last (pipeable)
2890
- * assert.deepStrictEqual(pipe(record, RecordX.getOrThrow("b")), 2)
2891
- *
2892
- * // missing key throws
2893
- * assert.throws(() => RecordX.getOrThrow(record, "missing"))
2894
- * ```
2895
- *
2896
- * @category unsafe
2897
- * @since 0.0.0
2898
- */
2899
- declare const getOrThrow: (<K extends string | symbol>(key: K) => <V>(record: Record<K, V>) => V) & (<K extends string | symbol, V>(record: Record<K, V>, key: K) => V);
2900
- /**
2901
- * Returns the value at `key` in `record`, throwing the result of `onNone(key)`
2902
- * if the key is absent.
2903
- *
2904
- * Like {@link getOrThrow}, but lets the caller supply the thrown value (an
2905
- * `Error`, a string, or any custom failure) computed from the missing key. Use
2906
- * it when the default "key not found" message isn't descriptive enough for the
2907
- * call site.
2908
- *
2909
- * @example
2910
- * ```ts
2911
- * import { pipe } from "effect"
2912
- * import { RecordX } from "@nunofyobiz/effect-extras"
2913
- *
2914
- * const record: Record<string, number> = { a: 1 }
2915
- * const onNone = (key: string) => new Error(`no ${key}`)
2916
- *
2917
- * // data-first
2918
- * assert.deepStrictEqual(RecordX.getOrThrowWith(record, "a", onNone), 1)
2919
- *
2920
- * // data-last (pipeable)
2921
- * assert.deepStrictEqual(pipe(record, RecordX.getOrThrowWith("a", onNone)), 1)
2922
- *
2923
- * // missing key throws the custom error
2924
- * assert.throws(() => RecordX.getOrThrowWith(record, "missing", onNone))
2925
- * ```
2926
- *
2927
- * @category unsafe
2928
- * @since 0.0.0
2929
- */
2930
- declare const getOrThrowWith: (<K extends string | symbol>(key: K, onNone: (key: K) => unknown) => <V>(record: Record<K, V>) => V) & (<K extends string | symbol, V>(record: Record<K, V>, key: K, onNone: (key: K) => unknown) => V);
2931
- /**
2932
- * Inserts or updates the value at `key`, deriving the new value from the current
2933
- * one via `upsert`.
2934
- *
2935
- * The `upsert` function receives an `Option` of the existing value —
2936
- * `Option.some(value)` when the key is present, `Option.none()` when it's
2937
- * absent — and returns the value to store. This unifies "insert if missing" and
2938
- * "update if present" into a single pass, with `Option.match` as the natural way
2939
- * to handle both cases.
2940
- *
2941
- * @example
2942
- * ```ts
2943
- * import { Option, pipe } from "effect"
2944
- * import { RecordX } from "@nunofyobiz/effect-extras"
2945
- *
2946
- * const bump = Option.match({
2947
- * onNone: () => 1,
2948
- * onSome: (n: number) => n + 1,
2949
- * })
2950
- *
2951
- * // data-first: updates an existing entry
2952
- * assert.deepStrictEqual(RecordX.upsert({ a: 1 }, "a", bump), { a: 2 })
2953
- *
2954
- * // data-last (pipeable): inserts a missing entry
2955
- * const counts: Record<string, number> = { a: 1 }
2956
- * assert.deepStrictEqual(pipe(counts, RecordX.upsert("b", bump)), {
2957
- * a: 1,
2958
- * b: 1,
2959
- * })
2960
- * ```
2961
- *
2962
- * @category mapping
2963
- * @since 0.0.0
2964
- */
2965
- declare const upsert: (<K extends string | symbol, V>(key: K, upsert: (existingValue: Option.Option<V>) => V) => (record: Record<K, V>) => Record<K, V>) & (<K extends string | symbol, V>(record: Record<K, V>, key: K, upsert: (existingValue: Option.Option<V>) => V) => Record<K, V>);
2966
- /**
2967
- * Indexes an iterable of values into a `Record`, keying each value by the result
2968
- * of `identify`.
2969
- *
2970
- * Builds a lookup table from a collection: every value is stored under the key
2971
- * `identify(value)`. When two values produce the same key the later one wins, so
2972
- * the result holds the last value seen per key. Useful for turning a list of
2973
- * records into a by-id map.
2974
- *
2975
- * @example
2976
- * ```ts
2977
- * import { pipe } from "effect"
2978
- * import { RecordX } from "@nunofyobiz/effect-extras"
2979
- *
2980
- * const items = [
2981
- * { id: "a", n: 1 },
2982
- * { id: "b", n: 2 },
2983
- * { id: "a", n: 3 }, // wins over the earlier "a"
2984
- * ]
2985
- *
2986
- * // data-first
2987
- * assert.deepStrictEqual(
2988
- * RecordX.collectBy(items, (item) => item.id),
2989
- * { a: { id: "a", n: 3 }, b: { id: "b", n: 2 } },
2990
- * )
2991
- *
2992
- * // data-last (pipeable)
2993
- * assert.deepStrictEqual(
2994
- * pipe(items, RecordX.collectBy((item) => item.id)),
2995
- * { a: { id: "a", n: 3 }, b: { id: "b", n: 2 } },
2996
- * )
2997
- * ```
2998
- *
2999
- * @category constructors
3000
- * @since 0.0.0
3001
- */
3002
- declare const collectBy: (<K extends string | symbol, V>(identify: (v: V) => K) => (values: Iterable<V>) => Record<K, V>) & (<K extends string | symbol, V>(values: Iterable<V>, identify: (v: V) => K) => Record<K, V>);
3003
-
3004
- declare const RecordX_collectBy: typeof collectBy;
3005
- declare const RecordX_getOrThrow: typeof getOrThrow;
3006
- declare const RecordX_getOrThrowWith: typeof getOrThrowWith;
3007
- declare const RecordX_isNonEmptyRecord: typeof isNonEmptyRecord;
3008
- declare const RecordX_keysAs: typeof keysAs;
3009
- declare const RecordX_modifyIfExists: typeof modifyIfExists;
3010
- declare const RecordX_takeFirstWhere: typeof takeFirstWhere;
3011
- declare const RecordX_takeLast: typeof takeLast;
3012
- declare const RecordX_takeLastWhere: typeof takeLastWhere;
3013
- declare const RecordX_upsert: typeof upsert;
3014
- declare namespace RecordX {
3015
- export { RecordX_collectBy as collectBy, RecordX_getOrThrow as getOrThrow, RecordX_getOrThrowWith as getOrThrowWith, RecordX_isNonEmptyRecord as isNonEmptyRecord, RecordX_keysAs as keysAs, RecordX_modifyIfExists as modifyIfExists, RecordX_takeFirstWhere as takeFirstWhere, RecordX_takeLast as takeLast, RecordX_takeLastWhere as takeLastWhere, RecordX_upsert as upsert };
3016
- }
3017
-
3018
- /**
3019
- * Generic, framework-agnostic extensions to Effect's `Result` module.
3020
- *
3021
- * @since 0.0.0
3022
- */
3023
-
3024
- /**
3025
- * Lifts an `Option` into a `Result` with a `void` failure: `Some(value)` becomes
3026
- * `Result.succeed(value)` and `None` becomes `Result.failVoid`.
3027
- *
3028
- * Useful in v4 where `Array.filterMap` and `Record.filterMap` expect
3029
- * `Result`-returning predicates (a `Success` keeps the value, a `Failure` drops
3030
- * it); in v3 those APIs accepted `Option`-returning predicates directly:
3031
- *
3032
- * ```ts
3033
- * import { Array } from "effect"
3034
- * import { ResultX } from "@nunofyobiz/effect-extras"
3035
- *
3036
- * declare const items: ReadonlyArray<number>
3037
- * declare const maybeTransform: (item: number) => import("effect").Option.Option<string>
3038
- *
3039
- * // v3: Array.filterMap(items, (item) => maybeTransform(item))
3040
- * // v4:
3041
- * Array.filterMap(items, (item) => ResultX.fromOption(maybeTransform(item)))
3042
- * ```
3043
- *
3044
- * Effect ships `Result.fromOption(option, onNone)` which requires a non-`void`
3045
- * failure value; this helper specializes to the common "drop the item, no error
3046
- * needed" case used by `filterMap`.
3047
- *
3048
- * @example
3049
- * ```ts
3050
- * import { Option, Result } from "effect"
3051
- * import { ResultX } from "@nunofyobiz/effect-extras"
3052
- *
3053
- * assert.deepStrictEqual(
3054
- * ResultX.fromOption(Option.some(1)),
3055
- * Result.succeed(1),
3056
- * )
3057
- * assert.deepStrictEqual(
3058
- * ResultX.fromOption(Option.none<number>()),
3059
- * Result.failVoid,
3060
- * )
3061
- * ```
3062
- *
3063
- * @category conversions
3064
- * @since 0.0.0
3065
- */
3066
- declare const fromOption: <A>(option: Option.Option<A>) => Result.Result<A, void>;
3067
-
3068
- declare const ResultX_fromOption: typeof fromOption;
3069
- declare namespace ResultX {
3070
- export { ResultX_fromOption as fromOption };
3071
- }
3072
-
3073
- /**
3074
- * Generic, framework-agnostic extensions to Effect's `Schema` module.
3075
- *
3076
- * @since 0.0.0
3077
- */
3078
-
3079
- /**
3080
- * A `Schema` for a non-empty string that is trimmed on both decode and encode.
3081
- *
3082
- * Leading and trailing whitespace is stripped, and the resulting value must be
3083
- * non-empty — so a whitespace-only input (e.g. `" "`) fails the
3084
- * `NonEmptyString` refinement after trimming. Use it wherever user-supplied text
3085
- * should be normalized and guaranteed to carry content.
3086
- *
3087
- * @example
3088
- * ```ts
3089
- * import { Effect, Schema } from "effect"
3090
- * import { SchemaX } from "@nunofyobiz/effect-extras"
3091
- *
3092
- * const decoded = Effect.runSync(
3093
- * Schema.decodeEffect(SchemaX.TrimmedNonEmptyString)(" hello "),
3094
- * )
3095
- * assert.deepStrictEqual(decoded, "hello")
3096
- * ```
3097
- *
3098
- * @category constructors
3099
- * @since 0.0.0
3100
- */
3101
- declare const TrimmedNonEmptyString: Schema.decodeTo<Schema.toType<Schema.NonEmptyString>, Schema.NonEmptyString, never, never>;
3102
- /**
3103
- * A `Schema` for a URL-safe file path built on top of {@link
3104
- * TrimmedNonEmptyString}.
3105
- *
3106
- * On decode the path is `decodeURIComponent`-ed (percent-escapes are expanded);
3107
- * on encode it is `encodeURIComponent`-ed back into its URL-safe form. The
3108
- * underlying value is also trimmed and required to be non-empty. Use it at the
3109
- * boundary between stored/transmitted encoded paths and the decoded paths your
3110
- * code works with.
3111
- *
3112
- * @example
3113
- * ```ts
3114
- * import { Effect, Schema } from "effect"
3115
- * import { SchemaX } from "@nunofyobiz/effect-extras"
3116
- *
3117
- * // Decoding expands percent-escapes
3118
- * const decoded = Effect.runSync(
3119
- * Schema.decodeEffect(SchemaX.URLSafeFilePath)("a%2Fb.txt"),
3120
- * )
3121
- * assert.deepStrictEqual(decoded, "a/b.txt")
3122
- *
3123
- * // Encoding produces the URL-safe form
3124
- * const encoded = Effect.runSync(
3125
- * Schema.encodeEffect(SchemaX.URLSafeFilePath)("a/b.txt"),
3126
- * )
3127
- * assert.deepStrictEqual(encoded, "a%2Fb.txt")
3128
- * ```
3129
- *
3130
- * @category constructors
3131
- * @since 0.0.0
3132
- */
3133
- declare const URLSafeFilePath: Schema.decodeTo<Schema.toType<Schema.decodeTo<Schema.toType<Schema.NonEmptyString>, Schema.NonEmptyString, never, never>>, Schema.decodeTo<Schema.toType<Schema.NonEmptyString>, Schema.NonEmptyString, never, never>, never, never>;
3134
- /**
3135
- * Transforms a `bigint` `Schema` so its value is clamped to be non-negative,
3136
- * mapping any value below `0n` up to `0n` on both decode and encode.
3137
- *
3138
- * Unlike a refinement that *rejects* negative input, this *coerces* it: a
3139
- * negative `bigint` decodes to `0n` rather than failing. Apply it to a `bigint`
3140
- * schema whenever negative magnitudes are meaningless and should be floored at
3141
- * zero rather than treated as errors.
3142
- *
3143
- * @example
3144
- * ```ts
3145
- * import { Effect, Schema } from "effect"
3146
- * import { SchemaX } from "@nunofyobiz/effect-extras"
3147
- *
3148
- * const NonNegative = SchemaX.nonNegativeBigInt(Schema.BigInt)
3149
- *
3150
- * // Negative values are clamped up to 0n
3151
- * assert.deepStrictEqual(
3152
- * Effect.runSync(Schema.decodeEffect(NonNegative)(-5n)),
3153
- * 0n,
3154
- * )
3155
- *
3156
- * // Non-negative values pass through unchanged
3157
- * assert.deepStrictEqual(
3158
- * Effect.runSync(Schema.decodeEffect(NonNegative)(7n)),
3159
- * 7n,
3160
- * )
3161
- * ```
3162
- *
3163
- * @category combinators
3164
- * @since 0.0.0
3165
- */
3166
- declare const nonNegativeBigInt: <S extends Schema.Schema<bigint>>(schema: S) => Schema.decodeTo<Schema.toType<S>, S, never, never>;
3167
- /**
3168
- * Extracts the "constructor input" type of a `Schema` — what `.make({...})`
3169
- * accepts.
3170
- *
3171
- * Differs from `S["Type"]` (the decoded type) in that fields carrying
3172
- * constructor defaults (e.g. an `Overrideable` timestamp) are *optional* in
3173
- * `MakeIn` but *required* in `Type`. Use it in signatures that accept a value to
3174
- * construct, so callers can pass a plain object literal without supplying the
3175
- * defaulted, override-branded fields.
3176
- *
3177
- * @example
3178
- * ```ts
3179
- * import { Schema } from "effect"
3180
- * import { SchemaX } from "@nunofyobiz/effect-extras"
3181
- *
3182
- * const Person = Schema.Struct({ name: Schema.String, age: Schema.Number })
3183
- *
3184
- * const input: SchemaX.MakeIn<typeof Person> = { name: "Ada", age: 36 }
3185
- *
3186
- * assert.deepStrictEqual(input, { name: "Ada", age: 36 })
3187
- * ```
3188
- *
3189
- * @category models
3190
- * @since 0.0.0
3191
- */
3192
- type MakeIn<S extends {
3193
- readonly "~type.make.in": unknown;
3194
- }> = S["~type.make.in"];
3195
- /**
3196
- * Returns a new `Schema.Struct` containing only the named `keys` of `schema`.
3197
- *
3198
- * Restores the v3 ergonomics of `mySchema.pick("a", "b")` — v4 removed the
3199
- * `.pick(...)` method from `Schema.Struct` instances, so this rebuilds it on top
3200
- * of v4's `mapFields` primitive. Each picked field keeps its original schema,
3201
- * including any refinements.
3202
- *
3203
- * @example
3204
- * ```ts
3205
- * import { Effect, Schema } from "effect"
3206
- * import { SchemaX } from "@nunofyobiz/effect-extras"
3207
- *
3208
- * const Source = Schema.Struct({
3209
- * a: Schema.Number,
3210
- * b: Schema.String,
3211
- * c: Schema.Boolean,
3212
- * })
3213
- *
3214
- * const Picked = SchemaX.pick(Source, "a", "b")
3215
- *
3216
- * const decoded = Effect.runSync(
3217
- * Schema.decodeEffect(Picked)({ a: 1, b: "hi" }),
3218
- * )
3219
- * assert.deepStrictEqual(decoded, { a: 1, b: "hi" })
3220
- * ```
3221
- *
3222
- * @category combinators
3223
- * @since 0.0.0
3224
- */
3225
- declare const pick: <const Fields extends Schema.Struct.Fields, const Keys extends readonly (keyof Fields & string)[]>(schema: Schema.Struct<Fields>, ...keys: Keys) => Schema.Struct<Pick<Fields, Keys[number]>>;
3226
- /**
3227
- * Returns a new `Schema.Struct` with the named `keys` of `schema` removed.
3228
- *
3229
- * The complement of {@link pick}, restoring the v3 ergonomics of
3230
- * `mySchema.omit("a")` that v4 dropped from `Schema.Struct` instances. Every
3231
- * surviving field keeps its original schema, including any refinements.
3232
- *
3233
- * @example
3234
- * ```ts
3235
- * import { Effect, Schema } from "effect"
3236
- * import { SchemaX } from "@nunofyobiz/effect-extras"
3237
- *
3238
- * const Source = Schema.Struct({
3239
- * a: Schema.Number,
3240
- * b: Schema.String,
3241
- * c: Schema.Boolean,
3242
- * })
3243
- *
3244
- * const Omitted = SchemaX.omit(Source, "c")
3245
- *
3246
- * const decoded = Effect.runSync(
3247
- * Schema.decodeEffect(Omitted)({ a: 1, b: "hi" }),
3248
- * )
3249
- * assert.deepStrictEqual(decoded, { a: 1, b: "hi" })
3250
- * ```
3251
- *
3252
- * @category combinators
3253
- * @since 0.0.0
3254
- */
3255
- declare const omit: <const Fields extends Schema.Struct.Fields, const Keys extends readonly (keyof Fields & string)[]>(schema: Schema.Struct<Fields>, ...keys: Keys) => Schema.Struct<Omit<Fields, Keys[number]>>;
3256
- /**
3257
- * Returns a new `Schema.Struct` in which every field of `schema` is made
3258
- * optional.
3259
- *
3260
- * Restores the v3 `Schema.partial(mySchema)` behaviour that v4 removed, by
3261
- * wrapping each field in `Schema.optional`. A decoded value may therefore omit
3262
- * any field; fields that *are* present still have to satisfy their original
3263
- * schema, refinements included.
3264
- *
3265
- * @example
3266
- * ```ts
3267
- * import { Effect, Schema } from "effect"
3268
- * import { SchemaX } from "@nunofyobiz/effect-extras"
3269
- *
3270
- * const Source = Schema.Struct({ a: Schema.Number, b: Schema.String })
3271
- * const Partial = SchemaX.partial(Source)
3272
- *
3273
- * // All fields may be absent
3274
- * assert.deepStrictEqual(Effect.runSync(Schema.decodeEffect(Partial)({})), {})
3275
- *
3276
- * // A present subset still decodes
3277
- * assert.deepStrictEqual(
3278
- * Effect.runSync(Schema.decodeEffect(Partial)({ a: 1 })),
3279
- * { a: 1 },
3280
- * )
3281
- * ```
3282
- *
3283
- * @category combinators
3284
- * @since 0.0.0
3285
- */
3286
- declare const partial: <Fields extends Schema.Struct.Fields>(schema: Schema.Struct<Fields>) => Schema.Struct<{ [K in keyof Fields]: Schema.optional<Fields[K]>; }>;
3287
- /**
3288
- * Returns a new `Schema.Struct` containing only the named `keys` of `schema`,
3289
- * with every picked field made optional.
3290
- *
3291
- * Equivalent to `partial(pick(schema, ...keys))`, but reads more directly for
3292
- * the common "partial update over a subset of fields" pattern: select the
3293
- * mutable fields of an entity, then allow any of them to be omitted in the
3294
- * update payload. Composes {@link pick} and {@link partial} in one call.
3295
- *
3296
- * @example
3297
- * ```ts
3298
- * import { Effect, Schema } from "effect"
3299
- * import { SchemaX } from "@nunofyobiz/effect-extras"
3300
- *
3301
- * const Source = Schema.Struct({
3302
- * a: Schema.Number,
3303
- * b: Schema.String,
3304
- * c: Schema.Boolean,
3305
- * })
3306
- *
3307
- * const Update = SchemaX.pickPartial(Source, "a", "b")
3308
- *
3309
- * // Only picked fields are known, and each may be omitted
3310
- * assert.deepStrictEqual(Effect.runSync(Schema.decodeEffect(Update)({})), {})
3311
- * assert.deepStrictEqual(
3312
- * Effect.runSync(Schema.decodeEffect(Update)({ a: 1 })),
3313
- * { a: 1 },
3314
- * )
3315
- * ```
3316
- *
3317
- * @category combinators
3318
- * @since 0.0.0
3319
- */
3320
- declare const pickPartial: <const Fields extends Schema.Struct.Fields, const Keys extends readonly (keyof Fields & string)[]>(schema: Schema.Struct<Fields>, ...keys: Keys) => Schema.Struct<{ [K in Keys[number]]: Schema.optional<Fields[K]>; }>;
3321
-
3322
- type SchemaX_MakeIn<S extends {
3323
- readonly "~type.make.in": unknown;
3324
- }> = MakeIn<S>;
3325
- declare const SchemaX_TrimmedNonEmptyString: typeof TrimmedNonEmptyString;
3326
- declare const SchemaX_URLSafeFilePath: typeof URLSafeFilePath;
3327
- declare const SchemaX_nonNegativeBigInt: typeof nonNegativeBigInt;
3328
- declare const SchemaX_omit: typeof omit;
3329
- declare const SchemaX_partial: typeof partial;
3330
- declare const SchemaX_pick: typeof pick;
3331
- declare const SchemaX_pickPartial: typeof pickPartial;
3332
- declare namespace SchemaX {
3333
- export { type SchemaX_MakeIn as MakeIn, SchemaX_TrimmedNonEmptyString as TrimmedNonEmptyString, SchemaX_URLSafeFilePath as URLSafeFilePath, SchemaX_nonNegativeBigInt as nonNegativeBigInt, SchemaX_omit as omit, SchemaX_partial as partial, SchemaX_pick as pick, SchemaX_pickPartial as pickPartial };
3334
- }
3335
-
3336
- /**
3337
- * Runs a mutating function against a copy of `set`, leaving the original
3338
- * untouched, and returns the mutated copy.
3339
- *
3340
- * Use it to reuse imperative `Set` mutation code (`.add`, `.delete`) without
3341
- * sacrificing immutability: the callback may freely mutate the set it receives
3342
- * because it operates on a fresh clone. Supports both data-first and data-last
3343
- * (pipeable) call styles.
3344
- *
3345
- * @example
3346
- * ```ts
3347
- * import { SetX } from "@nunofyobiz/effect-extras"
3348
- * import { pipe } from "effect"
3349
- *
3350
- * const original = new Set(["a", "b"])
3351
- *
3352
- * const result = pipe(
3353
- * original,
3354
- * SetX.safelyMutate((set) => {
3355
- * set.delete("a")
3356
- * return set.add("c")
3357
- * })
3358
- * )
3359
- *
3360
- * assert.deepStrictEqual(result, new Set(["b", "c"]))
3361
- * // The original is left intact
3362
- * assert.deepStrictEqual(original, new Set(["a", "b"]))
3363
- * ```
3364
- *
3365
- * @category combinators
3366
- * @since 0.0.0
3367
- */
3368
- declare const safelyMutate: (<A>(mutate: (set: Set<A>) => Set<A>) => (set: Set<A>) => Set<A>) & (<A>(set: Set<A>, mutate: (set: Set<A>) => Set<A>) => Set<A>);
3369
- /**
3370
- * Returns a new `Set` with `value` added, leaving the input set unchanged.
3371
- *
3372
- * When `value` is already present the input set is returned as-is (no copy),
3373
- * making repeated adds of existing members allocation-free. Supports both
3374
- * data-first and data-last (pipeable) call styles.
3375
- *
3376
- * @example
3377
- * ```ts
3378
- * import { SetX } from "@nunofyobiz/effect-extras"
3379
- * import { pipe } from "effect"
3380
- *
3381
- * // Data-first — adds a new element into a fresh set
3382
- * assert.deepStrictEqual(
3383
- * SetX.add(new Set(["a", "b"]), "c"),
3384
- * new Set(["a", "b", "c"])
3385
- * )
3386
- *
3387
- * // Data-last — existing element leaves the set unchanged
3388
- * assert.deepStrictEqual(
3389
- * pipe(new Set(["a", "b"]), SetX.add("b")),
3390
- * new Set(["a", "b"])
3391
- * )
3392
- * ```
3393
- *
3394
- * @category combinators
3395
- * @since 0.0.0
3396
- */
3397
- declare const add: (<A>(value: A) => (set: Set<A>) => Set<A>) & (<A>(set: Set<A>, value: A) => Set<A>);
3398
- /**
3399
- * Returns a new `Set` with `value` removed, leaving the input set unchanged.
3400
- *
3401
- * When `value` is absent the input set is returned as-is (no copy). Supports both
3402
- * data-first and data-last (pipeable) call styles.
3403
- *
3404
- * @example
3405
- * ```ts
3406
- * import { SetX } from "@nunofyobiz/effect-extras"
3407
- * import { pipe } from "effect"
3408
- *
3409
- * // Data-first — removes an existing element into a fresh set
3410
- * assert.deepStrictEqual(
3411
- * SetX.remove(new Set(["a", "b", "c"]), "c"),
3412
- * new Set(["a", "b"])
3413
- * )
3414
- *
3415
- * // Data-last — absent element leaves the set unchanged
3416
- * assert.deepStrictEqual(
3417
- * pipe(new Set(["a", "b"]), SetX.remove("z")),
3418
- * new Set(["a", "b"])
3419
- * )
3420
- * ```
3421
- *
3422
- * @category combinators
3423
- * @since 0.0.0
3424
- */
3425
- declare const remove: (<A>(value: A) => (set: Set<A>) => Set<A>) & (<A>(set: Set<A>, value: A) => Set<A>);
3426
- /**
3427
- * Returns a new `Set` with `value` added if it was absent or removed if it was
3428
- * present, leaving the input set unchanged.
3429
- *
3430
- * Use it for membership toggles (selection state, feature flags by key) where a
3431
- * value's presence should flip on each call. Supports both data-first and
3432
- * data-last (pipeable) call styles.
3433
- *
3434
- * @example
3435
- * ```ts
3436
- * import { SetX } from "@nunofyobiz/effect-extras"
3437
- * import { pipe } from "effect"
3438
- *
3439
- * // Data-first — absent value gets added
3440
- * assert.deepStrictEqual(
3441
- * SetX.toggle(new Set(["a", "b"]), "c"),
3442
- * new Set(["a", "b", "c"])
3443
- * )
3444
- *
3445
- * // Data-last — present value gets removed
3446
- * assert.deepStrictEqual(
3447
- * pipe(new Set(["a", "b", "c"]), SetX.toggle("b")),
3448
- * new Set(["a", "c"])
3449
- * )
3450
- * ```
3451
- *
3452
- * @category combinators
3453
- * @since 0.0.0
3454
- */
3455
- declare const toggle: (<A>(value: A) => (set: Set<A>) => Set<A>) & (<A>(set: Set<A>, value: A) => Set<A>);
3456
-
3457
- declare const SetX_add: typeof add;
3458
- declare const SetX_remove: typeof remove;
3459
- declare const SetX_safelyMutate: typeof safelyMutate;
3460
- declare const SetX_toggle: typeof toggle;
3461
- declare namespace SetX {
3462
- export { SetX_add as add, SetX_remove as remove, SetX_safelyMutate as safelyMutate, SetX_toggle as toggle };
3463
- }
3464
-
3465
- /**
3466
- * Prepends `start` to `string_`.
3467
- *
3468
- * v4's `String` module has no native `prepend` (only `concat`), so this fills
3469
- * the gap as a pipeable helper.
3470
- *
3471
- * @example
3472
- * ```ts
3473
- * import { pipe } from "effect"
3474
- * import { StringX } from "@nunofyobiz/effect-extras"
3475
- *
3476
- * // data-first
3477
- * assert.deepStrictEqual(StringX.prepend("world", "hello "), "hello world")
3478
- *
3479
- * // data-last (piped)
3480
- * assert.deepStrictEqual(pipe("world", StringX.prepend("hello ")), "hello world")
3481
- * ```
3482
- *
3483
- * @category combinators
3484
- * @since 0.0.0
3485
- */
3486
- declare const prepend: ((start: string) => (string_: string) => string) & ((string_: string, start: string) => string);
3487
- /**
3488
- * Wraps `string_` between `start` and `end`.
3489
- *
3490
- * No v4 native equivalent — handy for quoting, bracketing, or fencing a value.
3491
- *
3492
- * @example
3493
- * ```ts
3494
- * import { pipe } from "effect"
3495
- * import { StringX } from "@nunofyobiz/effect-extras"
3496
- *
3497
- * // data-first
3498
- * assert.deepStrictEqual(StringX.surround("value", "[", "]"), "[value]")
3499
- *
3500
- * // data-last (piped)
3501
- * assert.deepStrictEqual(pipe("value", StringX.surround("(", ")")), "(value)")
3502
- * ```
3503
- *
3504
- * @category combinators
3505
- * @since 0.0.0
3506
- */
3507
- declare const surround: ((start: string, end: string) => (string_: string) => string) & ((string_: string, start: string, end: string) => string);
3508
- /**
3509
- * Prepends `start` to `string_` unless `string_` already starts with it.
3510
- *
3511
- * Idempotent: applying it to an already-prefixed string is a no-op, so
3512
- * `ensurePrepend("foofoo", "foo")` stays `"foofoo"` rather than gaining a
3513
- * second `"foo"`.
3514
- *
3515
- * @example
3516
- * ```ts
3517
- * import { pipe } from "effect"
3518
- * import { StringX } from "@nunofyobiz/effect-extras"
3519
- *
3520
- * // data-first — adds the prefix when missing
3521
- * assert.deepStrictEqual(StringX.ensurePrepend("bar", "foo"), "foobar")
3522
- *
3523
- * // idempotent — already prefixed, returned unchanged
3524
- * assert.deepStrictEqual(StringX.ensurePrepend("foobar", "foo"), "foobar")
3525
- *
3526
- * // data-last (piped)
3527
- * assert.deepStrictEqual(pipe("bar", StringX.ensurePrepend("foo")), "foobar")
3528
- * ```
3529
- *
3530
- * @category combinators
3531
- * @since 0.0.0
3532
- */
3533
- declare const ensurePrepend: ((start: string) => (string_: string) => string) & ((string_: string, start: string) => string);
3534
-
3535
- declare const StringX_ensurePrepend: typeof ensurePrepend;
3536
- declare const StringX_prepend: typeof prepend;
3537
- declare const StringX_surround: typeof surround;
3538
- declare namespace StringX {
3539
- export { StringX_ensurePrepend as ensurePrepend, StringX_prepend as prepend, StringX_surround as surround };
3540
- }
3541
-
3542
- /**
3543
- * Generic, framework-agnostic extensions to Effect's `Struct` module.
3544
- *
3545
- * @since 0.0.0
3546
- */
3547
-
3548
- /**
3549
- * Describes the shape of a per-field transformation over an object `O`: a record
3550
- * `T` whose values are functions taking the corresponding field of `O`.
3551
- *
3552
- * Used to type the "evolve" pattern, where each provided key maps to a function
3553
- * that receives that field's current value. Copied from Effect's internal
3554
- * `Struct.evolve()` type, which is not exported — it would be better to use
3555
- * theirs directly if it ever becomes public.
3556
- *
3557
- * @example
3558
- * ```ts
3559
- * import { StructX } from "@nunofyobiz/effect-extras"
3560
- *
3561
- * type Transform = StructX.PartialTransform<
3562
- * { a: number; b: string },
3563
- * { a: (n: number) => boolean }
3564
- * >
3565
- *
3566
- * const evolve: Transform = { a: (n) => n > 0 }
3567
- *
3568
- * assert.deepStrictEqual(evolve.a(1), true)
3569
- * ```
3570
- *
3571
- * @category models
3572
- * @since 0.0.0
3573
- */
3574
- type PartialTransform<O, T> = {
3575
- [K in keyof T]: T[K] extends (a: O[K & keyof O]) => unknown ? T[K] : (a: O[K & keyof O]) => unknown;
3576
- };
3577
- /**
3578
- * Builds a singleton record `{ [name]: value }` when `value` is defined, or an
3579
- * empty object `{}` when it is `undefined` — meant to be spread into an object
3580
- * literal.
3581
- *
3582
- * This is the canonical fix for `exactOptionalPropertyTypes: true` (which this
3583
- * repo enables for Effect Schema). Under that flag, spreading
3584
- * `{ key: maybeUndefined }` into an object whose key is `key?: T` is a type
3585
- * error: the property must be *absent*, not present-but-`undefined`. Spreading
3586
- * `...defined("key", maybeUndefined)` instead conditionally omits the property
3587
- * altogether. Note that `null` and other falsy-but-defined values (`0`, `""`,
3588
- * `false`) are kept — only `undefined` is dropped.
3589
- *
3590
- * @example
3591
- * ```ts
3592
- * import { StructX } from "@nunofyobiz/effect-extras"
3593
- *
3594
- * // Defined value → singleton record
3595
- * assert.deepStrictEqual(StructX.defined("name", "Ada"), { name: "Ada" })
3596
- *
3597
- * // undefined → property omitted entirely
3598
- * assert.deepStrictEqual(StructX.defined("name", undefined), {})
3599
- *
3600
- * // Falsy-but-defined values are kept
3601
- * assert.deepStrictEqual(StructX.defined("name", 0), { name: 0 })
3602
- *
3603
- * // Typical use: spread to conditionally include an optional field
3604
- * const maybeAge: number | undefined = undefined
3605
- * assert.deepStrictEqual({ id: 1, ...StructX.defined("age", maybeAge) }, {
3606
- * id: 1,
3607
- * })
3608
- * ```
3609
- *
3610
- * @category constructors
3611
- * @since 0.0.0
3612
- */
3613
- declare const defined: <const K extends string, V>(name: K, value: V | undefined) => Partial<Record<K, Exclude<V, undefined>>>;
3614
- /**
3615
- * Removes every property whose value is `undefined` from `record`, narrowing
3616
- * each remaining property type to exclude `undefined`.
3617
- *
3618
- * The bulk counterpart of {@link defined}: instead of building one optional
3619
- * field, it filters a whole object. Very useful for update/patch actions where
3620
- * `undefined` means "leave this field unchanged" while every other value —
3621
- * including `null`, `0`, `""`, `false`, and `Option.none()` — means "set the
3622
- * field to exactly this".
3623
- *
3624
- * @example
3625
- * ```ts
3626
- * import { StructX } from "@nunofyobiz/effect-extras"
3627
- *
3628
- * // Drops `b` (undefined) but keeps every other value, including null/0/false
3629
- * assert.deepStrictEqual(
3630
- * StructX.filterDefined({ a: "x", b: undefined, c: 0, d: null, e: false }),
3631
- * { a: "x", c: 0, d: null, e: false },
3632
- * )
3633
- * ```
3634
- *
3635
- * @category filtering
3636
- * @since 0.0.0
3637
- */
3638
- declare const filterDefined: <R extends Record<string, unknown>>(record: R) => Partial<{ [P in keyof R]: Exclude<R[P], undefined>; }>;
3639
- /**
3640
- * Builds a singleton record `{ [name]: value }` when `value` is `Some`, or an
3641
- * empty object `{}` when it is `None` — meant to be spread into an object
3642
- * literal.
3643
- *
3644
- * The `Option`-valued sibling of {@link defined}: where `defined` keys off
3645
- * `undefined`, this keys off `Option` presence. Spread `...some("key", opt)` to
3646
- * conditionally include a field only when the `Option` carries a value, which
3647
- * stays correct under `exactOptionalPropertyTypes: true`.
3648
- *
3649
- * @example
3650
- * ```ts
3651
- * import { Option } from "effect"
3652
- * import { StructX } from "@nunofyobiz/effect-extras"
3653
- *
3654
- * // Some → singleton record
3655
- * assert.deepStrictEqual(StructX.some("name", Option.some("Ada")), {
3656
- * name: "Ada",
3657
- * })
3658
- *
3659
- * // None → property omitted entirely
3660
- * assert.deepStrictEqual(StructX.some("name", Option.none()), {})
3661
- * ```
3662
- *
3663
- * @category constructors
3664
- * @since 0.0.0
3665
- */
3666
- declare const some: <const K extends string, V>(name: K, value: Option.Option<V>) => Partial<Record<K, V>>;
3667
- /**
3668
- * Looks up `key` in a record of `Option` values and returns a singleton record
3669
- * when the value is `Some`, or `{}` when the key is absent or its value is
3670
- * `None`.
3671
- *
3672
- * Combines `Record.get` + `Option.flatten` + a singleton builder in one call —
3673
- * ideal for spreading an optional field out of a lookup table into an object
3674
- * literal under `exactOptionalPropertyTypes: true`. By default the output key
3675
- * matches the lookup key; pass `renameKeyTo` to emit the value under a different
3676
- * name.
3677
- *
3678
- * @example
3679
- * ```ts
3680
- * import { Option } from "effect"
3681
- * import { StructX } from "@nunofyobiz/effect-extras"
3682
- *
3683
- * const lookup = {
3684
- * a: Option.some(100),
3685
- * b: Option.none<number>(),
3686
- * }
3687
- *
3688
- * // Some → singleton record under the same key
3689
- * assert.deepStrictEqual(StructX.pickSome(lookup, "a"), { a: 100 })
3690
- *
3691
- * // None → property omitted entirely
3692
- * assert.deepStrictEqual(StructX.pickSome(lookup, "b"), {})
3693
- *
3694
- * // Rename the output key
3695
- * assert.deepStrictEqual(StructX.pickSome(lookup, "a", "count"), { count: 100 })
3696
- * ```
3697
- *
3698
- * @category constructors
3699
- * @since 0.0.0
3700
- */
3701
- declare function pickSome<const K extends string, V>(record: Record<K, Option.Option<V>>, key: K): Partial<Record<K, V>>;
3702
- declare function pickSome<const K1 extends string, V, const K2 extends string>(record: Record<K1, Option.Option<V>>, key: K1, renameKeyTo: K2): Partial<Record<K2, V>>;
3703
- /**
3704
- * Builds a singleton record `{ [name]: value }` when `value` is truthy, or an
3705
- * empty object `{}` otherwise — meant to be spread into an object literal.
3706
- *
3707
- * Stricter than {@link defined}: it drops not just `undefined` but every falsy
3708
- * value (`null`, `false`, `0`, `""`, `NaN`), and narrows the value type
3709
- * accordingly. Use it to spread a field only when it carries a meaningful,
3710
- * non-falsy value.
3711
- *
3712
- * @example
3713
- * ```ts
3714
- * import { StructX } from "@nunofyobiz/effect-extras"
3715
- *
3716
- * // Truthy value → singleton record
3717
- * assert.deepStrictEqual(StructX.truthy("name", "Ada"), { name: "Ada" })
3718
- *
3719
- * // Falsy values → property omitted entirely
3720
- * assert.deepStrictEqual(StructX.truthy("name", ""), {})
3721
- * assert.deepStrictEqual(StructX.truthy("name", 0), {})
3722
- * assert.deepStrictEqual(StructX.truthy("name", false), {})
3723
- * ```
3724
- *
3725
- * @category constructors
3726
- * @since 0.0.0
3727
- */
3728
- declare const truthy: <const K extends string, V>(name: K, value: V) => Partial<Record<K, Exclude<NonNullable<V>, false | 0 | "">>>;
3729
- /**
3730
- * Returns `true` when `object` has `key` set to a non-nullish value, narrowing
3731
- * that property to `NonNullable` on the type level.
3732
- *
3733
- * A type guard combining `hasProperty` with a nullish check: after a successful
3734
- * test, TypeScript treats `object[key]` as present and free of `null` /
3735
- * `undefined`. Handy as a predicate passed to `Array.filter` to keep only the
3736
- * elements whose `key` is populated.
3737
- *
3738
- * @example
3739
- * ```ts
3740
- * import { pipe } from "effect"
3741
- * import { StructX } from "@nunofyobiz/effect-extras"
3742
- *
3743
- * // data-first
3744
- * assert.deepStrictEqual(
3745
- * StructX.hasNotNullableProperty({ id: "1" }, "id"),
3746
- * true,
3747
- * )
3748
- *
3749
- * // data-last (pipeable); a null value fails the guard
3750
- * assert.deepStrictEqual(
3751
- * pipe({ id: null }, StructX.hasNotNullableProperty("id")),
3752
- * false,
3753
- * )
3754
- * ```
3755
- *
3756
- * @category refinements
3757
- * @since 0.0.0
3758
- */
3759
- declare const hasNotNullableProperty: (<T, K extends keyof T>(key: K) => (object: T) => object is T & Record<K, NonNullable<T[K]>>) & (<T, K extends keyof T>(object: T, key: K) => object is T & Record<K, NonNullable<T[K]>>);
3760
-
3761
- type StructX_PartialTransform<O, T> = PartialTransform<O, T>;
3762
- declare const StructX_defined: typeof defined;
3763
- declare const StructX_filterDefined: typeof filterDefined;
3764
- declare const StructX_hasNotNullableProperty: typeof hasNotNullableProperty;
3765
- declare const StructX_pickSome: typeof pickSome;
3766
- declare const StructX_some: typeof some;
3767
- declare const StructX_truthy: typeof truthy;
3768
- declare namespace StructX {
3769
- export { type StructX_PartialTransform as PartialTransform, StructX_defined as defined, StructX_filterDefined as filterDefined, StructX_hasNotNullableProperty as hasNotNullableProperty, StructX_pickSome as pickSome, StructX_some as some, StructX_truthy as truthy };
3770
- }
3771
-
3772
- export { ArrayX, BigIntX, BooleanX, DurationX, EffectX, FormDataX, MapX, NonNullableX, NumberX, OptionX, OrderX, PredicateX, PromiseX, RecordX, ResultX, SchemaX, SetX, StringX, StructX, WarnResult$1 as WarnResult, fromNullableOrThrow as nn };
1
+ export * as ArrayX from "./ArrayX.js";
2
+ export * as BigIntX from "./BigIntX.js";
3
+ export * as BooleanX from "./BooleanX.js";
4
+ export * as DurationX from "./DurationX.js";
5
+ export * as EffectX from "./EffectX.js";
6
+ export * as FormDataX from "./FormDataX.js";
7
+ export * as MapX from "./MapX.js";
8
+ export * as NonNullableX from "./NonNullableX.js";
9
+ export { fromNullableOrThrow as nn } from "./NonNullableX.js";
10
+ export * as NumberX from "./NumberX.js";
11
+ export * as OptionX from "./OptionX.js";
12
+ export * as OrderX from "./OrderX.js";
13
+ export * as PredicateX from "./PredicateX.js";
14
+ export * as PromiseX from "./PromiseX.js";
15
+ export * as RecordX from "./RecordX.js";
16
+ export * as ResultX from "./ResultX.js";
17
+ export * as SchemaX from "./SchemaX.js";
18
+ export * as SetX from "./SetX.js";
19
+ export * as StringX from "./StringX.js";
20
+ export * as StructX from "./StructX.js";
21
+ export * as WarnResult from "./WarnResult.js";
22
+ //# sourceMappingURL=index.d.ts.map