@nlozgachev/pipelined 0.62.0 → 0.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/data.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { a as NonEmptyArr, N as NonEmpty } from './InternalTypes-LdhLQx3N.js';
2
- import { M as Maybe, R as Result, E as Equality, b as Ordering, T as Task } from './Validation-DZLizBZ0.js';
3
- import { B as Brand } from './Duration-B8joKzro.js';
1
+ import { a as NonEmptyArr, N as NonEmpty } from './InternalTypes-CCXa8Kvr.js';
2
+ import { M as Maybe, R as Result, E as Equality, b as Ordering, T as Task } from './Validation-C5RGZUXy.js';
3
+ import { B as Brand } from './Duration-DeyxG6VQ.js';
4
4
  import './types.js';
5
5
 
6
6
  declare namespace ArrTaskResult {
@@ -39,1328 +39,316 @@ declare namespace ArrTaskResult {
39
39
  */
40
40
  const sequence: <E, A>(data: readonly Task<Result<E, A>>[]) => Task<Result<E, readonly A[]>>;
41
41
  }
42
- declare namespace ArrNonEmpty {
43
- /**
44
- * Creates a single-element list.
45
- *
46
- * @example
47
- * ```ts
48
- * Arr.NonEmpty.singleton(42); // [42]
49
- * ```
50
- */
51
- const singleton: <A>(value: A) => NonEmptyArr<A>;
52
- namespace from {
53
- /**
54
- * Returns Some if the array is non-empty, None otherwise.
55
- *
56
- * @example
57
- * ```ts
58
- * Arr.NonEmpty.from.Array([1, 2]); // Some([1, 2])
59
- * Arr.NonEmpty.from.Array([]); // None
60
- * ```
61
- */
62
- const Array: <A>(data: readonly A[]) => Maybe<NonEmptyArr<A>>;
63
- }
64
- /**
65
- * Returns the first element of a NonEmptyArr.
66
- *
67
- * @example
68
- * ```ts
69
- * Arr.NonEmpty.head([1, 2, 3]); // 1
70
- * ```
71
- */
72
- const head: <A>(data: NonEmptyArr<A>) => A;
73
- /**
74
- * Returns the last element of a NonEmptyArr.
75
- *
76
- * @example
77
- * ```ts
78
- * Arr.NonEmpty.last([1, 2, 3]); // 3
79
- * ```
80
- */
81
- const last: <A>(data: NonEmptyArr<A>) => A;
82
- /**
83
- * Returns all elements except the first.
84
- *
85
- * @example
86
- * ```ts
87
- * Arr.NonEmpty.tail([1, 2, 3]); // [2, 3]
88
- * ```
89
- */
90
- const tail: <A>(data: NonEmptyArr<A>) => readonly A[];
91
- /**
92
- * Reduces a NonEmptyArr from the left without an initial value.
93
- *
94
- * @example
95
- * ```ts
96
- * pipe([1, 2, 3, 4] as Arr.NonEmpty<number>, Arr.NonEmpty.reduce((a: number, b: number) => a + b)); // 10
97
- * ```
98
- */
99
- const reduce: <A>(f: (acc: A, a: A) => A) => (data: NonEmptyArr<A>) => A;
100
- /**
101
- * Transforms each element of a NonEmptyArr.
102
- *
103
- * @example
104
- * ```ts
105
- * pipe(Arr.NonEmpty.singleton(1), Arr.NonEmpty.map(n => n * 2)); // [2]
106
- * ```
107
- */
108
- const map: <A, B>(f: (a: A) => B) => (data: NonEmptyArr<A>) => NonEmptyArr<B>;
109
- /**
110
- * Transforms each element of a NonEmptyArr, also receiving the index.
111
- *
112
- * @example
113
- * ```ts
114
- * pipe(Arr.NonEmpty.singleton("a"), Arr.NonEmpty.mapWithIndex((i, s) => `${i}:${s}`)); // ["0:a"]
115
- * ```
116
- */
117
- const mapWithIndex: <A, B>(f: (i: number, a: A) => B) => (data: NonEmptyArr<A>) => NonEmptyArr<B>;
118
- /**
119
- * Inserts a separator between every element of a NonEmptyArr.
120
- *
121
- * @example
122
- * ```ts
123
- * pipe([1, 2] as Arr.NonEmpty<number>, Arr.NonEmpty.intersperse(0)); // [1, 0, 2]
124
- * ```
125
- */
126
- const intersperse: <A>(sep: A) => (data: NonEmptyArr<A>) => NonEmptyArr<A>;
127
- /**
128
- * Concatenates a NonEmptyArr with a standard array.
129
- *
130
- * @example
131
- * ```ts
132
- * pipe(Arr.NonEmpty.singleton(1), Arr.NonEmpty.concat([2, 3])); // [1, 2, 3]
133
- * ```
134
- */
135
- const concat: <A>(other: readonly A[]) => (data: NonEmptyArr<A>) => NonEmptyArr<A>;
136
- /**
137
- * Reverses a NonEmptyArr.
138
- *
139
- * @example
140
- * ```ts
141
- * pipe(Arr.NonEmpty.singleton(1), Arr.NonEmpty.reverse); // [1]
142
- * ```
143
- */
144
- const reverse: <A>(data: NonEmptyArr<A>) => NonEmptyArr<A>;
145
- }
146
- /**
147
- * Functional array utilities that compose well with pipe.
148
- * All functions are data-last and curried where applicable.
149
- * Safe access functions return Maybe instead of throwing or returning undefined.
150
- *
151
- * @example
152
- * ```ts
153
- * pipe(
154
- * [1, 2, 3, 4, 5],
155
- * Arr.filter(n => n > 2),
156
- * Arr.map(n => n * 10),
157
- * Arr.head
158
- * ); // Some(30)
159
- * ```
160
- */
161
- declare namespace Arr {
162
- /**
163
- * A type alias representing an array that is guaranteed to contain at least one element.
164
- * Under the hood, this is a read-only tuple structure: `readonly [A, ...A[]]`.
165
- *
166
- * @example
167
- * ```ts
168
- * const list: Arr.NonEmpty<number> = [1, 2, 3];
169
- * ```
170
- */
171
- export type NonEmpty<A> = NonEmptyArr<A>;
172
- /**
173
- * Returns the first element of an array, or None if the array is empty.
174
- *
175
- * @example
176
- * ```ts
177
- * Arr.head([1, 2, 3]); // Some(1)
178
- * Arr.head([]); // None
179
- * ```
180
- */
181
- export const head: <A>(data: readonly A[]) => Maybe<A>;
182
- /**
183
- * Returns the last element of an array, or None if the array is empty.
184
- *
185
- * @example
186
- * ```ts
187
- * Arr.last([1, 2, 3]); // Some(3)
188
- * Arr.last([]); // None
189
- * ```
190
- */
191
- export const last: <A>(data: readonly A[]) => Maybe<A>;
192
- /**
193
- * Returns all elements except the first, or None if the array is empty.
194
- *
195
- * @example
196
- * ```ts
197
- * Arr.tail([1, 2, 3]); // Some([2, 3])
198
- * Arr.tail([]); // None
199
- * ```
200
- */
201
- export const tail: <A>(data: readonly A[]) => Maybe<readonly A[]>;
202
- /**
203
- * Returns all elements except the last, or None if the array is empty.
204
- *
205
- * @example
206
- * ```ts
207
- * Arr.init([1, 2, 3]); // Some([1, 2])
208
- * Arr.init([]); // None
209
- * ```
210
- */
211
- export const init: <A>(data: readonly A[]) => Maybe<readonly A[]>;
212
- /**
213
- * Returns the first element matching the predicate, or None.
214
- *
215
- * @example
216
- * ```ts
217
- * pipe([1, 2, 3, 4], Arr.findFirst(n => n > 2)); // Some(3)
218
- * ```
219
- */
220
- export const findFirst: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => Maybe<A>;
221
- /**
222
- * Returns the last element matching the predicate, or None.
223
- *
224
- * @example
225
- * ```ts
226
- * pipe([1, 2, 3, 4], Arr.findLast(n => n > 2)); // Some(4)
227
- * ```
228
- */
229
- export const findLast: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => Maybe<A>;
230
- /**
231
- * Returns the index of the first element matching the predicate, or None.
232
- *
233
- * @example
234
- * ```ts
235
- * pipe([1, 2, 3, 4], Arr.findIndex(n => n > 2)); // Some(2)
236
- * ```
237
- */
238
- export const findIndex: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => Maybe<number>;
239
- /**
240
- * Transforms each element of an array.
241
- *
242
- * @example
243
- * ```ts
244
- * pipe([1, 2, 3], Arr.map(n => n * 2)); // [2, 4, 6]
245
- * ```
246
- */
247
- export const map: <A, B>(f: (a: A) => B) => (data: readonly A[]) => readonly B[];
248
- /**
249
- * Transforms each element using both its value and its zero-based index.
250
- *
251
- * @example
252
- * ```ts
253
- * pipe(
254
- * ["a", "b", "c"],
255
- * Arr.mapWithIndex((i, s) => ({ position: i + 1, value: s }))
256
- * ); // [{ position: 1, value: "a" }, { position: 2, value: "b" }, { position: 3, value: "c" }]
257
- * ```
258
- */
259
- export const mapWithIndex: <A, B>(f: (i: number, a: A) => B) => (data: readonly A[]) => readonly B[];
260
- /**
261
- * Filters elements that satisfy the predicate.
262
- *
263
- * @example
264
- * ```ts
265
- * pipe([1, 2, 3, 4], Arr.filter(n => n % 2 === 0)); // [2, 4]
266
- * ```
267
- */
268
- export const filter: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly A[];
269
- /**
270
- * Maps each element to a Maybe and collects only the Some values.
271
- * Combines map and filter in a single pass.
272
- *
273
- * @example
274
- * ```ts
275
- * const parseNum = (s: string): Maybe<number> => {
276
- * const n = Number(s);
277
- * return isNaN(n) ? Maybe.make.none() : Maybe.make.some(n);
278
- * };
279
- *
280
- * pipe(["1", "abc", "3"], Arr.filterMap(parseNum)); // [1, 3]
281
- * ```
282
- */
283
- export const filterMap: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => readonly B[];
284
- /**
285
- * Splits an array into two groups based on a predicate.
286
- * First group contains elements that satisfy the predicate,
287
- * second group contains the rest.
288
- *
289
- * @example
290
- * ```ts
291
- * pipe([1, 2, 3, 4], Arr.partition(n => n % 2 === 0)); // [[2, 4], [1, 3]]
292
- * ```
293
- */
294
- export const partition: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly [readonly A[], readonly A[]];
295
- /**
296
- * Narrows a list of Maybe values down to a list of their underlying values,
297
- * discarding all None instances.
298
- *
299
- * @example
300
- * ```ts
301
- * Arr.compact([Maybe.make.some(1), Maybe.make.none(), Maybe.make.some(3)]); // [1, 3]
302
- * ```
303
- */
304
- export const compact: <A>(data: readonly Maybe<A>[]) => readonly A[];
305
- /**
306
- * Separates an array of Result values into two separate lists of errors and successes.
307
- * Returns a tuple containing `[errors, successes]`.
308
- *
309
- * @example
310
- * ```ts
311
- * Arr.separate([Result.make.ok(1), Result.make.err("bad"), Result.make.ok(3)]); // [["bad"], [1, 3]]
312
- * ```
313
- */
314
- export const separate: <E, A>(data: readonly Result<E, A>[]) => readonly [readonly E[], readonly A[]];
315
- /**
316
- * Maps each element to a Result, and separates the results into a tuple of failures and successes.
317
- *
318
- * @example
319
- * ```ts
320
- * pipe(
321
- * [1, 2, 3, 4],
322
- * Arr.partitionMap(n => n % 2 === 0 ? Result.make.ok(n) : Result.make.err(`odd: ${n}`))
323
- * ); // [["odd: 1", "odd: 3"], [2, 4]]
324
- * ```
325
- */
326
- export const partitionMap: <A, E, B>(f: (a: A) => Result<E, B>) => (data: readonly A[]) => readonly [readonly E[], readonly B[]];
327
- /**
328
- * Groups elements by a key function.
329
- *
330
- * @example
331
- * ```ts
332
- * pipe(
333
- * ["apple", "avocado", "banana"],
334
- * Arr.groupBy(s => s[0])
335
- * ); // { a: ["apple", "avocado"], b: ["banana"] }
336
- * ```
337
- */
338
- export const groupBy: <A>(f: (a: A) => string) => (data: readonly A[]) => Record<string, NonEmptyArr<A>>;
339
- /**
340
- * Removes duplicate elements using strict equality.
341
- *
342
- * @example
343
- * ```ts
344
- * Arr.uniq([1, 2, 2, 3, 1]); // [1, 2, 3]
345
- * ```
346
- */
347
- export const uniq: <A>(data: readonly A[]) => readonly A[];
348
- /**
349
- * Removes duplicate elements by comparing the result of a key function.
350
- *
351
- * @example
352
- * ```ts
353
- * pipe(
354
- * [{id: 1, name: "a"}, {id: 1, name: "b"}, {id: 2, name: "c"}],
355
- * Arr.uniqBy(x => x.id)
356
- * ); // [{id: 1, name: "a"}, {id: 2, name: "c"}]
357
- * ```
358
- */
359
- export const uniqBy: <A, B>(f: (a: A) => B) => (data: readonly A[]) => readonly A[];
360
- /**
361
- * Removes duplicate elements using a custom equality check.
362
- * Preserves the order of first occurrences. Complements `uniq` (reference equality)
363
- * and `uniqBy` (key extraction).
364
- *
365
- * @example
366
- * ```ts
367
- * type Point = { x: number; y: number };
368
- * const eqPoint: Equality<Point> = (a, b) => a.x === b.x && a.y === b.y;
369
- *
370
- * pipe(
371
- * [{ x: 1, y: 1 }, { x: 2, y: 2 }, { x: 1, y: 1 }],
372
- * Arr.uniqWith(eqPoint),
373
- * ); // [{ x: 1, y: 1 }, { x: 2, y: 2 }]
374
- * ```
375
- */
376
- export const uniqWith: <A>(eq: Equality<A>) => (data: readonly A[]) => readonly A[];
377
- /**
378
- * Sorts an array using a comparison function. Returns a new array.
379
- * To sort with a typed `Ordering<A>`, prefer `Arr.sortWith`.
380
- *
381
- * @example
382
- * ```ts
383
- * pipe([3, 1, 2], Arr.sortBy((a, b) => a - b)); // [1, 2, 3]
384
- * ```
385
- */
386
- export const sortBy: <A>(compare: (a: A, b: A) => number) => (data: readonly A[]) => readonly A[];
387
- /**
388
- * Sorts an array using an `Ordering<A>`. Returns a new array without mutating the original.
389
- * Use this over `sortBy` when you have a typed `Ordering<A>` from the `Ordering` module.
390
- *
391
- * @example
392
- * ```ts
393
- * pipe([3, 1, 2], Arr.sortWith(Ordering.number)); // [1, 2, 3]
394
- *
395
- * type Product = { price: number };
396
- * const products: Product[] = [{ price: 20 }, { price: 10 }];
397
- * const byPrice = pipe(Ordering.number, Ordering.by((p: Product) => p.price));
398
- * pipe(products, Arr.sortWith(byPrice));
399
- * ```
400
- */
401
- export const sortWith: <A>(ord: Ordering<A>) => (data: readonly A[]) => readonly A[];
402
- /**
403
- * Pairs up elements from two arrays. Stops at the shorter array.
404
- *
405
- * @example
406
- * ```ts
407
- * pipe([1, 2, 3], Arr.zip(["a", "b"])); // [[1, "a"], [2, "b"]]
408
- * ```
409
- */
410
- export const zip: <B>(other: readonly B[]) => <A>(data: readonly A[]) => readonly (readonly [A, B])[];
411
- /**
412
- * Combines elements from two arrays using a function. Stops at the shorter array.
413
- *
414
- * @example
415
- * ```ts
416
- * pipe([1, 2], Arr.zipWith((a: number, b: string) => `${a}${b}`)(["a", "b"])); // ["1a", "2b"]
417
- * ```
418
- */
419
- export const zipWith: <A, B, C>(f: (a: A, b: B) => C) => (other: readonly B[]) => (data: readonly A[]) => readonly C[];
420
- /**
421
- * Inserts a separator between every element.
422
- *
423
- * @example
424
- * ```ts
425
- * pipe([1, 2, 3], Arr.intersperse(0)); // [1, 0, 2, 0, 3]
426
- * ```
427
- */
428
- export const intersperse: <A>(sep: A) => (data: readonly A[]) => readonly A[];
429
- /**
430
- * Concatenates a standard array with another array.
431
- *
432
- * @example
433
- * ```ts
434
- * pipe([1, 2], Arr.concat([3, 4])); // [1, 2, 3, 4]
435
- * ```
436
- */
437
- export const concat: <A>(other: readonly A[]) => (data: readonly A[]) => readonly A[];
438
- /**
439
- * Splits an array into chunks of the given size.
440
- *
441
- * @example
442
- * ```ts
443
- * pipe([1, 2, 3, 4, 5], Arr.chunksOf(2)); // [[1, 2], [3, 4], [5]]
444
- * ```
445
- */
446
- export const chunksOf: (n: number) => <A>(data: readonly A[]) => readonly (readonly A[])[];
447
- /**
448
- * Flattens a nested array by one level.
449
- *
450
- * @example
451
- * ```ts
452
- * Arr.flatten([[1, 2], [3], [4, 5]]); // [1, 2, 3, 4, 5]
453
- * ```
454
- */
455
- export const flatten: <A>(data: readonly (readonly A[])[]) => readonly A[];
456
- /**
457
- * Maps each element to an array and flattens the result.
458
- *
459
- * @example
460
- * ```ts
461
- * pipe([1, 2, 3], Arr.flatMap(n => [n, n * 10])); // [1, 10, 2, 20, 3, 30]
462
- * ```
463
- */
464
- export const flatMap: <A, B>(f: (a: A) => readonly B[]) => (data: readonly A[]) => readonly B[];
465
- /**
466
- * Reduces an array from the left.
467
- *
468
- * @example
469
- * ```ts
470
- * pipe([1, 2, 3], Arr.reduce(0, (acc, n) => acc + n)); // 6
471
- * ```
472
- */
473
- export const reduce: <A, B>(initial: B, f: (acc: B, a: A) => B) => (data: readonly A[]) => B;
474
- interface TaskTraverse {
475
- <A, B>(f: (a: A) => Task<B>): (data: readonly A[]) => Task<readonly B[]>;
476
- Result: typeof ArrTaskResult.traverse;
477
- }
478
- interface TaskSequence {
479
- <A>(data: readonly Task<A>[]): Task<readonly A[]>;
480
- Result: typeof ArrTaskResult.sequence;
481
- }
482
- export namespace traverse {
483
- const Maybe: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => Maybe<readonly B[]>;
484
- const Result: <E, A, B>(f: (a: A) => Result<E, B>) => (data: readonly A[]) => Result<E, readonly B[]>;
485
- const Task: TaskTraverse;
486
- }
487
- export namespace sequence {
488
- const Maybe: <A>(data: readonly Maybe<A>[]) => Maybe<readonly A[]>;
489
- const Result: <E, A>(data: readonly Result<E, A>[]) => Result<E, readonly A[]>;
490
- const Task: TaskSequence;
491
- }
492
- export namespace is {
493
- /**
494
- * Returns true if the array is empty.
495
- *
496
- * @example
497
- * ```ts
498
- * Arr.is.empty([]); // true
499
- * Arr.is.empty([1]); // false
500
- * ```
501
- */
502
- const empty: <A>(data: readonly A[]) => data is readonly [];
503
- /**
504
- * Returns true if the array is non-empty (type guard).
505
- *
506
- * @example
507
- * ```ts
508
- * Arr.is.nonEmpty([1, 2]); // true
509
- * Arr.is.nonEmpty([]); // false
510
- * ```
511
- */
512
- const nonEmpty: <A>(data: readonly A[]) => data is NonEmpty<A>;
513
- }
514
- /**
515
- * Prepends a value to the beginning of an array, returning a NonEmptyArr.
516
- *
517
- * @example
518
- * ```ts
519
- * pipe([1, 2], Arr.prepend(0)); // [0, 1, 2]
520
- * ```
521
- */
522
- export const prepend: <A>(value: A) => (data: readonly A[]) => NonEmpty<A>;
523
- /**
524
- * Appends a value to the end of an array, returning a NonEmptyArr.
525
- *
526
- * @example
527
- * ```ts
528
- * pipe([1, 2], Arr.append(3)); // [1, 2, 3]
529
- * ```
530
- */
531
- export const append: <A>(value: A) => (data: readonly A[]) => NonEmpty<A>;
532
- /**
533
- * Returns the length of an array.
534
- *
535
- * @example
536
- * ```ts
537
- * Arr.size([1, 2, 3]); // 3
538
- * ```
539
- */
540
- export const size: <A>(data: readonly A[]) => number;
541
- /**
542
- * Returns true if any element satisfies the predicate.
543
- *
544
- * @example
545
- * ```ts
546
- * pipe([1, 2, 3], Arr.some(n => n > 2)); // true
547
- * ```
548
- */
549
- export const some: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => boolean;
550
- /**
551
- * Returns true if all elements satisfy the predicate.
552
- *
553
- * @example
554
- * ```ts
555
- * pipe([1, 2, 3], Arr.every(n => n > 0)); // true
556
- * ```
557
- */
558
- export const every: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => boolean;
559
- /**
560
- * Reverses an array. Returns a new array.
561
- *
562
- * @example
563
- * ```ts
564
- * Arr.reverse([1, 2, 3]); // [3, 2, 1]
565
- * ```
566
- */
567
- export const reverse: <A>(data: readonly A[]) => readonly A[];
568
- /**
569
- * Returns a new array with `item` inserted before the element at `index`.
570
- * Negative indices are clamped to 0; indices beyond the array length append to the end.
571
- *
572
- * @example
573
- * ```ts
574
- * pipe([1, 2, 3], Arr.insertAt(1, 99)); // [1, 99, 2, 3]
575
- * pipe([1, 2, 3], Arr.insertAt(0, 99)); // [99, 1, 2, 3]
576
- * pipe([1, 2, 3], Arr.insertAt(3, 99)); // [1, 2, 3, 99]
577
- * ```
578
- */
579
- export const insertAt: <A>(index: number, item: A) => (data: readonly A[]) => readonly A[];
580
- /**
581
- * Returns a new array with the element at `index` removed.
582
- * Returns the original array unchanged if `index` is out of bounds.
583
- *
584
- * @example
585
- * ```ts
586
- * pipe([1, 2, 3], Arr.removeAt(1)); // [1, 3]
587
- * pipe([1, 2, 3], Arr.removeAt(0)); // [2, 3]
588
- * pipe([1, 2, 3], Arr.removeAt(5)); // [1, 2, 3]
589
- * ```
590
- */
591
- export const removeAt: (index: number) => <A>(data: readonly A[]) => readonly A[];
592
- /**
593
- * Takes the first n elements from an array.
594
- *
595
- * @example
596
- * ```ts
597
- * pipe([1, 2, 3, 4], Arr.take(2)); // [1, 2]
598
- * ```
599
- */
600
- export const take: (n: number) => <A>(data: readonly A[]) => readonly A[];
601
- /**
602
- * Drops the first n elements from an array.
603
- *
604
- * @example
605
- * ```ts
606
- * pipe([1, 2, 3, 4], Arr.drop(2)); // [3, 4]
607
- * ```
608
- */
609
- export const drop: (n: number) => <A>(data: readonly A[]) => readonly A[];
610
- /**
611
- * Takes elements from the start while the predicate holds.
612
- *
613
- * @example
614
- * ```ts
615
- * pipe([1, 2, 3, 1], Arr.takeWhile(n => n < 3)); // [1, 2]
616
- * ```
617
- */
618
- export const takeWhile: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly A[];
619
- /**
620
- * Drops elements from the start while the predicate holds.
621
- *
622
- * @example
623
- * ```ts
624
- * pipe([1, 2, 3, 1], Arr.dropWhile(n => n < 3)); // [3, 1]
625
- * ```
626
- */
627
- export const dropWhile: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly A[];
628
- /**
629
- * Like `reduce`, but returns every intermediate accumulator as an array.
630
- * The initial value is not included — the output has the same length as the input.
631
- *
632
- * @example
633
- * ```ts
634
- * pipe([1, 2, 3], Arr.scan(0, (acc, n) => acc + n)); // [1, 3, 6]
635
- * ```
636
- */
637
- export const scan: <A, B>(initial: B, f: (acc: B, a: A) => B) => (data: readonly A[]) => readonly B[];
638
- /**
639
- * Splits an array at an index into a `[before, after]` tuple.
640
- * Negative indices clamp to 0; indices beyond the array length clamp to the end.
641
- *
642
- * @example
643
- * ```ts
644
- * pipe([1, 2, 3, 4], Arr.splitAt(2)); // [[1, 2], [3, 4]]
645
- * pipe([1, 2, 3], Arr.splitAt(0)); // [[], [1, 2, 3]]
646
- * pipe([1, 2, 3], Arr.splitAt(10)); // [[1, 2, 3], []]
647
- * ```
648
- */
649
- export const splitAt: (index: number) => <A>(data: readonly A[]) => readonly [readonly A[], readonly A[]];
650
- /**
651
- * Partitions an array by applying a function returning `Maybe<B>`.
652
- * Elements returning `None` are gathered into `failures` (original `A` values);
653
- * elements returning `Some(b)` are gathered into `successes` (`B` values).
654
- *
655
- * @example
656
- * ```ts
657
- * const parseNumber = (s: string) => isNaN(Number(s)) ? Maybe.make.none() : Maybe.make.some(Number(s));
658
- * pipe(["1", "abc", "3"], Arr.partitionMaybe(parseNumber)); // [["abc"], [1, 3]]
659
- * ```
660
- */
661
- export const partitionMaybe: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => readonly [failures: readonly A[], successes: readonly B[]];
662
- /**
663
- * Safely looks up an element by index. Supports negative indices counting back from the end.
664
- * Returns `None` if the index is out of bounds.
665
- *
666
- * @example
667
- * ```ts
668
- * pipe([10, 20, 30], Arr.at(1)); // Some(20)
669
- * pipe([10, 20, 30], Arr.at(-1)); // Some(30)
670
- * pipe([10, 20, 30], Arr.at(5)); // None
671
- * ```
672
- */
673
- export const at: (index: number) => <A>(data: readonly A[]) => Maybe<A>;
674
- /**
675
- * Finds the first element in an array for which `f` returns `Some(b)`.
676
- *
677
- * @example
678
- * ```ts
679
- * pipe(
680
- * ["1", "a", "2"],
681
- * Arr.findMap((s) => isNaN(Number(s)) ? Maybe.make.none() : Maybe.make.some(Number(s)))
682
- * ); // Some(1)
683
- * ```
684
- */
685
- export const findMap: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => Maybe<B>;
686
- /**
687
- * Indexes elements of an array into a `ReadonlyMap<K, A>` using a key extraction function.
688
- *
689
- * @example
690
- * ```ts
691
- * pipe(
692
- * [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }],
693
- * Arr.indexBy((u) => u.id)
694
- * ); // ReadonlyMap { 1 => { id: 1, name: "Alice" }, 2 => { id: 2, name: "Bob" } }
695
- * ```
696
- */
697
- export const indexBy: <A, K>(keyFn: (a: A) => K) => (data: readonly A[]) => ReadonlyMap<K, A>;
698
- /**
699
- * Counts occurrences of each element in an array, returning a `ReadonlyMap<A, number>`.
700
- *
701
- * @example
702
- * ```ts
703
- * Arr.frequencies(["a", "b", "a", "c", "b", "a"]);
704
- * // ReadonlyMap { "a" => 3, "b" => 2, "c" => 1 }
705
- * ```
706
- */
707
- export const frequencies: <A>(data: readonly A[]) => ReadonlyMap<A, number>;
708
- /**
709
- * Groups consecutive elements that share the same key returned by `keyFn`.
710
- *
711
- * @example
712
- * ```ts
713
- * pipe(
714
- * [1, 1, 2, 3, 3, 1],
715
- * Arr.chunkBy((n) => n)
716
- * ); // [[1, 1], [2], [3, 3], [1]]
717
- * ```
718
- */
719
- export const chunkBy: <A, K>(keyFn: (a: A) => K) => (data: readonly A[]) => readonly (readonly A[])[];
720
- /**
721
- * Removes consecutive duplicate elements.
722
- * An optional `Equality<A>` can be provided (defaults to `Object.is`).
723
- *
724
- * @example
725
- * ```ts
726
- * Arr.dedupeAdjacent()([1, 1, 2, 2, 1, 3]); // [1, 2, 1, 3]
727
- * ```
728
- */
729
- export const dedupeAdjacent: <A>(eq?: Equality<A>) => (data: readonly A[]) => readonly A[];
730
- /**
731
- * Produces a sliding window of `size` elements over an array, advancing by `step` (default `1`).
732
- * Returns an empty array if `size <= 0` or `size > data.length`.
733
- *
734
- * @example
735
- * ```ts
736
- * pipe([1, 2, 3, 4], Arr.windowed(2)); // [[1, 2], [2, 3], [3, 4]]
737
- * pipe([1, 2, 3, 4], Arr.windowed(2, { step: 2 })); // [[1, 2], [3, 4]]
738
- * ```
739
- */
740
- export const windowed: (size: number, options?: {
741
- step?: number;
742
- }) => <A>(data: readonly A[]) => readonly (readonly A[])[];
743
- /**
744
- * Generates an array from an initial seed state until `f` returns `None`.
745
- *
746
- * @example
747
- * ```ts
748
- * Arr.unfold(1, (n) => n > 3 ? Maybe.make.none() : Maybe.make.some([n, n + 1]));
749
- * // [1, 2, 3]
750
- * ```
751
- */
752
- export const unfold: <A, S>(initial: S, f: (state: S) => Maybe<readonly [A, S]>) => readonly A[];
753
- export const NonEmpty: typeof ArrNonEmpty;
754
- export { };
755
- }
756
-
757
- /**
758
- * Safe conversion and arithmetic utilities for arbitrary-precision integers (`bigint`).
759
- * All functions are pure and data-last to compose cleanly with `pipe`.
760
- *
761
- * @example
762
- * ```ts
763
- * import { BigNum } from "@nlozgachev/pipelined/data";
764
- * import { pipe } from "@nlozgachev/pipelined/composition";
765
- *
766
- * const result = pipe(
767
- * BigNum.from.string("100"),
768
- * Maybe.map(BigNum.add(50n))
769
- * ); // Some(150n)
770
- * ```
771
- */
772
- declare namespace BigNum {
773
- namespace from {
774
- /**
775
- * Safely parses a string into a `bigint`. Returns `None` if parsing fails.
776
- *
777
- * @example
778
- * ```ts
779
- * BigNum.from.string("123"); // Some(123n)
780
- * BigNum.from.string("abc"); // None
781
- * ```
782
- */
783
- const string: (s: string) => Maybe<bigint>;
784
- /**
785
- * Safely converts a number into a `bigint`. Returns `None` for floats, `NaN`, or non-safe integers.
786
- *
787
- * @example
788
- * ```ts
789
- * BigNum.from.number(42); // Some(42n)
790
- * BigNum.from.number(3.14); // None
791
- * ```
792
- */
793
- const number: (n: number) => Maybe<bigint>;
794
- }
795
- namespace to {
796
- /**
797
- * Safely converts a `bigint` to a `number`. Returns `None` if the value is outside JavaScript's safe integer range.
798
- *
799
- * @example
800
- * ```ts
801
- * BigNum.to.number(42n); // Some(42)
802
- * BigNum.to.number(9007199254740993n); // None
803
- * ```
804
- */
805
- const number: (b: bigint) => Maybe<number>;
806
- }
807
- /**
808
- * Adds `b` to `a`. Data-last curried signature: `add(b)(a)` = `a + b`.
809
- *
810
- * @example
811
- * ```ts
812
- * pipe(10n, BigNum.add(5n)); // 15n
813
- * ```
814
- */
815
- const add: (b: bigint) => (a: bigint) => bigint;
816
- /**
817
- * Subtracts `b` from `a`. Data-last curried signature: `sub(b)(a)` = `a - b`.
818
- *
819
- * @example
820
- * ```ts
821
- * pipe(10n, BigNum.sub(3n)); // 7n
822
- * ```
823
- */
824
- const sub: (b: bigint) => (a: bigint) => bigint;
825
- /**
826
- * Multiplies `a` by `b`. Data-last curried signature: `mul(b)(a)` = `a * b`.
827
- *
828
- * @example
829
- * ```ts
830
- * pipe(6n, BigNum.mul(7n)); // 42n
831
- * ```
832
- */
833
- const mul: (b: bigint) => (a: bigint) => bigint;
834
- /**
835
- * Divides `a` by `b`. Returns `None` if `b` is `0n`.
836
- *
837
- * @example
838
- * ```ts
839
- * pipe(20n, BigNum.div(4n)); // Some(5n)
840
- * pipe(5n, BigNum.div(0n)); // None
841
- * ```
842
- */
843
- const div: (b: bigint) => (a: bigint) => Maybe<bigint>;
844
- /**
845
- * Computes remainder of `a / b`. Returns `None` if `b` is `0n`.
846
- *
847
- * @example
848
- * ```ts
849
- * pipe(10n, BigNum.mod(3n)); // Some(1n)
850
- * pipe(5n, BigNum.mod(0n)); // None
851
- * ```
852
- */
853
- const mod: (b: bigint) => (a: bigint) => Maybe<bigint>;
854
- /**
855
- * Clamps `a` between `min` and `max` (inclusive).
856
- *
857
- * @example
858
- * ```ts
859
- * pipe(150n, BigNum.clamp(0n, 100n)); // 100n
860
- * ```
861
- */
862
- const clamp: (min: bigint, max: bigint) => (a: bigint) => bigint;
863
- /**
864
- * Returns `true` if `a` is in the range `[start, end)` (inclusive start, exclusive end).
865
- *
866
- * @example
867
- * ```ts
868
- * pipe(5n, BigNum.inRange(1n, 10n)); // true
869
- * ```
870
- */
871
- const inRange: (start: bigint, end: bigint) => (a: bigint) => boolean;
872
- /**
873
- * Returns absolute value of a `bigint`.
874
- *
875
- * @example
876
- * ```ts
877
- * BigNum.abs(-42n); // 42n
878
- * ```
879
- */
880
- const abs: (a: bigint) => bigint;
881
- /**
882
- * Returns the minimum of `a` and `b`.
883
- *
884
- * @example
885
- * ```ts
886
- * pipe(10n, BigNum.min(5n)); // 5n
887
- * ```
888
- */
889
- const min: (b: bigint) => (a: bigint) => bigint;
890
- /**
891
- * Returns the maximum of `a` and `b`.
892
- *
893
- * @example
894
- * ```ts
895
- * pipe(10n, BigNum.max(5n)); // 10n
896
- * ```
897
- */
898
- const max: (b: bigint) => (a: bigint) => bigint;
42
+ interface TaskTraverse {
43
+ <A, B>(f: (a: A) => Task<B>): (data: readonly A[]) => Task<readonly B[]>;
44
+ Result: typeof ArrTaskResult.traverse;
45
+ }
46
+ interface TaskSequence {
47
+ <A>(data: readonly Task<A>[]): Task<readonly A[]>;
48
+ Result: typeof ArrTaskResult.sequence;
49
+ }
50
+ declare const Arr: {
51
+ head: <A>(data: readonly A[]) => Maybe<A>;
52
+ last: <A>(data: readonly A[]) => Maybe<A>;
53
+ tail: <A>(data: readonly A[]) => Maybe<readonly A[]>;
54
+ init: <A>(data: readonly A[]) => Maybe<readonly A[]>;
55
+ findFirst: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => Maybe<A>;
56
+ findLast: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => Maybe<A>;
57
+ findIndex: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => Maybe<number>;
58
+ map: <A, B>(f: (a: A) => B) => (data: readonly A[]) => readonly B[];
59
+ mapWithIndex: <A, B>(f: (i: number, a: A) => B) => (data: readonly A[]) => readonly B[];
60
+ filter: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly A[];
61
+ filterMap: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => readonly B[];
62
+ partition: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly [readonly A[], readonly A[]];
63
+ compact: <A>(data: readonly Maybe<A>[]) => readonly A[];
64
+ separate: <E, A>(data: readonly Result<E, A>[]) => readonly [readonly E[], readonly A[]];
65
+ partitionMap: <A, E, B>(f: (a: A) => Result<E, B>) => (data: readonly A[]) => readonly [readonly E[], readonly B[]];
66
+ groupBy: <A>(f: (a: A) => string) => (data: readonly A[]) => Record<string, NonEmptyArr<A>>;
67
+ uniq: <A>(data: readonly A[]) => readonly A[];
68
+ uniqBy: <A, B>(f: (a: A) => B) => (data: readonly A[]) => readonly A[];
69
+ uniqWith: <A>(eq: Equality<A>) => (data: readonly A[]) => readonly A[];
70
+ sortBy: <A>(compare: (a: A, b: A) => number) => (data: readonly A[]) => readonly A[];
71
+ sortWith: <A>(ord: Ordering<A>) => (data: readonly A[]) => readonly A[];
72
+ zip: <B>(other: readonly B[]) => <A>(data: readonly A[]) => readonly (readonly [A, B])[];
73
+ zipWith: <A, B, C>(f: (a: A, b: B) => C) => (other: readonly B[]) => (data: readonly A[]) => readonly C[];
74
+ intersperse: <A>(sep: A) => (data: readonly A[]) => readonly A[];
75
+ concat: <A>(other: readonly A[]) => (data: readonly A[]) => readonly A[];
76
+ chunksOf: (n: number) => <A>(data: readonly A[]) => readonly (readonly A[])[];
77
+ flatten: <A>(data: readonly (readonly A[])[]) => readonly A[];
78
+ flatMap: <A, B>(f: (a: A) => readonly B[]) => (data: readonly A[]) => readonly B[];
79
+ reduce: <A, B>(initial: B, f: (acc: B, a: A) => B) => (data: readonly A[]) => B;
80
+ prepend: <A>(value: A) => (data: readonly A[]) => NonEmptyArr<A>;
81
+ append: <A>(value: A) => (data: readonly A[]) => NonEmptyArr<A>;
82
+ size: <A>(data: readonly A[]) => number;
83
+ some: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => boolean;
84
+ every: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => boolean;
85
+ reverse: <A>(data: readonly A[]) => readonly A[];
86
+ insertAt: <A>(index: number, item: A) => (data: readonly A[]) => readonly A[];
87
+ removeAt: (index: number) => <A>(data: readonly A[]) => readonly A[];
88
+ take: (n: number) => <A>(data: readonly A[]) => readonly A[];
89
+ drop: (n: number) => <A>(data: readonly A[]) => readonly A[];
90
+ takeWhile: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly A[];
91
+ dropWhile: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly A[];
92
+ scan: <A, B>(initial: B, f: (acc: B, a: A) => B) => (data: readonly A[]) => readonly B[];
93
+ splitAt: (index: number) => <A>(data: readonly A[]) => readonly [readonly A[], readonly A[]];
94
+ partitionMaybe: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => readonly [failures: readonly A[], successes: readonly B[]];
95
+ at: (index: number) => <A>(data: readonly A[]) => Maybe<A>;
96
+ findMap: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => Maybe<B>;
97
+ indexBy: <A, K>(keyFn: (a: A) => K) => (data: readonly A[]) => ReadonlyMap<K, A>;
98
+ frequencies: <A>(data: readonly A[]) => ReadonlyMap<A, number>;
99
+ chunkBy: <A, K>(keyFn: (a: A) => K) => (data: readonly A[]) => readonly (readonly A[])[];
100
+ dedupeAdjacent: <A>(eq?: Equality<A>) => (data: readonly A[]) => readonly A[];
101
+ windowed: (windowSize: number, options?: {
102
+ step?: number;
103
+ }) => <A>(data: readonly A[]) => readonly (readonly A[])[];
104
+ unfold: <A, S>(initial: S, f: (state: S) => Maybe<readonly [A, S]>) => readonly A[];
105
+ from: {
106
+ Array: <A>(data: readonly A[]) => Maybe<NonEmptyArr<A>>;
107
+ };
108
+ is: {
109
+ empty: <A>(data: readonly A[]) => data is readonly [];
110
+ nonEmpty: <A>(data: readonly A[]) => data is NonEmptyArr<A>;
111
+ };
112
+ traverse: {
113
+ Maybe: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => Maybe<readonly B[]>;
114
+ Result: <E, A, B>(f: (a: A) => Result<E, B>) => (data: readonly A[]) => Result<E, readonly B[]>;
115
+ Task: TaskTraverse;
116
+ };
117
+ sequence: {
118
+ Maybe: <A>(data: readonly Maybe<A>[]) => Maybe<readonly A[]>;
119
+ Result: <E, A>(data: readonly Result<E, A>[]) => Result<E, readonly A[]>;
120
+ Task: TaskSequence;
121
+ };
122
+ NonEmpty: {
123
+ singleton: <A>(value: A) => NonEmptyArr<A>;
124
+ from: {
125
+ Array: <A>(data: readonly A[]) => Maybe<NonEmptyArr<A>>;
126
+ };
127
+ head: <A>(data: NonEmptyArr<A>) => A;
128
+ last: <A>(data: NonEmptyArr<A>) => A;
129
+ tail: <A>(data: NonEmptyArr<A>) => readonly A[];
130
+ reduce: <A>(f: (acc: A, a: A) => A) => (data: NonEmptyArr<A>) => A;
131
+ map: <A, B>(f: (a: A) => B) => (data: NonEmptyArr<A>) => NonEmptyArr<B>;
132
+ mapWithIndex: <A, B>(f: (i: number, a: A) => B) => (data: NonEmptyArr<A>) => NonEmptyArr<B>;
133
+ intersperse: <A>(sep: A) => (data: NonEmptyArr<A>) => NonEmptyArr<A>;
134
+ concat: <A>(other: readonly A[]) => (data: NonEmptyArr<A>) => NonEmptyArr<A>;
135
+ reverse: <A>(data: NonEmptyArr<A>) => NonEmptyArr<A>;
136
+ };
137
+ };
138
+ declare namespace Arr {
139
+ type NonEmpty<A> = NonEmptyArr<A>;
899
140
  }
900
141
 
901
142
  /**
902
- * A branded type representing a key-value dictionary with at least one entry.
903
- */
904
- type NonEmptyMap<K, V> = Brand<NonEmpty<"Dict">, ReadonlyMap<K, V>>;
905
- /**
906
- * Functional utilities for key-value dictionaries (`ReadonlyMap<K, V>`). All functions are pure
907
- * and data-last — they compose naturally with `pipe`.
908
- *
909
- * Unlike plain objects (`Rec`), dictionaries support any key type, preserve insertion order, and
910
- * make membership checks explicit via `lookup` returning `Maybe`.
143
+ * Safe conversion and arithmetic utilities for arbitrary-precision integers (`bigint`).
144
+ * All functions are pure and data-last to compose cleanly with `pipe`.
911
145
  *
912
146
  * @example
913
147
  * ```ts
914
- * import { Dict } from "@nlozgachev/pipelined/data";
148
+ * import { BigNum } from "@nlozgachev/pipelined/data";
915
149
  * import { pipe } from "@nlozgachev/pipelined/composition";
916
150
  *
917
- * const scores = pipe(
918
- * Dict.from.entries([["alice", 10], ["bob", 8], ["carol", 10]] as const),
919
- * Dict.filter(n => n >= 10),
920
- * Dict.map(n => `${n} points`),
921
- * );
922
- * // ReadonlyMap { "alice" => "10 points", "carol" => "10 points" }
151
+ * const result = pipe(
152
+ * BigNum.from.string("100"),
153
+ * Maybe.map(BigNum.add(50n))
154
+ * ); // Some(150n)
923
155
  * ```
924
156
  */
925
- declare namespace DictNonEmpty {
926
- /**
927
- * Creates a NonEmptyMap containing a single key-value entry.
928
- *
929
- * @example
930
- * ```ts
931
- * Dict.NonEmpty.singleton("name", "Alice"); // ReadonlyMap { "name" => "Alice" }
932
- * ```
933
- */
934
- const singleton: <K, V>(key: K, value: V) => NonEmptyMap<K, V>;
935
- namespace from {
936
- /**
937
- * Returns Some containing NonEmptyMap if the map is not empty, None otherwise.
938
- *
939
- * @example
940
- * ```ts
941
- * Dict.NonEmpty.from.Map(Dict.from.entries([["a", 1]])); // Some(ReadonlyMap { "a" => 1 })
942
- * Dict.NonEmpty.from.Map(Dict.empty()); // None
943
- * ```
944
- */
945
- const Map: <K, V>(m: ReadonlyMap<K, V>) => Maybe<NonEmptyMap<K, V>>;
946
- }
947
- /**
948
- * Returns a non-empty array of keys, in insertion order.
949
- *
950
- * @example
951
- * ```ts
952
- * Dict.NonEmpty.keys(Dict.NonEmpty.singleton("a", 1)); // ["a"]
953
- * ```
954
- */
955
- const keys: <K, V>(m: NonEmptyMap<K, V>) => NonEmptyArr<K>;
956
- /**
957
- * Returns a non-empty array of values, in insertion order.
958
- *
959
- * @example
960
- * ```ts
961
- * Dict.NonEmpty.values(Dict.NonEmpty.singleton("a", 1)); // [1]
962
- * ```
963
- */
964
- const values: <K, V>(m: NonEmptyMap<K, V>) => NonEmptyArr<V>;
965
- /**
966
- * Returns a non-empty array of entry tuples, in insertion order.
967
- *
968
- * @example
969
- * ```ts
970
- * Dict.NonEmpty.entries(Dict.NonEmpty.singleton("a", 1)); // [["a", 1]]
971
- * ```
972
- */
973
- const entries: <K, V>(m: NonEmptyMap<K, V>) => NonEmptyArr<readonly [K, V]>;
974
- /**
975
- * Reduces a NonEmptyMap's values from the left without an initial seed value.
976
- *
977
- * @example
978
- * ```ts
979
- * pipe(Dict.NonEmpty.singleton("a", 1), Dict.NonEmpty.reduce((a, b) => a + b)); // 1
980
- * ```
981
- */
982
- const reduce: <V>(f: (acc: V, value: V) => V) => <K>(m: NonEmptyMap<K, V>) => V;
983
- /**
984
- * Transforms each value in the non-empty dictionary.
985
- *
986
- * @example
987
- * ```ts
988
- * pipe(Dict.NonEmpty.singleton("a", 1), Dict.NonEmpty.map(n => n * 2));
989
- * // ReadonlyMap { "a" => 2 }
990
- * ```
991
- */
992
- const map: <A, B>(f: (a: A) => B) => <K>(m: NonEmptyMap<K, A>) => NonEmptyMap<K, B>;
993
- /**
994
- * Transforms each value in the non-empty dictionary, also receiving the key.
995
- *
996
- * @example
997
- * ```ts
998
- * pipe(Dict.NonEmpty.singleton("a", 1), Dict.NonEmpty.mapWithKey((k, v) => `${k}:${v}`));
999
- * // ReadonlyMap { "a" => "a:1" }
1000
- * ```
1001
- */
1002
- const mapWithKey: <K, A, B>(f: (key: K, a: A) => B) => (m: NonEmptyMap<K, A>) => NonEmptyMap<K, B>;
1003
- }
1004
- declare namespace Dict {
1005
- /**
1006
- * A branded type representing a key-value dictionary with at least one entry.
1007
- */
1008
- type NonEmpty<K, V> = NonEmptyMap<K, V>;
1009
- namespace is {
1010
- /**
1011
- * Returns `true` if the dictionary has no entries.
1012
- *
1013
- * @example
1014
- * ```ts
1015
- * Dict.is.empty(Dict.empty()); // true
1016
- * ```
1017
- */
1018
- const empty: <K, V>(m: ReadonlyMap<K, V>) => boolean;
157
+ declare const BigNum: {
158
+ from: {
1019
159
  /**
1020
- * Type guard to check if a dictionary is non-empty.
160
+ * Safely parses a string into a `bigint`. Returns `None` if parsing fails.
1021
161
  *
1022
162
  * @example
1023
163
  * ```ts
1024
- * Dict.is.nonEmpty(Dict.from.entries([["a", 1]])); // true
1025
- * Dict.is.nonEmpty(Dict.empty()); // false
164
+ * BigNum.from.string("123"); // Some(123n)
165
+ * BigNum.from.string("abc"); // None
1026
166
  * ```
1027
167
  */
1028
- const nonEmpty: <K, V>(m: ReadonlyMap<K, V>) => m is NonEmpty<K, V>;
1029
- }
1030
- /**
1031
- * Creates an empty dictionary.
1032
- *
1033
- * @example
1034
- * ```ts
1035
- * Dict.empty<string, number>(); // ReadonlyMap {}
1036
- * ```
1037
- */
1038
- const empty: <K, V>() => ReadonlyMap<K, V>;
1039
- /**
1040
- * Creates a dictionary with a single entry.
1041
- *
1042
- * @example
1043
- * ```ts
1044
- * Dict.singleton("name", "Alice"); // ReadonlyMap { "name" => "Alice" }
1045
- * ```
1046
- */
1047
- const singleton: <K, V>(key: K, value: V) => ReadonlyMap<K, V>;
1048
- namespace from {
168
+ string: (s: string) => Maybe<bigint>;
1049
169
  /**
1050
- * Creates a dictionary from an array of key-value pairs.
170
+ * Safely converts a number into a `bigint`. Returns `None` for floats, `NaN`, or non-safe integers.
1051
171
  *
1052
172
  * @example
1053
173
  * ```ts
1054
- * Dict.from.entries([["a", 1], ["b", 2]]); // ReadonlyMap { "a" => 1, "b" => 2 }
174
+ * BigNum.from.number(42); // Some(42n)
175
+ * BigNum.from.number(3.14); // None
1055
176
  * ```
1056
177
  */
1057
- const entries: <K, V>(entries: readonly (readonly [K, V])[]) => ReadonlyMap<K, V>;
178
+ number: (n: number) => Maybe<bigint>;
179
+ };
180
+ to: {
1058
181
  /**
1059
- * Creates a dictionary from a plain object. Keys are always strings.
182
+ * Safely converts a `bigint` to a `number`. Returns `None` if the value is outside JavaScript's safe integer range.
1060
183
  *
1061
184
  * @example
1062
185
  * ```ts
1063
- * Dict.from.Record({ a: 1, b: 2 }); // ReadonlyMap { "a" => 1, "b" => 2 }
186
+ * BigNum.to.number(42n); // Some(42)
187
+ * BigNum.to.number(9007199254740993n); // None
1064
188
  * ```
1065
189
  */
1066
- const Record: <V>(rec: Readonly<Record<string, V>>) => ReadonlyMap<string, V>;
1067
- }
1068
- /**
1069
- * Groups elements of an array into a dictionary keyed by the result of `keyFn`. Each key maps
1070
- * to the array of elements that produced it, in insertion order. Uses the native `Map.groupBy`
1071
- * when available, falling back to a manual loop in older environments.
1072
- *
1073
- * @example
1074
- * ```ts
1075
- * pipe(
1076
- * [{ name: "alice", role: "admin" }, { name: "bob", role: "viewer" }, { name: "carol", role: "admin" }],
1077
- * Dict.groupBy(user => user.role),
1078
- * );
1079
- * // ReadonlyMap { "admin" => [alice, carol], "viewer" => [bob] }
1080
- * ```
1081
- */
1082
- const groupBy: <K, A>(keyFn: (a: A) => K) => (items: readonly A[]) => ReadonlyMap<K, readonly A[]>;
1083
- /**
1084
- * Returns `true` if the dictionary contains the given key.
1085
- *
1086
- * @example
1087
- * ```ts
1088
- * pipe(Dict.from.entries([["a", 1]]), Dict.has("a")); // true
1089
- * pipe(Dict.from.entries([["a", 1]]), Dict.has("b")); // false
1090
- * ```
1091
- */
1092
- const has: <K>(key: K) => <V>(m: ReadonlyMap<K, V>) => boolean;
1093
- /**
1094
- * Looks up a value by key, returning `Some(value)` if found and `None` if not.
1095
- *
1096
- * @example
1097
- * ```ts
1098
- * pipe(Dict.from.entries([["a", 1]]), Dict.lookup("a")); // Some(1)
1099
- * pipe(Dict.from.entries([["a", 1]]), Dict.lookup("b")); // None
1100
- * ```
1101
- */
1102
- const lookup: <K>(key: K) => <V>(m: ReadonlyMap<K, V>) => Maybe<V>;
1103
- /**
1104
- * Returns the number of entries in the dictionary.
1105
- *
1106
- * @example
1107
- * ```ts
1108
- * Dict.size(Dict.from.entries([["a", 1], ["b", 2]])); // 2
1109
- * ```
1110
- */
1111
- const size: <K, V>(m: ReadonlyMap<K, V>) => number;
1112
- /**
1113
- * Returns all keys as a readonly array, in insertion order.
1114
- *
1115
- * @example
1116
- * ```ts
1117
- * Dict.keys(Dict.from.entries([["a", 1], ["b", 2]])); // ["a", "b"]
1118
- * ```
1119
- */
1120
- const keys: <K, V>(m: ReadonlyMap<K, V>) => readonly K[];
1121
- /**
1122
- * Returns all values as a readonly array, in insertion order.
1123
- *
1124
- * @example
1125
- * ```ts
1126
- * Dict.values(Dict.from.entries([["a", 1], ["b", 2]])); // [1, 2]
1127
- * ```
1128
- */
1129
- const values: <K, V>(m: ReadonlyMap<K, V>) => readonly V[];
1130
- /**
1131
- * Returns all key-value pairs as a readonly array of tuples, in insertion order.
1132
- *
1133
- * @example
1134
- * ```ts
1135
- * Dict.entries(Dict.from.entries([["a", 1], ["b", 2]])); // [["a", 1], ["b", 2]]
1136
- * ```
1137
- */
1138
- const entries: <K, V>(m: ReadonlyMap<K, V>) => readonly (readonly [K, V])[];
1139
- /**
1140
- * Returns a new dictionary with the given key set to the given value.
1141
- * If the key already exists, its value is replaced.
1142
- *
1143
- * @example
1144
- * ```ts
1145
- * pipe(Dict.from.entries([["a", 1]]), Dict.insert("b", 2));
1146
- * // ReadonlyMap { "a" => 1, "b" => 2 }
1147
- * ```
1148
- */
1149
- const insert: <K, V>(key: K, value: V) => (m: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
1150
- /**
1151
- * Returns a new dictionary with the given key removed.
1152
- * If the key does not exist, the dictionary is returned unchanged.
1153
- *
1154
- * @example
1155
- * ```ts
1156
- * pipe(Dict.from.entries([["a", 1], ["b", 2]]), Dict.remove("a"));
1157
- * // ReadonlyMap { "b" => 2 }
1158
- * ```
1159
- */
1160
- const remove: <K, V>(key: K) => (m: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
1161
- /**
1162
- * Returns a new dictionary with the value at `key` set by `f`. If the key does not exist,
1163
- * `f` receives `None`. If the key exists, `f` receives `Some(currentValue)`.
1164
- *
1165
- * Useful for incrementing counters, initialising defaults, or conditional updates.
1166
- *
1167
- * @example
1168
- * ```ts
1169
- * const increment = (opt: Maybe<number>) => pipe(opt, Maybe.getOrElse(() => 0)) + 1;
1170
- * pipe(Dict.from.entries([["views", 5]]), Dict.upsert("views", increment)); // { views: 6 }
1171
- * pipe(Dict.from.entries([["views", 5]]), Dict.upsert("likes", increment)); // { views: 5, likes: 1 }
1172
- * ```
1173
- */
1174
- const upsert: <K, V>(key: K, f: (existing: Maybe<V>) => V) => (m: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
1175
- /**
1176
- * Transforms each value in the dictionary.
1177
- *
1178
- * @example
1179
- * ```ts
1180
- * pipe(Dict.from.entries([["a", 1], ["b", 2]]), Dict.map(n => n * 2));
1181
- * // ReadonlyMap { "a" => 2, "b" => 4 }
1182
- * ```
1183
- */
1184
- const map: <A, B>(f: (a: A) => B) => <K>(m: ReadonlyMap<K, A>) => ReadonlyMap<K, B>;
1185
- /**
1186
- * Transforms each value in the dictionary, also receiving the key.
1187
- *
1188
- * @example
1189
- * ```ts
1190
- * pipe(Dict.from.entries([["a", 1], ["b", 2]]), Dict.mapWithKey((k, v) => `${k}:${v}`));
1191
- * // ReadonlyMap { "a" => "a:1", "b" => "b:2" }
1192
- * ```
1193
- */
1194
- const mapWithKey: <K, A, B>(f: (key: K, a: A) => B) => (m: ReadonlyMap<K, A>) => ReadonlyMap<K, B>;
190
+ number: (b: bigint) => Maybe<number>;
191
+ };
1195
192
  /**
1196
- * Returns a new dictionary containing only the entries for which the predicate returns `true`.
193
+ * Adds `b` to `a`. Data-last curried signature: `add(b)(a)` = `a + b`.
1197
194
  *
1198
195
  * @example
1199
196
  * ```ts
1200
- * pipe(Dict.from.entries([["a", 1], ["b", 3], ["c", 0]]), Dict.filter(n => n > 0));
1201
- * // ReadonlyMap { "a" => 1, "b" => 3 }
197
+ * pipe(10n, BigNum.add(5n)); // 15n
1202
198
  * ```
1203
199
  */
1204
- const filter: <A>(predicate: (a: A) => boolean) => <K>(m: ReadonlyMap<K, A>) => ReadonlyMap<K, A>;
200
+ add: (b: bigint) => (a: bigint) => bigint;
1205
201
  /**
1206
- * Returns a new dictionary containing only the entries for which the predicate returns `true`.
1207
- * The predicate also receives the key.
202
+ * Subtracts `b` from `a`. Data-last curried signature: `sub(b)(a)` = `a - b`.
1208
203
  *
1209
204
  * @example
1210
205
  * ```ts
1211
- * pipe(Dict.from.entries([["a", 1], ["b", 2]]), Dict.filterWithKey((k, v) => k !== "a" && v > 0));
1212
- * // ReadonlyMap { "b" => 2 }
206
+ * pipe(10n, BigNum.sub(3n)); // 7n
1213
207
  * ```
1214
208
  */
1215
- const filterWithKey: <K, A>(predicate: (key: K, a: A) => boolean) => (m: ReadonlyMap<K, A>) => ReadonlyMap<K, A>;
209
+ sub: (b: bigint) => (a: bigint) => bigint;
1216
210
  /**
1217
- * Removes all `None` values from a `ReadonlyMap<K, Maybe<A>>`, returning a plain
1218
- * `ReadonlyMap<K, A>`. Useful when building dictionaries from fallible lookups.
211
+ * Multiplies `a` by `b`. Data-last curried signature: `mul(b)(a)` = `a * b`.
1219
212
  *
1220
213
  * @example
1221
214
  * ```ts
1222
- * Dict.compact(Dict.from.entries<string, Maybe<number>>([
1223
- * ["a", Maybe.make.some(1)],
1224
- * ["b", Maybe.make.none()],
1225
- * ["c", Maybe.make.some(3)],
1226
- * ]));
1227
- * // ReadonlyMap { "a" => 1, "c" => 3 }
215
+ * pipe(6n, BigNum.mul(7n)); // 42n
1228
216
  * ```
1229
217
  */
1230
- const compact: <K, A>(m: ReadonlyMap<K, Maybe<A>>) => ReadonlyMap<K, A>;
218
+ mul: (b: bigint) => (a: bigint) => bigint;
1231
219
  /**
1232
- * Applies `f` to each value. Entries where `f` returns `None` are removed; entries where
1233
- * `f` returns `Some` are kept with the unwrapped value. Combines map and filter in one pass.
220
+ * Divides `a` by `b`. Returns `None` if `b` is `0n`.
1234
221
  *
1235
222
  * @example
1236
223
  * ```ts
1237
- * const parse = (s: string): Maybe<number> => {
1238
- * const n = Number(s);
1239
- * return isNaN(n) ? Maybe.make.none() : Maybe.make.some(n);
1240
- * };
1241
- * Dict.filterMap(parse)(Dict.from.Record({ a: "1", b: "two", c: "3" }));
1242
- * // ReadonlyMap { "a" => 1, "c" => 3 }
224
+ * pipe(20n, BigNum.div(4n)); // Some(5n)
225
+ * pipe(5n, BigNum.div(0n)); // None
1243
226
  * ```
1244
227
  */
1245
- const filterMap: <A, B>(f: (a: A) => Maybe<B>) => <K>(m: ReadonlyMap<K, A>) => ReadonlyMap<K, B>;
228
+ div: (b: bigint) => (a: bigint) => Maybe<bigint>;
1246
229
  /**
1247
- * Merges two dictionaries. When both contain the same key, the value from `other` takes
1248
- * precedence.
230
+ * Computes remainder of `a / b`. Returns `None` if `b` is `0n`.
1249
231
  *
1250
232
  * @example
1251
233
  * ```ts
1252
- * pipe(
1253
- * Dict.from.entries([["a", 1], ["b", 2]]),
1254
- * Dict.union(Dict.from.entries([["b", 3], ["c", 4]])),
1255
- * );
1256
- * // ReadonlyMap { "a" => 1, "b" => 3, "c" => 4 }
234
+ * pipe(10n, BigNum.mod(3n)); // Some(1n)
235
+ * pipe(5n, BigNum.mod(0n)); // None
1257
236
  * ```
1258
237
  */
1259
- const union: <K, V>(other: ReadonlyMap<K, V>) => (m: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
238
+ mod: (b: bigint) => (a: bigint) => Maybe<bigint>;
1260
239
  /**
1261
- * Returns a new dictionary containing only the entries whose keys appear in both dictionaries.
1262
- * Values are taken from the left (base) dictionary.
240
+ * Clamps `a` between `min` and `max` (inclusive).
1263
241
  *
1264
242
  * @example
1265
243
  * ```ts
1266
- * pipe(
1267
- * Dict.from.entries([["a", 1], ["b", 2], ["c", 3]]),
1268
- * Dict.intersection(Dict.from.entries([["b", 99], ["c", 0]])),
1269
- * );
1270
- * // ReadonlyMap { "b" => 2, "c" => 3 }
244
+ * pipe(150n, BigNum.clamp(0n, 100n)); // 100n
1271
245
  * ```
1272
246
  */
1273
- const intersection: <K, V>(other: ReadonlyMap<K, unknown>) => (m: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
247
+ clamp: (min: bigint, max: bigint) => (a: bigint) => bigint;
1274
248
  /**
1275
- * Returns a new dictionary containing only the entries whose keys do not appear in `other`.
249
+ * Returns `true` if `a` is in the range `[start, end)` (inclusive start, exclusive end).
1276
250
  *
1277
251
  * @example
1278
252
  * ```ts
1279
- * pipe(
1280
- * Dict.from.entries([["a", 1], ["b", 2], ["c", 3]]),
1281
- * Dict.difference(Dict.from.entries([["b", 0]])),
1282
- * );
1283
- * // ReadonlyMap { "a" => 1, "c" => 3 }
253
+ * pipe(5n, BigNum.inRange(1n, 10n)); // true
1284
254
  * ```
1285
255
  */
1286
- const difference: <K, V>(other: ReadonlyMap<K, unknown>) => (m: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
256
+ inRange: (start: bigint, end: bigint) => (a: bigint) => boolean;
1287
257
  /**
1288
- * Folds the dictionary into a single value by applying `f` to each value in insertion order.
1289
- * When you also need the key, use `reduceWithKey`.
258
+ * Returns absolute value of a `bigint`.
1290
259
  *
1291
260
  * @example
1292
261
  * ```ts
1293
- * Dict.reduce(0, (acc, value: number) => acc + value)(
1294
- * Dict.from.entries([["a", 1], ["b", 2], ["c", 3]])
1295
- * ); // 6
262
+ * BigNum.abs(-42n); // 42n
1296
263
  * ```
1297
264
  */
1298
- const reduce: <A, B>(init: B, f: (acc: B, value: A) => B) => <K>(m: ReadonlyMap<K, A>) => B;
265
+ abs: (a: bigint) => bigint;
1299
266
  /**
1300
- * Folds the dictionary into a single value by applying `f` to each key-value pair in insertion
1301
- * order.
267
+ * Returns the minimum of `a` and `b`.
1302
268
  *
1303
269
  * @example
1304
270
  * ```ts
1305
- * Dict.reduceWithKey("", (acc, value, key) => acc + key + ":" + value + " ")(
1306
- * Dict.from.entries([["a", 1], ["b", 2]])
1307
- * ); // "a:1 b:2 "
271
+ * pipe(10n, BigNum.min(5n)); // 5n
1308
272
  * ```
1309
273
  */
1310
- const reduceWithKey: <K, A, B>(init: B, f: (acc: B, value: A, key: K) => B) => (m: ReadonlyMap<K, A>) => B;
274
+ min: (b: bigint) => (a: bigint) => bigint;
1311
275
  /**
1312
- * Merges two maps using a custom combination function on key collisions.
1313
- * Supports both uncurried `Dict.mergeWith(combine)(first, second)` and curried `pipe(first, Dict.mergeWith(combine)(second))`.
276
+ * Returns the maximum of `a` and `b`.
1314
277
  *
1315
278
  * @example
1316
279
  * ```ts
1317
- * const combineStats = Dict.mergeWith((a: number, b: number) => a + b);
1318
- * const map1 = Dict.from.entries([["a", 1], ["b", 2]]);
1319
- * const map2 = Dict.from.entries([["b", 3], ["c", 4]]);
1320
- * combineStats(map1, map2);
1321
- * pipe(map1, combineStats(map2));
280
+ * pipe(10n, BigNum.max(5n)); // 10n
1322
281
  * ```
1323
282
  */
1324
- function mergeWith<K, V>(combine: (a: V, b: V) => V): {
1325
- (second: ReadonlyMap<K, V>): (first: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
1326
- (first: ReadonlyMap<K, V>, second: ReadonlyMap<K, V>): ReadonlyMap<K, V>;
283
+ max: (b: bigint) => (a: bigint) => bigint;
284
+ };
285
+
286
+ /**
287
+ * A branded type representing a key-value dictionary with at least one entry.
288
+ */
289
+ type NonEmptyMap<K, V> = Brand<NonEmpty<"Dict">, ReadonlyMap<K, V>>;
290
+ declare function mergeWith$1<V>(combine: (a: V, b: V) => V): {
291
+ <K>(first: ReadonlyMap<K, V>, second: ReadonlyMap<K, V>): ReadonlyMap<K, V>;
292
+ <K>(second: ReadonlyMap<K, V>): (first: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
293
+ };
294
+ declare const Dict: {
295
+ is: {
296
+ empty: <K, V>(m: ReadonlyMap<K, V>) => boolean;
297
+ nonEmpty: <K, V>(m: ReadonlyMap<K, V>) => m is NonEmptyMap<K, V>;
1327
298
  };
1328
- namespace to {
1329
- /**
1330
- * Converts a `ReadonlyMap<string, V>` to a plain object. Only meaningful when keys are strings.
1331
- *
1332
- * @example
1333
- * ```ts
1334
- * Dict.to.Record(Dict.from.entries([["a", 1], ["b", 2]])); // { a: 1, b: 2 }
1335
- * ```
1336
- */
1337
- const Record: <V>(m: ReadonlyMap<string, V>) => Readonly<Record<string, V>>;
1338
- }
1339
- /**
1340
- * Transforms key and value pairs simultaneously into a new ReadonlyMap.
1341
- *
1342
- * @example
1343
- * ```ts
1344
- * pipe(
1345
- * Dict.from.entries([["a", 1], ["b", 2]]),
1346
- * Dict.mapEntries((k, v) => [k.toUpperCase(), v * 10])
1347
- * ); // Map { "A" => 10, "B" => 20 }
1348
- * ```
1349
- */
1350
- const mapEntries: <K1, V1, K2, V2>(f: (key: K1, value: V1) => readonly [K2, V2]) => (data: ReadonlyMap<K1, V1>) => ReadonlyMap<K2, V2>;
1351
- /**
1352
- * Transforms keys of a ReadonlyMap while preserving values.
1353
- *
1354
- * @example
1355
- * ```ts
1356
- * pipe(
1357
- * Dict.from.entries([["a", 1], ["b", 2]]),
1358
- * Dict.mapKeys((k) => k.toUpperCase())
1359
- * ); // Map { "A" => 1, "B" => 2 }
1360
- * ```
299
+ empty: <K, V>() => ReadonlyMap<K, V>;
300
+ singleton: <K, V>(key: K, value: V) => ReadonlyMap<K, V>;
301
+ from: {
302
+ entries: <K, V>(entries: readonly (readonly [K, V])[]) => ReadonlyMap<K, V>;
303
+ Record: <K extends string, V>(record: Readonly<Record<K, V>>) => ReadonlyMap<K, V>;
304
+ Array: <K, V>(data: readonly (readonly [K, V])[]) => ReadonlyMap<K, V>;
305
+ nullable: <K, V>(data: ReadonlyMap<K, V> | null | undefined) => Maybe<ReadonlyMap<K, V>>;
306
+ };
307
+ to: {
308
+ Record: <K extends string, V>(map: ReadonlyMap<K, V>) => Readonly<Record<K, V>>;
309
+ };
310
+ groupBy: <A, K>(f: (a: A) => K) => (as: readonly A[]) => ReadonlyMap<K, NonEmptyArr<A>>;
311
+ has: <K, V>(key: K) => (data: ReadonlyMap<K, V>) => boolean;
312
+ lookup: <K, V>(key: K) => (data: ReadonlyMap<K, V>) => Maybe<V>;
313
+ size: <K, V>(data: ReadonlyMap<K, V>) => number;
314
+ keys: <K, V>(data: ReadonlyMap<K, V>) => readonly K[];
315
+ values: <K, V>(data: ReadonlyMap<K, V>) => readonly V[];
316
+ entries: <K, V>(data: ReadonlyMap<K, V>) => readonly (readonly [K, V])[];
317
+ insert: <K, V>(key: K, value: V) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
318
+ remove: <K, V>(key: K) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
319
+ upsert: <K, V>(key: K, f: (existing: Maybe<V>) => V) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
320
+ map: <A, B>(f: (a: A) => B) => <K>(data: ReadonlyMap<K, A>) => ReadonlyMap<K, B>;
321
+ mapWithKey: <K, A, B>(f: (key: K, value: A) => B) => (data: ReadonlyMap<K, A>) => ReadonlyMap<K, B>;
322
+ filter: <A>(predicate: (a: A) => boolean) => <K>(data: ReadonlyMap<K, A>) => ReadonlyMap<K, A>;
323
+ filterWithKey: <K, A>(predicate: (key: K, value: A) => boolean) => (data: ReadonlyMap<K, A>) => ReadonlyMap<K, A>;
324
+ compact: <K, A>(data: ReadonlyMap<K, Maybe<A>>) => ReadonlyMap<K, A>;
325
+ filterMap: <A, B>(f: (a: A) => Maybe<B>) => <K>(data: ReadonlyMap<K, A>) => ReadonlyMap<K, B>;
326
+ union: <K, V>(other: ReadonlyMap<K, V>) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
327
+ intersection: <K, V>(other: ReadonlyMap<K, V>) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
328
+ difference: <K, V>(other: ReadonlyMap<K, V>) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
329
+ reduce: <B, V>(init: B, f: (acc: B, value: V) => B) => <K>(data: ReadonlyMap<K, V>) => B;
330
+ reduceWithKey: <B, K, V>(init: B, f: (acc: B, value: V, key: K) => B) => (data: ReadonlyMap<K, V>) => B;
331
+ mergeWith: typeof mergeWith$1;
332
+ mapEntries: <K1, V1, K2, V2>(f: (key: K1, value: V1) => readonly [K2, V2]) => (data: ReadonlyMap<K1, V1>) => ReadonlyMap<K2, V2>;
333
+ mapKeys: <K1, K2, V>(f: (key: K1) => K2) => (data: ReadonlyMap<K1, V>) => ReadonlyMap<K2, V>;
334
+ NonEmpty: {
335
+ singleton: <K, V>(key: K, value: V) => NonEmptyMap<K, V>;
336
+ from: {
337
+ Map: <K, V>(m: ReadonlyMap<K, V>) => Maybe<NonEmptyMap<K, V>>;
338
+ };
339
+ keys: <K, V>(m: NonEmptyMap<K, V>) => NonEmptyArr<K>;
340
+ values: <K, V>(m: NonEmptyMap<K, V>) => NonEmptyArr<V>;
341
+ entries: <K, V>(m: NonEmptyMap<K, V>) => NonEmptyArr<readonly [K, V]>;
342
+ reduce: <V>(f: (acc: V, value: V) => V) => <K>(m: NonEmptyMap<K, V>) => V;
343
+ map: <A, B>(f: (a: A) => B) => <K>(m: NonEmptyMap<K, A>) => NonEmptyMap<K, B>;
344
+ mapWithKey: <K, A, B>(f: (key: K, a: A) => B) => (m: NonEmptyMap<K, A>) => NonEmptyMap<K, B>;
345
+ };
346
+ };
347
+ declare namespace Dict {
348
+ /**
349
+ * A branded type representing a key-value dictionary with at least one entry.
1361
350
  */
1362
- const mapKeys: <K1, K2, V>(f: (key: K1) => K2) => (data: ReadonlyMap<K1, V>) => ReadonlyMap<K2, V>;
1363
- const NonEmpty: typeof DictNonEmpty;
351
+ type NonEmpty<K, V> = NonEmptyMap<K, V>;
1364
352
  }
1365
353
 
1366
354
  /**
@@ -1378,7 +366,7 @@ declare namespace Dict {
1378
366
  * ); // Ok("Alice")
1379
367
  * ```
1380
368
  */
1381
- declare namespace Json {
369
+ declare const Json: {
1382
370
  /**
1383
371
  * Safely parses a JSON string into `unknown`.
1384
372
  * Converts thrown exceptions into a `Result<SyntaxError, unknown>`.
@@ -1389,7 +377,7 @@ declare namespace Json {
1389
377
  * Json.parse('{invalid}'); // Err(SyntaxError)
1390
378
  * ```
1391
379
  */
1392
- const parse: (text: string) => Result<SyntaxError, unknown>;
380
+ parse: (text: string) => Result<SyntaxError, unknown>;
1393
381
  /**
1394
382
  * Safely stringifies a value into a JSON string.
1395
383
  * Converts thrown exceptions (e.g. circular references) into a `Result<TypeError, string>`.
@@ -1399,27 +387,11 @@ declare namespace Json {
1399
387
  * Json.stringify({ a: 1 }); // Ok('{"a":1}')
1400
388
  * ```
1401
389
  */
1402
- const stringify: (value: unknown, replacer?: (this: any, key: string, value: any) => any, space?: string | number) => Result<TypeError, string>;
1403
- }
390
+ stringify: (value: unknown, replacer?: (this: any, key: string, value: any) => any, space?: string | number) => Result<TypeError, string>;
391
+ };
1404
392
 
1405
- /**
1406
- * Number utilities for common operations. All transformation functions are data-last
1407
- * and curried so they compose naturally with `pipe` and `Arr.map`.
1408
- *
1409
- * @example
1410
- * ```ts
1411
- * import { Num } from "@nlozgachev/pipelined/data";
1412
- * import { pipe } from "@nlozgachev/pipelined/composition";
1413
- *
1414
- * pipe(
1415
- * Num.range(1, 6),
1416
- * Arr.map(Num.multiply(2)),
1417
- * Arr.filter(Num.between(4, 8))
1418
- * ); // [4, 6, 8]
1419
- * ```
1420
- */
1421
- declare namespace Num {
1422
- namespace is {
393
+ declare const Num: {
394
+ is: {
1423
395
  /**
1424
396
  * Returns `true` when the number is equal to zero.
1425
397
  *
@@ -1429,7 +401,7 @@ declare namespace Num {
1429
401
  * Num.is.zero(5); // false
1430
402
  * ```
1431
403
  */
1432
- const zero: (n: number) => boolean;
404
+ zero: (n: number) => boolean;
1433
405
  /**
1434
406
  * Returns `true` when the number is a whole integer.
1435
407
  *
@@ -1439,7 +411,7 @@ declare namespace Num {
1439
411
  * Num.is.integer(3.14); // false
1440
412
  * ```
1441
413
  */
1442
- const integer: (n: number) => boolean;
414
+ integer: (n: number) => boolean;
1443
415
  /**
1444
416
  * Returns `true` when the number is a finite float (fractional number).
1445
417
  *
@@ -1449,7 +421,7 @@ declare namespace Num {
1449
421
  * Num.is.float(5); // false
1450
422
  * ```
1451
423
  */
1452
- const float: (n: number) => boolean;
424
+ float: (n: number) => boolean;
1453
425
  /**
1454
426
  * Returns `true` when the number is finite (not `Infinity`, `-Infinity`, or `NaN`).
1455
427
  *
@@ -1459,7 +431,7 @@ declare namespace Num {
1459
431
  * Num.is.finite(Infinity); // false
1460
432
  * ```
1461
433
  */
1462
- const finite: (n: number) => boolean;
434
+ finite: (n: number) => boolean;
1463
435
  /**
1464
436
  * Returns `true` when the value is `NaN`.
1465
437
  *
@@ -1469,7 +441,7 @@ declare namespace Num {
1469
441
  * Num.is.nan(42); // false
1470
442
  * ```
1471
443
  */
1472
- const nan: (n: number) => boolean;
444
+ nan: (n: number) => boolean;
1473
445
  /**
1474
446
  * Returns `true` when the number is an even integer.
1475
447
  *
@@ -1480,7 +452,7 @@ declare namespace Num {
1480
452
  * Num.is.even(2.5); // false
1481
453
  * ```
1482
454
  */
1483
- const even: (n: number) => boolean;
455
+ even: (n: number) => boolean;
1484
456
  /**
1485
457
  * Returns `true` when the number is an odd integer.
1486
458
  *
@@ -1491,7 +463,7 @@ declare namespace Num {
1491
463
  * Num.is.odd(2.5); // false
1492
464
  * ```
1493
465
  */
1494
- const odd: (n: number) => boolean;
466
+ odd: (n: number) => boolean;
1495
467
  /**
1496
468
  * Returns `true` when the number is strictly greater than zero.
1497
469
  *
@@ -1502,7 +474,7 @@ declare namespace Num {
1502
474
  * Num.is.positive(-5); // false
1503
475
  * ```
1504
476
  */
1505
- const positive: (n: number) => boolean;
477
+ positive: (n: number) => boolean;
1506
478
  /**
1507
479
  * Returns `true` when the number is strictly less than zero.
1508
480
  *
@@ -1513,8 +485,8 @@ declare namespace Num {
1513
485
  * Num.is.negative(5); // false
1514
486
  * ```
1515
487
  */
1516
- const negative: (n: number) => boolean;
1517
- }
488
+ negative: (n: number) => boolean;
489
+ };
1518
490
  /**
1519
491
  * Generates an array of numbers from `from` to `to` (both inclusive),
1520
492
  * stepping by `step` (default `1`). If `step` is negative or zero, or `from > to`,
@@ -1530,7 +502,7 @@ declare namespace Num {
1530
502
  * Num.range(3, 3); // [3]
1531
503
  * ```
1532
504
  */
1533
- const range: (from: number, to: number, step?: number) => readonly number[];
505
+ range: (from: number, to: number, step?: number) => readonly number[];
1534
506
  /**
1535
507
  * Clamps a number between `min` and `max` (both inclusive).
1536
508
  *
@@ -1541,7 +513,7 @@ declare namespace Num {
1541
513
  * pipe(42, Num.clamp(0, 100)); // 42
1542
514
  * ```
1543
515
  */
1544
- const clamp: (min: number, max: number) => (n: number) => number;
516
+ clamp: (min: number, max: number) => (n: number) => number;
1545
517
  /**
1546
518
  * Returns `true` when the number is between `min` and `max` (both inclusive).
1547
519
  *
@@ -1552,7 +524,7 @@ declare namespace Num {
1552
524
  * pipe(10, Num.between(1, 10)); // true
1553
525
  * ```
1554
526
  */
1555
- const between: (min: number, max: number) => (n: number) => boolean;
527
+ between: (min: number, max: number) => (n: number) => boolean;
1556
528
  /**
1557
529
  * Returns `true` when the number is in the range `[start, end)` (inclusive of `start`, exclusive of `end`).
1558
530
  *
@@ -1563,7 +535,7 @@ declare namespace Num {
1563
535
  * pipe(10, Num.inRange(1, 10)); // false
1564
536
  * ```
1565
537
  */
1566
- const inRange: (start: number, end: number) => (n: number) => boolean;
538
+ inRange: (start: number, end: number) => (n: number) => boolean;
1567
539
  /**
1568
540
  * Parses a string as a number. Returns `None` when the result is `NaN`.
1569
541
  *
@@ -1575,7 +547,7 @@ declare namespace Num {
1575
547
  * Num.parse(""); // None
1576
548
  * ```
1577
549
  */
1578
- const parse: (s: string) => Maybe<number>;
550
+ parse: (s: string) => Maybe<number>;
1579
551
  /**
1580
552
  * Adds `b` to a number. Data-last: use in `pipe` or `Arr.map`.
1581
553
  *
@@ -1585,533 +557,260 @@ declare namespace Num {
1585
557
  * pipe([1, 2, 3], Arr.map(Num.add(10))); // [11, 12, 13]
1586
558
  * ```
1587
559
  */
1588
- const add: (b: number) => (a: number) => number;
560
+ add: (b: number) => (a: number) => number;
1589
561
  /**
1590
562
  * Subtracts `b` from a number. Data-last: `subtract(b)(a)` = `a - b`.
1591
563
  *
1592
564
  * @example
1593
565
  * ```ts
1594
566
  * pipe(10, Num.subtract(3)); // 7
1595
- * pipe([5, 10, 15], Arr.map(Num.subtract(2))); // [3, 8, 13]
1596
- * ```
1597
- */
1598
- const subtract: (b: number) => (a: number) => number;
1599
- /**
1600
- * Multiplies a number by `b`. Data-last: use in `pipe` or `Arr.map`.
1601
- *
1602
- * @example
1603
- * ```ts
1604
- * pipe(6, Num.multiply(7)); // 42
1605
- * pipe([1, 2, 3], Arr.map(Num.multiply(100))); // [100, 200, 300]
1606
- * ```
1607
- */
1608
- const multiply: (b: number) => (a: number) => number;
1609
- /**
1610
- * Divides a number by `b`. Returns `None` when `b` is zero. Data-last: `divide(b)(a)` = `a / b`.
1611
- *
1612
- * @example
1613
- * ```ts
1614
- * pipe(20, Num.divide(4)); // Some(5)
1615
- * pipe(5, Num.divide(0)); // None
1616
- * pipe([10, 20, 30], Arr.filterMap(Num.divide(10))); // [1, 2, 3]
1617
- * ```
1618
- */
1619
- const divide: (b: number) => (a: number) => Maybe<number>;
1620
- /**
1621
- * Returns the absolute value of a number.
1622
- *
1623
- * @example
1624
- * ```ts
1625
- * pipe(-5, Num.abs); // 5
1626
- * pipe(5, Num.abs); // 5
1627
- * ```
1628
- */
1629
- const abs: (n: number) => number;
1630
- /**
1631
- * Negates a number (arithmetic negation).
1632
- *
1633
- * @example
1634
- * ```ts
1635
- * pipe(5, Num.negate); // -5
1636
- * pipe(-5, Num.negate); // 5
1637
- * ```
1638
- */
1639
- const negate: (n: number) => number;
1640
- /**
1641
- * Rounds a number to the nearest integer.
1642
- *
1643
- * @example
1644
- * ```ts
1645
- * pipe(3.5, Num.round); // 4
1646
- * pipe(3.4, Num.round); // 3
1647
- * ```
1648
- */
1649
- const round: (n: number) => number;
1650
- /**
1651
- * Rounds a number down to the nearest integer.
1652
- *
1653
- * @example
1654
- * ```ts
1655
- * pipe(3.9, Num.floor); // 3
1656
- * pipe(-3.2, Num.floor); // -4
1657
- * ```
1658
- */
1659
- const floor: (n: number) => number;
1660
- /**
1661
- * Rounds a number up to the nearest integer.
1662
- *
1663
- * @example
1664
- * ```ts
1665
- * pipe(3.1, Num.ceil); // 4
1666
- * pipe(-3.9, Num.ceil); // -3
1667
- * ```
1668
- */
1669
- const ceil: (n: number) => number;
1670
- /**
1671
- * Returns the remainder of dividing a number by `divisor`. Returns `None` when `divisor` is zero.
1672
- * Data-last: `remainder(divisor)(a)` = `a % divisor`.
1673
- *
1674
- * @example
1675
- * ```ts
1676
- * pipe(10, Num.remainder(3)); // Some(1)
1677
- * pipe(5, Num.remainder(0)); // None
1678
- * pipe([10, 11, 12], Arr.filterMap(Num.remainder(3))); // [1, 2, 0]
1679
- * ```
1680
- */
1681
- const remainder: (divisor: number) => (n: number) => Maybe<number>;
1682
- /**
1683
- * Computes the sum of a list of numbers. Returns `0` if the list is empty.
1684
- *
1685
- * @example
1686
- * ```ts
1687
- * Num.sum([1, 2, 3]); // 6
1688
- * Num.sum([]); // 0
1689
- * ```
1690
- */
1691
- const sum: (ns: readonly number[]) => number;
1692
- /**
1693
- * Computes the mean of a list of numbers. Returns `None` if the list is empty.
1694
- *
1695
- * @example
1696
- * ```ts
1697
- * Num.mean([1, 2, 3]); // Some(2)
1698
- * Num.mean([]); // None
1699
- * ```
1700
- */
1701
- const mean: (ns: readonly number[]) => Maybe<number>;
1702
- /**
1703
- * Computes the minimum of a list of numbers. Returns `None` if the list is empty.
1704
- *
1705
- * @example
1706
- * ```ts
1707
- * Num.min([5, 1, 3]); // Some(1)
1708
- * Num.min([]); // None
1709
- * ```
1710
- */
1711
- const min: (ns: readonly number[]) => Maybe<number>;
1712
- /**
1713
- * Computes the maximum of a list of numbers. Returns `None` if the list is empty.
1714
- *
1715
- * @example
1716
- * ```ts
1717
- * Num.max([1, 5, 3]); // Some(5)
1718
- * Num.max([]); // None
1719
- * ```
1720
- */
1721
- const max: (ns: readonly number[]) => Maybe<number>;
1722
- /**
1723
- * Formats a number using `Intl.NumberFormat`. Returns `None` when `n` is `NaN` or non-finite.
1724
- * Data-last curried signature.
1725
- *
1726
- * @example
1727
- * ```ts
1728
- * const formatCurrency = Num.format({ style: "currency", currency: "USD" }, "en-US");
1729
- * pipe(1234.5, formatCurrency); // Some("$1,234.50")
1730
- * pipe(NaN, formatCurrency); // None
1731
- * ```
1732
- */
1733
- const format: (options?: Intl.NumberFormatOptions, locales?: string | string[]) => (n: number) => Maybe<string>;
1734
- }
1735
-
1736
- /**
1737
- * A branded type representing a record with at least one key-value pair.
1738
- */
1739
- type NonEmptyRecord<A, K extends string = string> = Brand<NonEmpty<"Rec">, Readonly<Record<K, A>>>;
1740
- declare namespace RecNonEmpty {
1741
- /**
1742
- * Creates a NonEmpty record from a single key-value pair.
1743
- *
1744
- * @example
1745
- * ```ts
1746
- * Rec.NonEmpty.singleton("a", 1); // { a: 1 }
1747
- * ```
1748
- */
1749
- const singleton: <K extends string, A>(key: K, value: A) => NonEmptyRecord<A, K>;
1750
- namespace from {
1751
- /**
1752
- * Creates a NonEmpty record from a standard record if it is not empty.
1753
- *
1754
- * @example
1755
- * ```ts
1756
- * Rec.NonEmpty.from.Record({ a: 1 }); // Some({ a: 1 })
1757
- * Rec.NonEmpty.from.Record({}); // None
1758
- * ```
1759
- */
1760
- const Record: <K extends string, A>(data: Readonly<Record<K, A>>) => Maybe<NonEmptyRecord<A, K>>;
1761
- }
1762
- /**
1763
- * Returns a non-empty array of keys for a NonEmpty record.
1764
- *
1765
- * @example
1766
- * ```ts
1767
- * Rec.NonEmpty.keys(Rec.NonEmpty.singleton("a", 1)); // ["a"]
1768
- * ```
1769
- */
1770
- const keys: <K extends string, A>(data: NonEmptyRecord<A, K>) => NonEmptyArr<K>;
1771
- /**
1772
- * Returns a non-empty array of values for a NonEmpty record.
1773
- *
1774
- * @example
1775
- * ```ts
1776
- * Rec.NonEmpty.values(Rec.NonEmpty.singleton("a", 1)); // [1]
1777
- * ```
1778
- */
1779
- const values: <K extends string, A>(data: NonEmptyRecord<A, K>) => NonEmptyArr<A>;
1780
- /**
1781
- * Returns a non-empty array of entry tuples for a NonEmpty record.
1782
- *
1783
- * @example
1784
- * ```ts
1785
- * Rec.NonEmpty.entries(Rec.NonEmpty.singleton("a", 1)); // [["a", 1]]
1786
- * ```
1787
- */
1788
- const entries: <K extends string, A>(data: NonEmptyRecord<A, K>) => NonEmptyArr<readonly [K, A]>;
1789
- /**
1790
- * Reduces a NonEmpty record's values from the left without an initial value.
1791
- *
1792
- * @example
1793
- * ```ts
1794
- * pipe(Rec.NonEmpty.singleton("a", 1), Rec.NonEmpty.reduce((a, b) => a + b)); // 1
1795
- * ```
1796
- */
1797
- const reduce: <A>(f: (acc: A, a: A) => A) => <K extends string>(data: NonEmptyRecord<A, K>) => A;
1798
- /**
1799
- * Transforms each value of a NonEmpty record.
1800
- *
1801
- * @example
1802
- * ```ts
1803
- * pipe(Rec.NonEmpty.singleton("a", 1), Rec.NonEmpty.map(n => n * 2)); // { a: 2 }
1804
- * ```
1805
- */
1806
- const map: <A, B>(f: (a: A) => B) => <K extends string>(data: NonEmptyRecord<A, K>) => NonEmptyRecord<B, K>;
1807
- /**
1808
- * Transforms each value of a NonEmpty record, also receiving the key.
1809
- *
1810
- * @example
1811
- * ```ts
1812
- * pipe(Rec.NonEmpty.singleton("a", 1), Rec.NonEmpty.mapWithKey((k, v) => `${k}:${v}`)); // { a: "a:1" }
1813
- * ```
1814
- */
1815
- const mapWithKey: <A, B>(f: (key: string, a: A) => B) => <K extends string>(data: NonEmptyRecord<A, K>) => NonEmptyRecord<B, K>;
1816
- }
1817
- /**
1818
- * Functional record/object utilities that compose well with pipe.
1819
- * All functions are data-last and curried where applicable.
1820
- *
1821
- * @example
1822
- * ```ts
1823
- * pipe(
1824
- * { a: 1, b: 2, c: 3 },
1825
- * Rec.filter(n => n > 1),
1826
- * Rec.map(n => n * 10)
1827
- * ); // { b: 20, c: 30 }
1828
- * ```
1829
- */
1830
- declare namespace Rec {
1831
- /**
1832
- * A branded type representing a record with at least one key-value pair.
1833
- */
1834
- type NonEmpty<A, K extends string = string> = NonEmptyRecord<A, K>;
1835
- namespace is {
1836
- /**
1837
- * Returns true if the record has no keys.
1838
- *
1839
- * @example
1840
- * ```ts
1841
- * Rec.is.empty({}); // true
1842
- * Rec.is.empty({ a: 1 }); // false
1843
- * ```
1844
- */
1845
- const empty: <A>(data: Readonly<Record<string, A>>) => boolean;
1846
- /**
1847
- * Type guard to check if a record is non-empty.
1848
- *
1849
- * @example
1850
- * ```ts
1851
- * Rec.is.nonEmpty({ a: 1 }); // true
1852
- * Rec.is.nonEmpty({}); // false
1853
- * ```
1854
- */
1855
- const nonEmpty: <A, K extends string>(data: Readonly<Record<K, A>>) => data is NonEmptyRecord<A, K>;
1856
- }
1857
- /**
1858
- * Transforms each value in a record.
1859
- *
1860
- * @example
1861
- * ```ts
1862
- * pipe({ a: 1, b: 2 }, Rec.map(n => n * 2)); // { a: 2, b: 4 }
1863
- * ```
1864
- */
1865
- const map: <A, B>(f: (a: A) => B) => <K extends string>(data: Readonly<Record<K, A>>) => Readonly<Record<K, B>>;
1866
- /**
1867
- * Maps each value in a record with a function returning a `Maybe`, keeping only `Some` values.
1868
- *
1869
- * @example
1870
- * ```ts
1871
- * pipe(
1872
- * { a: 1, b: 2, c: 3 },
1873
- * Rec.filterMap((n) => (n % 2 === 0 ? Maybe.make.some(n * 10) : Maybe.make.none()))
1874
- * ); // { b: 20 }
1875
- * ```
1876
- */
1877
- const filterMap: <A, B>(f: (a: A) => Maybe<B>) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, B>>;
1878
- /**
1879
- * Transforms each value in a record, also receiving the key.
1880
- *
1881
- * @example
1882
- * ```ts
1883
- * pipe({ a: 1, b: 2 }, Rec.mapWithKey((k, v) => `${k}:${v}`));
1884
- * // { a: "a:1", b: "b:2" }
1885
- * ```
1886
- */
1887
- const mapWithKey: <A, B>(f: (key: string, a: A) => B) => <K extends string>(data: Readonly<Record<K, A>>) => Readonly<Record<K, B>>;
1888
- /**
1889
- * Filters values in a record by a predicate.
1890
- *
1891
- * @example
1892
- * ```ts
1893
- * pipe({ a: 1, b: 2, c: 3 }, Rec.filter(n => n > 1)); // { b: 2, c: 3 }
1894
- * ```
1895
- */
1896
- const filter: <A>(predicate: (a: A) => boolean) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
1897
- /**
1898
- * Filters values in a record by a predicate that also receives the key.
1899
- *
1900
- * @example
1901
- * ```ts
1902
- * pipe({ a: 1, b: 2, c: 3 }, Rec.filterWithKey((k, v) => k !== "a" && v > 0));
1903
- * // { b: 2 }
1904
- * ```
1905
- */
1906
- const filterWithKey: <A>(predicate: (key: string, a: A) => boolean) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
1907
- /**
1908
- * Looks up a value by key, returning Maybe.
1909
- *
1910
- * @example
1911
- * ```ts
1912
- * pipe({ a: 1, b: 2 }, Rec.lookup("a")); // Some(1)
1913
- * pipe({ a: 1, b: 2 }, Rec.lookup("c")); // None
567
+ * pipe([5, 10, 15], Arr.map(Num.subtract(2))); // [3, 8, 13]
1914
568
  * ```
1915
569
  */
1916
- const lookup: <K extends string>(key: K) => <V>(data: Record<string, V>) => Maybe<V>;
570
+ subtract: (b: number) => (a: number) => number;
1917
571
  /**
1918
- * Returns all keys of a record.
572
+ * Multiplies a number by `b`. Data-last: use in `pipe` or `Arr.map`.
1919
573
  *
1920
574
  * @example
1921
575
  * ```ts
1922
- * Rec.keys({ a: 1, b: 2 }); // ["a", "b"]
576
+ * pipe(6, Num.multiply(7)); // 42
577
+ * pipe([1, 2, 3], Arr.map(Num.multiply(100))); // [100, 200, 300]
1923
578
  * ```
1924
579
  */
1925
- const keys: <T extends Record<string, unknown>>(data: T) => readonly (keyof T & string)[];
580
+ multiply: (b: number) => (a: number) => number;
1926
581
  /**
1927
- * Returns all values of a record.
582
+ * Divides a number by `b`. Returns `None` when `b` is zero. Data-last: `divide(b)(a)` = `a / b`.
1928
583
  *
1929
584
  * @example
1930
585
  * ```ts
1931
- * Rec.values({ a: 1, b: 2 }); // [1, 2]
586
+ * pipe(20, Num.divide(4)); // Some(5)
587
+ * pipe(5, Num.divide(0)); // None
588
+ * pipe([10, 20, 30], Arr.filterMap(Num.divide(10))); // [1, 2, 3]
1932
589
  * ```
1933
590
  */
1934
- const values: <T extends Record<string, unknown>>(data: T) => readonly T[keyof T & string][];
591
+ divide: (b: number) => (a: number) => Maybe<number>;
1935
592
  /**
1936
- * Returns all key-value pairs of a record.
593
+ * Returns the absolute value of a number.
1937
594
  *
1938
595
  * @example
1939
596
  * ```ts
1940
- * Rec.entries({ a: 1, b: 2 }); // [["a", 1], ["b", 2]]
597
+ * pipe(-5, Num.abs); // 5
598
+ * pipe(5, Num.abs); // 5
1941
599
  * ```
1942
600
  */
1943
- const entries: <T extends Record<string, unknown>>(data: T) => readonly (readonly [keyof T, T[keyof T]])[];
1944
- namespace from {
1945
- /**
1946
- * Creates a record from key-value pairs.
1947
- *
1948
- * @example
1949
- * ```ts
1950
- * Rec.from.entries([["a", 1], ["b", 2]]); // { a: 1, b: 2 }
1951
- * ```
1952
- */
1953
- const entries: <A>(data: readonly (readonly [string, A])[]) => Readonly<Record<string, A>>;
1954
- }
601
+ abs: (n: number) => number;
1955
602
  /**
1956
- * Groups elements of an array into a record keyed by the result of `keyFn`. Each key maps to
1957
- * the array of elements that produced it, in insertion order.
1958
- *
1959
- * Unlike `Dict.groupBy`, keys are always strings. Use `Dict.groupBy` when you need non-string
1960
- * keys or want to avoid the plain-object prototype chain.
603
+ * Negates a number (arithmetic negation).
1961
604
  *
1962
605
  * @example
1963
606
  * ```ts
1964
- * pipe(
1965
- * ["apple", "avocado", "banana", "blueberry"],
1966
- * Rec.groupBy(s => s[0]),
1967
- * ); // { a: ["apple", "avocado"], b: ["banana", "blueberry"] }
607
+ * pipe(5, Num.negate); // -5
608
+ * pipe(-5, Num.negate); // 5
1968
609
  * ```
1969
610
  */
1970
- const groupBy: <A>(keyFn: (a: A) => string) => (items: readonly A[]) => Readonly<Record<string, readonly A[]>>;
611
+ negate: (n: number) => number;
1971
612
  /**
1972
- * Picks specific keys from a record.
613
+ * Rounds a number to the nearest integer.
1973
614
  *
1974
615
  * @example
1975
616
  * ```ts
1976
- * pipe({ a: 1, b: 2, c: 3 }, Rec.pick("a", "c")); // { a: 1, c: 3 }
617
+ * pipe(3.5, Num.round); // 4
618
+ * pipe(3.4, Num.round); // 3
1977
619
  * ```
1978
620
  */
1979
- const pick: <K extends string>(...pickedKeys: K[]) => <A extends Record<K, unknown>>(data: A) => Pick<A, K>;
621
+ round: (n: number) => number;
1980
622
  /**
1981
- * Omits specific keys from a record.
623
+ * Rounds a number down to the nearest integer.
1982
624
  *
1983
625
  * @example
1984
626
  * ```ts
1985
- * pipe({ a: 1, b: 2, c: 3 }, Rec.omit("b")); // { a: 1, c: 3 }
627
+ * pipe(3.9, Num.floor); // 3
628
+ * pipe(-3.2, Num.floor); // -4
1986
629
  * ```
1987
630
  */
1988
- const omit: <K extends string>(...omittedKeys: K[]) => <A extends Record<K, unknown>>(data: A) => Omit<A, K>;
631
+ floor: (n: number) => number;
1989
632
  /**
1990
- * Merges two records. Values from the second record take precedence.
633
+ * Rounds a number up to the nearest integer.
1991
634
  *
1992
635
  * @example
1993
636
  * ```ts
1994
- * pipe({ a: 1, b: 2 }, Rec.merge({ b: 3, c: 4 })); // { a: 1, b: 3, c: 4 }
637
+ * pipe(3.1, Num.ceil); // 4
638
+ * pipe(-3.9, Num.ceil); // -3
1995
639
  * ```
1996
640
  */
1997
- const merge: <A>(other: Readonly<Record<string, A>>) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
641
+ ceil: (n: number) => number;
1998
642
  /**
1999
- * Merges two records using a custom combination function on key collisions.
2000
- * Supports both uncurried `Rec.mergeWith(combine)(first, second)` and curried `pipe(first, Rec.mergeWith(combine)(second))`.
643
+ * Returns the remainder of dividing a number by `divisor`. Returns `None` when `divisor` is zero.
644
+ * Data-last: `remainder(divisor)(a)` = `a % divisor`.
2001
645
  *
2002
646
  * @example
2003
647
  * ```ts
2004
- * const combineStats = Rec.mergeWith((a: number, b: number) => a + b);
2005
- * combineStats({ a: 1, b: 2 }, { b: 3, c: 4 }); // { a: 1, b: 5, c: 4 }
2006
- * pipe({ a: 1, b: 2 }, combineStats({ b: 3, c: 4 })); // { a: 1, b: 5, c: 4 }
648
+ * pipe(10, Num.remainder(3)); // Some(1)
649
+ * pipe(5, Num.remainder(0)); // None
650
+ * pipe([10, 11, 12], Arr.filterMap(Num.remainder(3))); // [1, 2, 0]
2007
651
  * ```
2008
652
  */
2009
- function mergeWith<A>(combine: (a: A, b: A) => A): {
2010
- (second: Readonly<Record<string, A>>): (first: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
2011
- (first: Readonly<Record<string, A>>, second: Readonly<Record<string, A>>): Readonly<Record<string, A>>;
2012
- };
653
+ remainder: (divisor: number) => (n: number) => Maybe<number>;
2013
654
  /**
2014
- * Returns the number of keys in a record.
655
+ * Computes the sum of a list of numbers. Returns `0` if the list is empty.
2015
656
  *
2016
657
  * @example
2017
658
  * ```ts
2018
- * Rec.size({ a: 1, b: 2 }); // 2
659
+ * Num.sum([1, 2, 3]); // 6
660
+ * Num.sum([]); // 0
2019
661
  * ```
2020
662
  */
2021
- const size: <A>(data: Readonly<Record<string, A>>) => number;
663
+ sum: (ns: readonly number[]) => number;
2022
664
  /**
2023
- * Transforms each key while preserving values.
2024
- * If two keys map to the same new key, the last one wins.
665
+ * Computes the mean of a list of numbers. Returns `None` if the list is empty.
2025
666
  *
2026
667
  * @example
2027
668
  * ```ts
2028
- * pipe({ firstName: "Alice", lastName: "Smith" }, Rec.mapKeys(k => k.toUpperCase()));
2029
- * // { FIRSTNAME: "Alice", LASTNAME: "Smith" }
669
+ * Num.mean([1, 2, 3]); // Some(2)
670
+ * Num.mean([]); // None
2030
671
  * ```
2031
672
  */
2032
- const mapKeys: (f: (key: string) => string) => <A>(data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
673
+ mean: (ns: readonly number[]) => Maybe<number>;
2033
674
  /**
2034
- * Removes all `None` values from a `Record<string, Maybe<A>>`, returning a plain `Record<string, A>`.
2035
- * Useful when building records from fallible lookups.
675
+ * Computes the minimum of a list of numbers. Returns `None` if the list is empty.
2036
676
  *
2037
677
  * @example
2038
678
  * ```ts
2039
- * Rec.compact({ a: Maybe.make.some(1), b: Maybe.make.none(), c: Maybe.make.some(3) });
2040
- * // { a: 1, c: 3 }
679
+ * Num.min([5, 1, 3]); // Some(1)
680
+ * Num.min([]); // None
2041
681
  * ```
2042
682
  */
2043
- const compact: <A>(data: Readonly<Record<string, Maybe<A>>>) => Readonly<Record<string, A>>;
683
+ min: (ns: readonly number[]) => Maybe<number>;
2044
684
  /**
2045
- * Transforms key and value pairs simultaneously.
685
+ * Computes the maximum of a list of numbers. Returns `None` if the list is empty.
2046
686
  *
2047
687
  * @example
2048
688
  * ```ts
2049
- * pipe(
2050
- * { a: 1, b: 2 },
2051
- * Rec.mapEntries((k, v) => [k.toUpperCase(), v * 10])
2052
- * ); // { A: 10, B: 20 }
689
+ * Num.max([1, 5, 3]); // Some(5)
690
+ * Num.max([]); // None
2053
691
  * ```
2054
692
  */
2055
- const mapEntries: <A, K2 extends string, B>(f: (key: string, value: A) => readonly [K2, B]) => (data: Readonly<Record<string, A>>) => Readonly<Record<K2, B>>;
693
+ max: (ns: readonly number[]) => Maybe<number>;
2056
694
  /**
2057
- * Immutably updates a value at a deep nested path inside a record.
695
+ * Formats a number using `Intl.NumberFormat`. Returns `None` when `n` is `NaN` or non-finite.
696
+ * Data-last curried signature.
2058
697
  *
2059
698
  * @example
2060
699
  * ```ts
2061
- * pipe(
2062
- * { user: { profile: { age: 30 } } },
2063
- * Rec.updateIn(["user", "profile", "age"], (n: number) => n + 1)
2064
- * ); // { user: { profile: { age: 31 } } }
700
+ * const formatCurrency = Num.format({ style: "currency", currency: "USD" }, "en-US");
701
+ * pipe(1234.5, formatCurrency); // Some("$1,234.50")
702
+ * pipe(NaN, formatCurrency); // None
2065
703
  * ```
2066
704
  */
2067
- const updateIn: <T>(path: readonly [string, ...string[]], f: (val: T) => T) => (data: Readonly<Record<string, unknown>>) => Readonly<Record<string, unknown>>;
2068
- namespace traverse {
2069
- const Maybe: <A, B>(f: (a: A) => Maybe<B>) => (data: Readonly<Record<string, A>>) => Maybe<Readonly<Record<string, B>>>;
2070
- const Result: <E, A, B>(f: (a: A) => Result<E, B>) => (data: Readonly<Record<string, A>>) => Result<E, Readonly<Record<string, B>>>;
2071
- }
2072
- namespace sequence {
2073
- const Maybe: <A>(data: Readonly<Record<string, Maybe<A>>>) => Maybe<Readonly<Record<string, A>>>;
2074
- const Result: <E, A>(data: Readonly<Record<string, Result<E, A>>>) => Result<E, Readonly<Record<string, A>>>;
2075
- }
2076
- const NonEmpty: typeof RecNonEmpty;
2077
- }
705
+ format: (options?: Intl.NumberFormatOptions, locales?: string | string[]) => (n: number) => Maybe<string>;
706
+ };
2078
707
 
2079
708
  /**
2080
- * A branded type representing a string with at least one character.
709
+ * A branded type representing a record with at least one key-value pair.
2081
710
  */
2082
- type NonEmptyString = Brand<NonEmpty<"Str">, string>;
711
+ type NonEmptyRecord<A, K extends string = string> = Brand<NonEmpty<"Rec">, Readonly<Record<K, A>>>;
2083
712
  /**
2084
- * String utilities. All transformation functions are data-last and curried so they
2085
- * compose naturally with `pipe`. Safe parsers return `Maybe` instead of `NaN`.
713
+ * Merges two records using a custom combination function on key collisions.
714
+ * Supports both uncurried `Rec.mergeWith(combine)(first, second)` and curried `pipe(first, Rec.mergeWith(combine)(second))`.
2086
715
  *
2087
716
  * @example
2088
717
  * ```ts
2089
- * import { Str } from "@nlozgachev/pipelined/data";
2090
- * import { pipe } from "@nlozgachev/pipelined/composition";
2091
- *
2092
- * pipe(" Hello, World! ", Str.trim, Str.toLowerCase); // "hello, world!"
718
+ * const combineStats = Rec.mergeWith((a: number, b: number) => a + b);
719
+ * combineStats({ a: 1, b: 2 }, { b: 3, c: 4 }); // { a: 1, b: 5, c: 4 }
720
+ * pipe({ a: 1, b: 2 }, combineStats({ b: 3, c: 4 })); // { a: 1, b: 5, c: 4 }
2093
721
  * ```
2094
722
  */
2095
- declare namespace StrNonEmpty {
2096
- namespace from {
723
+ declare function mergeWith<A>(combine: (a: A, b: A) => A): {
724
+ (second: Readonly<Record<string, A>>): (first: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
725
+ (first: Readonly<Record<string, A>>, second: Readonly<Record<string, A>>): Readonly<Record<string, A>>;
726
+ };
727
+ declare const Rec: {
728
+ is: {
729
+ /**
730
+ * Returns true if the record has no keys.
731
+ *
732
+ * @example
733
+ * ```ts
734
+ * Rec.is.empty({}); // true
735
+ * Rec.is.empty({ a: 1 }); // false
736
+ * ```
737
+ */
738
+ empty: <A>(data: Readonly<Record<string, A>>) => boolean;
739
+ /**
740
+ * Type guard to check if a record is non-empty.
741
+ *
742
+ * @example
743
+ * ```ts
744
+ * Rec.is.nonEmpty({ a: 1 }); // true
745
+ * Rec.is.nonEmpty({}); // false
746
+ * ```
747
+ */
748
+ nonEmpty: <A, K extends string>(data: Readonly<Record<K, A>>) => data is NonEmptyRecord<A, K>;
749
+ };
750
+ from: {
2097
751
  /**
2098
- * Returns Some containing NonEmptyString if the string is not empty, None otherwise.
752
+ * Creates a record from key-value pairs.
2099
753
  *
2100
754
  * @example
2101
755
  * ```ts
2102
- * Str.NonEmpty.from.String("hello"); // Some("hello")
2103
- * Str.NonEmpty.from.String(""); // None
756
+ * Rec.from.entries([["a", 1], ["b", 2]]); // { a: 1, b: 2 }
2104
757
  * ```
2105
758
  */
2106
- const String: (s: string) => Maybe<NonEmptyString>;
2107
- }
759
+ entries: <A>(data: readonly (readonly [string, A])[]) => Readonly<Record<string, A>>;
760
+ };
761
+ to: {
762
+ Dict: <A, K extends string = string>(data: Readonly<Record<K, A>>) => ReadonlyMap<K, A>;
763
+ };
764
+ map: <A, B>(f: (a: A) => B) => <K extends string>(data: Readonly<Record<K, A>>) => Readonly<Record<K, B>>;
765
+ filterMap: <A, B>(f: (a: A) => Maybe<B>) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, B>>;
766
+ mapWithKey: <A, B>(f: (key: string, a: A) => B) => <K extends string>(data: Readonly<Record<K, A>>) => Readonly<Record<K, B>>;
767
+ filter: <A>(predicate: (a: A) => boolean) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
768
+ filterWithKey: <A>(predicate: (key: string, a: A) => boolean) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
769
+ lookup: <K extends string>(key: K) => <V>(data: Record<string, V>) => Maybe<V>;
770
+ keys: <T extends Record<string, unknown>>(data: T) => readonly (keyof T & string)[];
771
+ values: <T extends Record<string, unknown>>(data: T) => readonly T[keyof T & string][];
772
+ entries: <T extends Record<string, unknown>>(data: T) => readonly (readonly [keyof T, T[keyof T]])[];
773
+ groupBy: <A>(keyFn: (a: A) => string) => (items: readonly A[]) => Readonly<Record<string, readonly A[]>>;
774
+ pick: <K extends string>(...pickedKeys: K[]) => <A extends Record<K, unknown>>(data: A) => Pick<A, K>;
775
+ omit: <K extends string>(...omittedKeys: K[]) => <A extends Record<K, unknown>>(data: A) => Omit<A, K>;
776
+ merge: <A>(other: Readonly<Record<string, A>>) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
777
+ mergeWith: typeof mergeWith;
778
+ size: <A>(data: Readonly<Record<string, A>>) => number;
779
+ mapKeys: (f: (key: string) => string) => <A>(data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
780
+ compact: <A>(data: Readonly<Record<string, Maybe<A>>>) => Readonly<Record<string, A>>;
781
+ mapEntries: <A, K2 extends string, B>(f: (key: string, value: A) => readonly [K2, B]) => (data: Readonly<Record<string, A>>) => Readonly<Record<K2, B>>;
782
+ updateIn: <T>(path: readonly [string, ...string[]], f: (val: T) => T) => (data: Readonly<Record<string, unknown>>) => Readonly<Record<string, unknown>>;
783
+ traverse: {
784
+ Maybe: <A, B>(f: (a: A) => Maybe<B>) => (data: Readonly<Record<string, A>>) => Maybe<Readonly<Record<string, B>>>;
785
+ Result: <E, A, B>(f: (a: A) => Result<E, B>) => (data: Readonly<Record<string, A>>) => Result<E, Readonly<Record<string, B>>>;
786
+ };
787
+ sequence: {
788
+ Maybe: <A>(data: Readonly<Record<string, Maybe<A>>>) => Maybe<Readonly<Record<string, A>>>;
789
+ Result: <E, A>(data: Readonly<Record<string, Result<E, A>>>) => Result<E, Readonly<Record<string, A>>>;
790
+ };
791
+ NonEmpty: {
792
+ singleton: <K extends string, A>(key: K, value: A) => NonEmptyRecord<A, K>;
793
+ from: {
794
+ Record: <K extends string, A>(data: Readonly<Record<K, A>>) => Maybe<NonEmptyRecord<A, K>>;
795
+ };
796
+ keys: <K extends string, A>(data: NonEmptyRecord<A, K>) => NonEmptyArr<K>;
797
+ values: <K extends string, A>(data: NonEmptyRecord<A, K>) => NonEmptyArr<A>;
798
+ entries: <K extends string, A>(data: NonEmptyRecord<A, K>) => NonEmptyArr<readonly [K, A]>;
799
+ reduce: <A>(f: (acc: A, a: A) => A) => <K extends string>(data: NonEmptyRecord<A, K>) => A;
800
+ map: <A, B>(f: (a: A) => B) => <K extends string>(data: NonEmptyRecord<A, K>) => NonEmptyRecord<B, K>;
801
+ mapWithKey: <A, B>(f: (key: string, a: A) => B) => <K extends string>(data: NonEmptyRecord<A, K>) => NonEmptyRecord<B, K>;
802
+ };
803
+ };
804
+ declare namespace Rec {
805
+ type NonEmpty<A, K extends string = string> = NonEmptyRecord<A, K>;
2108
806
  }
2109
- declare namespace Str {
2110
- /**
2111
- * A branded type representing a string with at least one character.
2112
- */
2113
- type NonEmpty = NonEmptyString;
2114
- namespace is {
807
+
808
+ /**
809
+ * A branded type representing a string with at least one character.
810
+ */
811
+ type NonEmptyString = Brand<NonEmpty<"Str">, string>;
812
+ declare const Str: {
813
+ is: {
2115
814
  /**
2116
815
  * Returns `true` when the string is empty.
2117
816
  *
@@ -2121,12 +820,12 @@ declare namespace Str {
2121
820
  * pipe("hi", Str.is.empty); // false
2122
821
  * ```
2123
822
  */
2124
- const empty: (s: string) => boolean;
823
+ empty: (s: string) => boolean;
2125
824
  /**
2126
825
  * Type guard to check if a string is non-empty.
2127
826
  */
2128
- const nonEmpty: (s: string) => s is NonEmpty;
2129
- }
827
+ nonEmpty: (s: string) => s is NonEmptyString;
828
+ };
2130
829
  /**
2131
830
  * Splits a string by a separator. Data-last: use in `pipe`.
2132
831
  *
@@ -2135,7 +834,7 @@ declare namespace Str {
2135
834
  * pipe("a,b,c", Str.split(",")); // ["a", "b", "c"]
2136
835
  * ```
2137
836
  */
2138
- const split: (separator: string | RegExp) => (s: string) => readonly string[];
837
+ split: (separator: string | RegExp) => (s: string) => readonly string[];
2139
838
  /**
2140
839
  * Removes leading and trailing whitespace from a string.
2141
840
  *
@@ -2144,7 +843,7 @@ declare namespace Str {
2144
843
  * pipe(" hello ", Str.trim); // "hello"
2145
844
  * ```
2146
845
  */
2147
- const trim: (s: string) => string;
846
+ trim: (s: string) => string;
2148
847
  /**
2149
848
  * Returns `true` when the string contains the given substring.
2150
849
  *
@@ -2154,7 +853,7 @@ declare namespace Str {
2154
853
  * pipe("hello world", Str.includes("xyz")); // false
2155
854
  * ```
2156
855
  */
2157
- const includes: (substring: string) => (s: string) => boolean;
856
+ includes: (substring: string) => (s: string) => boolean;
2158
857
  /**
2159
858
  * Replaces the first occurrence of a pattern in a string. Data-last: use in `pipe`.
2160
859
  *
@@ -2164,7 +863,7 @@ declare namespace Str {
2164
863
  * pipe("Hello World", Str.replace(/world/i, "Earth")); // "Hello Earth"
2165
864
  * ```
2166
865
  */
2167
- const replace: (pattern: string | RegExp, replacement: string) => (s: string) => string;
866
+ replace: (pattern: string | RegExp, replacement: string) => (s: string) => string;
2168
867
  /**
2169
868
  * Replaces all occurrences of a pattern in a string. Data-last: use in `pipe`.
2170
869
  *
@@ -2174,7 +873,7 @@ declare namespace Str {
2174
873
  * pipe("aAbBaA", Str.replaceAll(/a/gi, "x")); // "xxBBxx"
2175
874
  * ```
2176
875
  */
2177
- const replaceAll: (pattern: string | RegExp, replacement: string) => (s: string) => string;
876
+ replaceAll: (pattern: string | RegExp, replacement: string) => (s: string) => string;
2178
877
  /**
2179
878
  * Returns `true` when the string starts with the given prefix.
2180
879
  *
@@ -2184,7 +883,7 @@ declare namespace Str {
2184
883
  * pipe("hello world", Str.startsWith("world")); // false
2185
884
  * ```
2186
885
  */
2187
- const startsWith: (prefix: string) => (s: string) => boolean;
886
+ startsWith: (prefix: string) => (s: string) => boolean;
2188
887
  /**
2189
888
  * Returns `true` when the string ends with the given suffix.
2190
889
  *
@@ -2194,7 +893,7 @@ declare namespace Str {
2194
893
  * pipe("hello world", Str.endsWith("hello")); // false
2195
894
  * ```
2196
895
  */
2197
- const endsWith: (suffix: string) => (s: string) => boolean;
896
+ endsWith: (suffix: string) => (s: string) => boolean;
2198
897
  /**
2199
898
  * Converts a string to uppercase.
2200
899
  *
@@ -2203,7 +902,7 @@ declare namespace Str {
2203
902
  * pipe("hello", Str.toUpperCase); // "HELLO"
2204
903
  * ```
2205
904
  */
2206
- const toUpperCase: (s: string) => string;
905
+ toUpperCase: (s: string) => string;
2207
906
  /**
2208
907
  * Converts a string to lowercase.
2209
908
  *
@@ -2212,7 +911,7 @@ declare namespace Str {
2212
911
  * pipe("HELLO", Str.toLowerCase); // "hello"
2213
912
  * ```
2214
913
  */
2215
- const toLowerCase: (s: string) => string;
914
+ toLowerCase: (s: string) => string;
2216
915
  /**
2217
916
  * Converts the first character of a string to uppercase.
2218
917
  *
@@ -2221,7 +920,7 @@ declare namespace Str {
2221
920
  * pipe("hello", Str.capitalize); // "Hello"
2222
921
  * ```
2223
922
  */
2224
- const capitalize: (s: string) => string;
923
+ capitalize: (s: string) => string;
2225
924
  /**
2226
925
  * Splits a string into lines, normalising `\r\n` and `\r` line endings.
2227
926
  *
@@ -2231,7 +930,7 @@ declare namespace Str {
2231
930
  * Str.lines("a\r\nb"); // ["a", "b"]
2232
931
  * ```
2233
932
  */
2234
- const lines: (s: string) => readonly string[];
933
+ lines: (s: string) => readonly string[];
2235
934
  /**
2236
935
  * Splits a string into words on any whitespace boundary, filtering out empty strings.
2237
936
  *
@@ -2240,7 +939,7 @@ declare namespace Str {
2240
939
  * Str.words(" hello world "); // ["hello", "world"]
2241
940
  * ```
2242
941
  */
2243
- const words: (s: string) => readonly string[];
942
+ words: (s: string) => readonly string[];
2244
943
  /**
2245
944
  * Returns `true` when the string is empty or contains only whitespace.
2246
945
  *
@@ -2250,7 +949,7 @@ declare namespace Str {
2250
949
  * pipe("hi", Str.isBlank); // false
2251
950
  * ```
2252
951
  */
2253
- const isBlank: (s: string) => boolean;
952
+ isBlank: (s: string) => boolean;
2254
953
  /**
2255
954
  * Returns the length of the string.
2256
955
  *
@@ -2260,7 +959,7 @@ declare namespace Str {
2260
959
  * pipe("", Str.length); // 0
2261
960
  * ```
2262
961
  */
2263
- const length: (s: string) => number;
962
+ length: (s: string) => number;
2264
963
  /**
2265
964
  * Extracts a substring between two indices. Data-last: use in `pipe`.
2266
965
  *
@@ -2270,7 +969,7 @@ declare namespace Str {
2270
969
  * pipe("hello", Str.slice(2)); // "llo"
2271
970
  * ```
2272
971
  */
2273
- const slice: (start: number, end?: number) => (s: string) => string;
972
+ slice: (start: number, end?: number) => (s: string) => string;
2274
973
  /**
2275
974
  * Pads the start of a string to a specified length. Data-last: use in `pipe`.
2276
975
  *
@@ -2280,7 +979,7 @@ declare namespace Str {
2280
979
  * pipe("hi", Str.padStart(5)); // " hi"
2281
980
  * ```
2282
981
  */
2283
- const padStart: (maxLength: number, fillString?: string) => (s: string) => string;
982
+ padStart: (maxLength: number, fillString?: string) => (s: string) => string;
2284
983
  /**
2285
984
  * Pads the end of a string to a specified length. Data-last: use in `pipe`.
2286
985
  *
@@ -2290,11 +989,11 @@ declare namespace Str {
2290
989
  * pipe("hi", Str.padEnd(5)); // "hi "
2291
990
  * ```
2292
991
  */
2293
- const padEnd: (maxLength: number, fillString?: string) => (s: string) => string;
992
+ padEnd: (maxLength: number, fillString?: string) => (s: string) => string;
2294
993
  /**
2295
994
  * Safe number parsers that return `Maybe` instead of `NaN`.
2296
995
  */
2297
- const parse: {
996
+ parse: {
2298
997
  /**
2299
998
  * Parses a string as an integer (base 10). Returns `None` if the result is `NaN`.
2300
999
  *
@@ -2327,7 +1026,7 @@ declare namespace Str {
2327
1026
  * Str.parseJson('invalid'); // Err(SyntaxError)
2328
1027
  * ```
2329
1028
  */
2330
- const parseJson: (s: string) => Result<SyntaxError, unknown>;
1029
+ parseJson: (s: string) => Result<SyntaxError, unknown>;
2331
1030
  /**
2332
1031
  * Converts the first character of a string to lower case.
2333
1032
  *
@@ -2337,7 +1036,7 @@ declare namespace Str {
2337
1036
  * Str.uncapitalize(""); // ""
2338
1037
  * ```
2339
1038
  */
2340
- const uncapitalize: (s: string) => string;
1039
+ uncapitalize: (s: string) => string;
2341
1040
  /**
2342
1041
  * Truncates a string to a maximum length, appending an optional suffix (default `"..."`).
2343
1042
  * Data-last curried signature.
@@ -2349,267 +1048,80 @@ declare namespace Str {
2349
1048
  * pipe("Hello, world!", Str.truncate({ length: 8, suffix: "…" })); // "Hello, w…"
2350
1049
  * ```
2351
1050
  */
2352
- const truncate: (options: {
1051
+ truncate: (options: {
2353
1052
  length: number;
2354
1053
  suffix?: string;
2355
1054
  }) => (s: string) => string;
2356
- const NonEmpty: typeof StrNonEmpty;
1055
+ NonEmpty: {
1056
+ from: {
1057
+ /**
1058
+ * Returns Some containing NonEmptyString if the string is not empty, None otherwise.
1059
+ *
1060
+ * @example
1061
+ * ```ts
1062
+ * Str.NonEmpty.from.String("hello"); // Some("hello")
1063
+ * Str.NonEmpty.from.String(""); // None
1064
+ * ```
1065
+ */
1066
+ String: (s: string) => Maybe<NonEmptyString>;
1067
+ };
1068
+ };
1069
+ };
1070
+ declare namespace Str {
1071
+ /**
1072
+ * A branded type representing a string with at least one character.
1073
+ */
1074
+ type NonEmpty = NonEmptyString;
2357
1075
  }
2358
1076
 
2359
1077
  /**
2360
1078
  * A branded type representing a unique collection with at least one element.
2361
1079
  */
2362
1080
  type NonEmptySet<A> = Brand<NonEmpty<"Uniq">, ReadonlySet<A>>;
2363
- /**
2364
- * Functional utilities for unique-value collections (`ReadonlySet<A>`). All functions are pure
2365
- * and data-last — they compose naturally with `pipe`.
2366
- *
2367
- * Every "mutating" operation returns a new set; the original is never changed.
2368
- *
2369
- * @example
2370
- * ```ts
2371
- * import { Uniq } from "@nlozgachev/pipelined/data";
2372
- * import { pipe } from "@nlozgachev/pipelined/composition";
2373
- *
2374
- * const active = pipe(
2375
- * Uniq.from.Array(["alice", "bob", "alice", "carol"]),
2376
- * Uniq.remove("bob"),
2377
- * Uniq.map(name => name.toUpperCase()),
2378
- * );
2379
- * // ReadonlySet { "ALICE", "CAROL" }
2380
- * ```
2381
- */
2382
- declare namespace UniqNonEmpty {
2383
- /**
2384
- * Creates a single-element unique collection.
2385
- *
2386
- * @example
2387
- * ```ts
2388
- * Uniq.NonEmpty.singleton(42); // ReadonlySet { 42 }
2389
- * ```
2390
- */
2391
- const singleton: <A>(item: A) => NonEmptySet<A>;
2392
- namespace from {
2393
- /**
2394
- * Returns Some containing NonEmptySet if the set is not empty, None otherwise.
2395
- *
2396
- * @example
2397
- * ```ts
2398
- * Uniq.NonEmpty.from.Set(Uniq.from.Array([1, 2])); // Some(ReadonlySet { 1, 2 })
2399
- * Uniq.NonEmpty.from.Set(Uniq.empty()); // None
2400
- * ```
2401
- */
2402
- const Set: <A>(s: ReadonlySet<A>) => Maybe<NonEmptySet<A>>;
2403
- }
2404
- /**
2405
- * Folds the collection into a single value without an initial seed value.
2406
- *
2407
- * @example
2408
- * ```ts
2409
- * pipe(Uniq.NonEmpty.singleton(42), Uniq.NonEmpty.reduce((a, b) => a + b)); // 42
2410
- * ```
2411
- */
2412
- const reduce: <A>(f: (acc: A, a: A) => A) => (s: NonEmptySet<A>) => A;
2413
- /**
2414
- * Transforms each item in the non-empty unique collection.
2415
- *
2416
- * @example
2417
- * ```ts
2418
- * pipe(Uniq.NonEmpty.singleton(1), Uniq.NonEmpty.map(n => n * 2)); // ReadonlySet { 2 }
2419
- * ```
2420
- */
2421
- const map: <A, B>(f: (a: A) => B) => (s: NonEmptySet<A>) => NonEmptySet<B>;
2422
- namespace to {
2423
- /**
2424
- * Converts the collection to a non-empty readonly array in insertion order.
2425
- *
2426
- * @example
2427
- * ```ts
2428
- * Uniq.NonEmpty.to.Array(Uniq.NonEmpty.singleton(42)); // [42]
2429
- * ```
2430
- */
2431
- const Array: <A>(s: NonEmptySet<A>) => NonEmptyArr<A>;
2432
- }
2433
- }
1081
+ declare const Uniq: {
1082
+ is: {
1083
+ empty: <A>(s: ReadonlySet<A>) => boolean;
1084
+ nonEmpty: <A>(s: ReadonlySet<A>) => s is NonEmptySet<A>;
1085
+ };
1086
+ empty: <A>() => ReadonlySet<A>;
1087
+ singleton: <A>(item: A) => ReadonlySet<A>;
1088
+ from: {
1089
+ Array: <A>(arr: readonly A[]) => ReadonlySet<A>;
1090
+ };
1091
+ has: <A>(item: A) => (s: ReadonlySet<A>) => boolean;
1092
+ size: <A>(s: ReadonlySet<A>) => number;
1093
+ add: <A>(item: A) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1094
+ insert: <A>(item: A) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1095
+ remove: <A>(item: A) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1096
+ toggle: <A>(item: A) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1097
+ map: <A, B>(f: (a: A) => B) => (s: ReadonlySet<A>) => ReadonlySet<B>;
1098
+ filter: <A>(predicate: (a: A) => boolean) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1099
+ filterMap: <A, B>(f: (a: A) => Maybe<B>) => (s: ReadonlySet<A>) => ReadonlySet<B>;
1100
+ union: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1101
+ intersection: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1102
+ difference: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1103
+ isSubsetOf: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => boolean;
1104
+ reduce: <A, B>(init: B, f: (acc: B, a: A) => B) => (s: ReadonlySet<A>) => B;
1105
+ to: {
1106
+ Array: <A>(s: ReadonlySet<A>) => readonly A[];
1107
+ };
1108
+ NonEmpty: {
1109
+ singleton: <A>(item: A) => NonEmptySet<A>;
1110
+ from: {
1111
+ Set: <A>(s: ReadonlySet<A>) => Maybe<NonEmptySet<A>>;
1112
+ };
1113
+ reduce: <A>(f: (acc: A, a: A) => A) => (s: NonEmptySet<A>) => A;
1114
+ map: <A, B>(f: (a: A) => B) => (s: NonEmptySet<A>) => NonEmptySet<B>;
1115
+ to: {
1116
+ Array: <A>(s: NonEmptySet<A>) => NonEmptyArr<A>;
1117
+ };
1118
+ };
1119
+ };
2434
1120
  declare namespace Uniq {
2435
1121
  /**
2436
1122
  * A branded type representing a unique collection with at least one element.
2437
1123
  */
2438
1124
  type NonEmpty<A> = NonEmptySet<A>;
2439
- namespace is {
2440
- /**
2441
- * Returns `true` if the collection has no items.
2442
- *
2443
- * @example
2444
- * ```ts
2445
- * Uniq.is.empty(Uniq.empty()); // true
2446
- * ```
2447
- */
2448
- const empty: <A>(s: ReadonlySet<A>) => boolean;
2449
- /**
2450
- * Type guard to check if a unique collection is non-empty.
2451
- *
2452
- * @example
2453
- * ```ts
2454
- * Uniq.is.nonEmpty(Uniq.from.Array([1, 2])); // true
2455
- * Uniq.is.nonEmpty(Uniq.empty()); // false
2456
- * ```
2457
- */
2458
- const nonEmpty: <A>(s: ReadonlySet<A>) => s is NonEmpty<A>;
2459
- }
2460
- /**
2461
- * Creates an empty unique collection.
2462
- *
2463
- * @example
2464
- * ```ts
2465
- * Uniq.empty<number>(); // ReadonlySet {}
2466
- * ```
2467
- */
2468
- const empty: <A>() => ReadonlySet<A>;
2469
- /**
2470
- * Creates a unique collection containing a single item.
2471
- *
2472
- * @example
2473
- * ```ts
2474
- * Uniq.singleton(42); // ReadonlySet { 42 }
2475
- * ```
2476
- */
2477
- const singleton: <A>(item: A) => ReadonlySet<A>;
2478
- namespace from {
2479
- /**
2480
- * Creates a unique collection from an array, automatically discarding duplicates.
2481
- *
2482
- * @example
2483
- * ```ts
2484
- * Uniq.from.Array([1, 2, 2, 3, 3, 3]); // ReadonlySet { 1, 2, 3 }
2485
- * Uniq.from.Array([]); // ReadonlySet {}
2486
- * ```
2487
- */
2488
- const Array: <A>(arr: readonly A[]) => ReadonlySet<A>;
2489
- }
2490
- /**
2491
- * Returns `true` if the collection contains the given item.
2492
- *
2493
- * @example
2494
- * ```ts
2495
- * pipe(Uniq.from.Array([1, 2, 3]), Uniq.has(2)); // true
2496
- * pipe(Uniq.from.Array([1, 2, 3]), Uniq.has(4)); // false
2497
- * ```
2498
- */
2499
- const has: <A>(item: A) => (s: ReadonlySet<A>) => boolean;
2500
- /**
2501
- * Returns the number of items in the collection.
2502
- *
2503
- * @example
2504
- * ```ts
2505
- * Uniq.size(Uniq.from.Array([1, 2, 3])); // 3
2506
- * ```
2507
- */
2508
- const size: <A>(s: ReadonlySet<A>) => number;
2509
- /**
2510
- * Returns `true` if every item in `set` also exists in `other`.
2511
- *
2512
- * @example
2513
- * ```ts
2514
- * pipe(Uniq.from.Array([1, 2]), Uniq.isSubsetOf(Uniq.from.Array([1, 2, 3]))); // true
2515
- * pipe(Uniq.from.Array([1, 4]), Uniq.isSubsetOf(Uniq.from.Array([1, 2, 3]))); // false
2516
- * pipe(Uniq.empty<number>(), Uniq.isSubsetOf(Uniq.from.Array([1, 2, 3]))); // true
2517
- * ```
2518
- */
2519
- const isSubsetOf: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => boolean;
2520
- /**
2521
- * Returns a new collection with the item added. If the item is already present, returns the
2522
- * original collection unchanged.
2523
- *
2524
- * @example
2525
- * ```ts
2526
- * pipe(Uniq.from.Array([1, 2]), Uniq.insert(3)); // ReadonlySet { 1, 2, 3 }
2527
- * pipe(Uniq.from.Array([1, 2]), Uniq.insert(2)); // ReadonlySet { 1, 2 } — unchanged
2528
- * ```
2529
- */
2530
- const insert: <A>(item: A) => (s: ReadonlySet<A>) => ReadonlySet<A>;
2531
- /**
2532
- * Returns a new collection with the item removed. If the item is not present, returns the
2533
- * original collection unchanged.
2534
- *
2535
- * @example
2536
- * ```ts
2537
- * pipe(Uniq.from.Array([1, 2, 3]), Uniq.remove(2)); // ReadonlySet { 1, 3 }
2538
- * pipe(Uniq.from.Array([1, 2, 3]), Uniq.remove(4)); // ReadonlySet { 1, 2, 3 } — unchanged
2539
- * ```
2540
- */
2541
- const remove: <A>(item: A) => (s: ReadonlySet<A>) => ReadonlySet<A>;
2542
- /**
2543
- * Applies `f` to each item, returning a new collection of the results. Duplicate results are
2544
- * automatically merged.
2545
- *
2546
- * @example
2547
- * ```ts
2548
- * pipe(Uniq.from.Array([1, 2, 3, 4]), Uniq.map(n => n % 3)); // ReadonlySet { 1, 2, 0 }
2549
- * ```
2550
- */
2551
- const map: <A, B>(f: (a: A) => B) => (s: ReadonlySet<A>) => ReadonlySet<B>;
2552
- /**
2553
- * Returns a new collection containing only the items for which the predicate returns `true`.
2554
- *
2555
- * @example
2556
- * ```ts
2557
- * pipe(Uniq.from.Array([1, 2, 3, 4, 5]), Uniq.filter(n => n % 2 === 0));
2558
- * // ReadonlySet { 2, 4 }
2559
- * ```
2560
- */
2561
- const filter: <A>(predicate: (a: A) => boolean) => (s: ReadonlySet<A>) => ReadonlySet<A>;
2562
- /**
2563
- * Returns a new collection containing all items from both collections.
2564
- *
2565
- * @example
2566
- * ```ts
2567
- * pipe(Uniq.from.Array([1, 2, 3]), Uniq.union(Uniq.from.Array([2, 3, 4])));
2568
- * // ReadonlySet { 1, 2, 3, 4 }
2569
- * ```
2570
- */
2571
- const union: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => ReadonlySet<A>;
2572
- /**
2573
- * Returns a new collection containing only the items that appear in both collections.
2574
- *
2575
- * @example
2576
- * ```ts
2577
- * pipe(Uniq.from.Array([1, 2, 3]), Uniq.intersection(Uniq.from.Array([2, 3, 4])));
2578
- * // ReadonlySet { 2, 3 }
2579
- * ```
2580
- */
2581
- const intersection: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => ReadonlySet<A>;
2582
- /**
2583
- * Returns a new collection containing only the items from `set` that do not appear in `other`.
2584
- *
2585
- * @example
2586
- * ```ts
2587
- * pipe(Uniq.from.Array([1, 2, 3, 4]), Uniq.difference(Uniq.from.Array([2, 4])));
2588
- * // ReadonlySet { 1, 3 }
2589
- * ```
2590
- */
2591
- const difference: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => ReadonlySet<A>;
2592
- /**
2593
- * Folds the collection into a single value by applying `f` to each item in insertion order.
2594
- *
2595
- * @example
2596
- * ```ts
2597
- * Uniq.reduce(0, (acc, n: number) => acc + n)(Uniq.from.Array([1, 2, 3])); // 6
2598
- * ```
2599
- */
2600
- const reduce: <A, B>(init: B, f: (acc: B, a: A) => B) => (s: ReadonlySet<A>) => B;
2601
- namespace to {
2602
- /**
2603
- * Converts the collection to a readonly array in insertion order.
2604
- *
2605
- * @example
2606
- * ```ts
2607
- * Uniq.to.Array(Uniq.from.Array([3, 1, 2])); // [3, 1, 2]
2608
- * ```
2609
- */
2610
- const Array: <A>(s: ReadonlySet<A>) => readonly A[];
2611
- }
2612
- const NonEmpty: typeof UniqNonEmpty;
2613
1125
  }
2614
1126
 
2615
1127
  export { Arr, BigNum, Dict, Json, type NonEmptyMap, type NonEmptyRecord, type NonEmptySet, type NonEmptyString, Num, Rec, Str, Uniq };