ts-data-forge 1.5.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +13 -1
  2. package/dist/array/array-utils.d.mts +693 -351
  3. package/dist/array/array-utils.d.mts.map +1 -1
  4. package/dist/array/array-utils.mjs +474 -1541
  5. package/dist/array/array-utils.mjs.map +1 -1
  6. package/dist/array/index.d.mts +0 -1
  7. package/dist/array/index.d.mts.map +1 -1
  8. package/dist/array/index.mjs +0 -1
  9. package/dist/array/index.mjs.map +1 -1
  10. package/dist/collections/imap-mapped.mjs.map +1 -1
  11. package/dist/collections/imap.mjs.map +1 -1
  12. package/dist/collections/iset-mapped.mjs.map +1 -1
  13. package/dist/collections/iset.mjs.map +1 -1
  14. package/dist/collections/queue.mjs +0 -1
  15. package/dist/collections/queue.mjs.map +1 -1
  16. package/dist/collections/stack.mjs +4 -5
  17. package/dist/collections/stack.mjs.map +1 -1
  18. package/dist/functional/match.d.mts +2 -33
  19. package/dist/functional/match.d.mts.map +1 -1
  20. package/dist/functional/match.mjs +2 -119
  21. package/dist/functional/match.mjs.map +1 -1
  22. package/dist/functional/optional.d.mts +29 -51
  23. package/dist/functional/optional.d.mts.map +1 -1
  24. package/dist/functional/optional.mjs +40 -171
  25. package/dist/functional/optional.mjs.map +1 -1
  26. package/dist/functional/pipe.d.mts +2 -15
  27. package/dist/functional/pipe.d.mts.map +1 -1
  28. package/dist/functional/pipe.mjs +2 -110
  29. package/dist/functional/pipe.mjs.map +1 -1
  30. package/dist/functional/result.d.mts +18 -45
  31. package/dist/functional/result.d.mts.map +1 -1
  32. package/dist/functional/result.mjs +40 -196
  33. package/dist/functional/result.mjs.map +1 -1
  34. package/dist/globals.d.mts +10 -9
  35. package/dist/index.mjs +0 -1
  36. package/dist/index.mjs.map +1 -1
  37. package/dist/iterator/range.d.mts +2 -6
  38. package/dist/iterator/range.d.mts.map +1 -1
  39. package/dist/iterator/range.mjs +2 -93
  40. package/dist/iterator/range.mjs.map +1 -1
  41. package/dist/json/json.mjs +0 -1
  42. package/dist/json/json.mjs.map +1 -1
  43. package/dist/number/num.d.mts +3 -6
  44. package/dist/number/num.d.mts.map +1 -1
  45. package/dist/number/num.mjs +4 -22
  46. package/dist/number/num.mjs.map +1 -1
  47. package/dist/number/refined-number-utils.mjs.map +1 -1
  48. package/dist/object/object.d.mts +4 -10
  49. package/dist/object/object.d.mts.map +1 -1
  50. package/dist/object/object.mjs +8 -140
  51. package/dist/object/object.mjs.map +1 -1
  52. package/dist/others/map-nullable.d.mts +2 -6
  53. package/dist/others/map-nullable.d.mts.map +1 -1
  54. package/dist/others/map-nullable.mjs +2 -146
  55. package/dist/others/map-nullable.mjs.map +1 -1
  56. package/dist/others/memoize-function.mjs.map +1 -1
  57. package/dist/others/unknown-to-string.mjs.map +1 -1
  58. package/package.json +12 -12
  59. package/src/array/array-utils-modification.test.mts +93 -67
  60. package/src/array/array-utils-overload-type-error.test.mts +2 -2
  61. package/src/array/array-utils-reducing-value.test.mts +31 -37
  62. package/src/array/array-utils-slice-clamped.test.mts +94 -70
  63. package/src/array/array-utils-transformation.test.mts +557 -10
  64. package/src/array/array-utils.mts +1835 -1000
  65. package/src/array/index.mts +0 -1
  66. package/src/collections/queue.mts +2 -2
  67. package/src/collections/stack.mts +8 -8
  68. package/src/functional/match.mts +18 -44
  69. package/src/functional/optional.mts +88 -102
  70. package/src/functional/pipe.mts +25 -20
  71. package/src/functional/result.mts +114 -124
  72. package/src/globals.d.mts +10 -9
  73. package/src/iterator/range.mts +14 -17
  74. package/src/number/num.mts +16 -12
  75. package/src/object/object.mts +30 -45
  76. package/src/others/map-nullable.mts +13 -15
  77. package/dist/array/tuple-utils.d.mts +0 -421
  78. package/dist/array/tuple-utils.d.mts.map +0 -1
  79. package/dist/array/tuple-utils.mjs +0 -391
  80. package/dist/array/tuple-utils.mjs.map +0 -1
  81. package/src/array/tuple-utils.mts +0 -519
  82. package/src/array/tuple-utils.test.mts +0 -518
@@ -2,7 +2,6 @@ import '../collections/imap-mapped.mjs';
2
2
  import { IMap } from '../collections/imap.mjs';
3
3
  import '../collections/iset-mapped.mjs';
4
4
  import '../collections/iset.mjs';
5
- import './tuple-utils.mjs';
6
5
  import { isString, isUndefined } from '../guard/is-type.mjs';
7
6
  import { Optional } from '../functional/optional.mjs';
8
7
  import { pipe } from '../functional/pipe.mjs';
@@ -32,7 +31,7 @@ import '../number/branded-types/safe-int.mjs';
32
31
  import '../number/branded-types/safe-uint.mjs';
33
32
  import '../number/branded-types/uint.mjs';
34
33
  import '../number/branded-types/uint16.mjs';
35
- import { asUint32, Uint32 } from '../number/branded-types/uint32.mjs';
34
+ import { Uint32, asUint32 } from '../number/branded-types/uint32.mjs';
36
35
  import '../number/enum/int8.mjs';
37
36
  import '../number/enum/uint8.mjs';
38
37
  import { Num } from '../number/num.mjs';
@@ -77,7 +76,7 @@ var Arr;
77
76
  * // Type: IntersectBrand<PositiveNumber, SizeType.Arr>
78
77
  * // Value: 3 (branded, guaranteed positive)
79
78
  *
80
- * const nonEmpty: NonEmptyArray<string> = ['a', 'b'] as NonEmptyArray<string>;
79
+ * const nonEmpty: NonEmptyArray<string> = ['a', 'b'];
81
80
  * const nonEmptySize = Arr.size(nonEmpty);
82
81
  * // Type: IntersectBrand<PositiveNumber, SizeType.Arr>
83
82
  * // Guaranteed to be > 0
@@ -107,13 +106,6 @@ var Arr;
107
106
  * const indices = Arr.seq(dataSize); // Creates [0, 1, 2]
108
107
  * const zeros = Arr.zeros(dataSize); // Creates [0, 0, 0]
109
108
  *
110
- * // Safe for bounds checking
111
- * const isValidIndex = (index: number) => index >= 0 && index < dataSize;
112
- *
113
- * // Comparison with other sizes
114
- * const otherArray = ['a', 'b'];
115
- * const sizeDiff = Uint32.sub(Arr.size(data), Arr.size(otherArray)); // 1
116
- *
117
109
  * // Functional composition
118
110
  * const arrays = [
119
111
  * [1, 2],
@@ -140,9 +132,9 @@ var Arr;
140
132
  * @see {@link isEmpty} for checking if size is 0
141
133
  * @see {@link isNonEmpty} for checking if size > 0
142
134
  */
135
+ Arr.size = (array) =>
143
136
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
144
- Arr.size = ((array) => asUint32(array.length));
145
- Arr.length = Arr.size;
137
+ array.length;
146
138
  // type guard
147
139
  /**
148
140
  * Type guard that checks if a value is an array, excluding types that cannot be arrays.
@@ -192,26 +184,11 @@ var Arr;
192
184
  * if (Arr.isEmpty(arr)) {
193
185
  * // arr is now typed as readonly []
194
186
  * console.log('Array is empty');
187
+ * // arr[0]; // type error!
195
188
  * return 0;
196
- * } else {
197
- * // arr is now typed as NonEmptyArray<number>
198
- * return arr[0]; // Safe access - TypeScript knows it's non-empty
199
189
  * }
200
190
  * }
201
191
  *
202
- * // Conditional processing
203
- * const data = [10, 20, 30];
204
- * if (!Arr.isEmpty(data)) {
205
- * // Safe to access elements
206
- * const firstElement = data[0]; // No undefined risk
207
- * const lastElement = data[data.length - 1];
208
- * }
209
- *
210
- * // Filtering empty arrays
211
- * const arrayList: readonly number[][] = [[1, 2], [], [3], []];
212
- * const nonEmptyArrays = arrayList.filter(arr => !Arr.isEmpty(arr));
213
- * // nonEmptyArrays: [[1, 2], [3]]
214
- *
215
192
  * // Early returns
216
193
  * function sumArray(numbers: readonly number[]): number {
217
194
  * if (Arr.isEmpty(numbers)) {
@@ -220,12 +197,6 @@ var Arr;
220
197
  * return numbers.reduce((sum, n) => sum + n, 0);
221
198
  * }
222
199
  *
223
- * // Type inference examples
224
- * const testEmpty = [] as const;
225
- * const testNonEmpty = [1, 2] as const;
226
- *
227
- * expectType<Parameters<typeof Arr.isEmpty>[0], readonly unknown[]>('=');
228
- * expectType<ReturnType<typeof Arr.isEmpty>, boolean>('=');
229
200
  * ```
230
201
  *
231
202
  * @see {@link isNonEmpty} for the opposite check (non-empty arrays)
@@ -266,16 +237,14 @@ var Arr;
266
237
  *
267
238
  * // Safe operations on non-empty arrays
268
239
  * function processData(data: readonly string[]) {
269
- * if (Arr.isNonEmpty(data)) {
270
- * // All of these are now safe without undefined checks
271
- * const first = data[0];
272
- * const last = data[data.length - 1];
273
- * const middle = data[Math.floor(data.length / 2)];
274
- *
275
- * // Can safely use non-empty array methods
276
- * const joined = data.join(', ');
277
- * const reduced = data.reduce((acc, item) => acc + item.length, 0);
278
- * }
240
+ * if (!Arr.isNonEmpty(data)) return; // early return pattern
241
+ *
242
+ * // This is now safe without undefined checks
243
+ * const first = data[0];
244
+ *
245
+ * // Can safely use non-empty array methods
246
+ * const lastElement = Arr.last(data);
247
+ *
279
248
  * }
280
249
  *
281
250
  * // Filtering and working with arrays
@@ -300,7 +269,7 @@ var Arr;
300
269
  * }
301
270
  *
302
271
  * // numbers is now NonEmptyArray<number>
303
- * return numbers.reduce((sum, n) => sum + n, 0) / numbers.length;
272
+ * return Arr.sum(numbers) / Arr.size(numbers);
304
273
  * }
305
274
  *
306
275
  * // Functional composition
@@ -432,8 +401,9 @@ var Arr;
432
401
  * expectType<typeof maybeEmpty, readonly 0[]>('=');
433
402
  * ```
434
403
  */
404
+ Arr.zeros = (len) =>
435
405
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
436
- Arr.zeros = ((len) => Array.from({ length: len }).fill(0));
406
+ Array.from({ length: len }).fill(0);
437
407
  /**
438
408
  * Creates a sequence of consecutive integers from 0 to `len-1`.
439
409
  *
@@ -475,8 +445,9 @@ var Arr;
475
445
  * expectType<typeof single, readonly [0]>('=');
476
446
  * ```
477
447
  */
448
+ Arr.seq = (len) =>
478
449
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
479
- Arr.seq = ((len) => Array.from({ length: len }, (_, i) => asUint32(i)));
450
+ Array.from({ length: len }, (_, i) => i);
480
451
  /**
481
452
  * Creates a new array of the specified length, with each position filled with the provided initial value.
482
453
  *
@@ -525,9 +496,9 @@ var Arr;
525
496
  * @see {@link zeros} for creating arrays filled with zeros
526
497
  * @see {@link seq} for creating sequences of consecutive integers
527
498
  */
499
+ Arr.create = (len, init) =>
528
500
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
529
- Arr.create = ((len, init) => Array.from({ length: Math.max(0, len) }, () => init));
530
- Arr.newArray = Arr.create;
501
+ Array.from({ length: Math.max(0, len) }, () => init);
531
502
  /**
532
503
  * Creates an array from a generator function.
533
504
  *
@@ -615,216 +586,11 @@ var Arr;
615
586
  Arr.copy = (array) =>
616
587
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
617
588
  array.slice();
618
- /**
619
- * Creates an array of numbers within a specified range with optional step increment.
620
- *
621
- * This function generates arithmetic sequences with advanced compile-time type inference:
622
- * - When `start` and `end` are {@link SmallUint} literals and `step` is 1 (or omitted), returns a precise tuple type
623
- * - When parameters are runtime values, returns appropriate array types based on sign constraints
624
- * - Empty arrays are returned for invalid ranges (e.g., start ≥ end with positive step)
625
- * - Never throws exceptions - invalid parameters result in empty arrays
626
- *
627
- * **SmallUint Constraint:** The {@link SmallUint} constraint (0-255) enables precise tuple type inference
628
- * for compile-time known ranges. This allows TypeScript to compute exact tuple types like `readonly [1, 2, 3, 4]`
629
- * instead of generic `readonly number[]`.
630
- *
631
- * **Type Inference Behavior:**
632
- * - Literal {@link SmallUint} values with step=1 → precise tuple type (`RangeList<S, E>`)
633
- * - Non-negative parameters → `readonly SafeUint[]`
634
- * - Mixed signs or negative parameters → `readonly SafeInt[]`
635
- * - Runtime values → lose precise typing but maintain safety
636
- *
637
- * @template S The type of the start value. When a {@link SmallUint} literal (0-255), enables precise tuple typing.
638
- * @template E The type of the end value. When a {@link SmallUint} literal (0-255), enables precise tuple typing.
639
- * @param start The start of the range (inclusive). Must be a safe integer. Supports:
640
- * - **Literal {@link SmallUint}:** Enables precise tuple types (0-255)
641
- * - **Runtime {@link SafeInt}:** Fallback to general array types
642
- * - **Negative values:** Supported for countdown sequences
643
- * @param end The end of the range (exclusive). Must be a safe integer. Supports:
644
- * - **Literal {@link SmallUint}:** Enables precise tuple types (0-255)
645
- * - **Runtime {@link SafeInt}:** Fallback to general array types
646
- * - **Equal to start:** Results in empty array
647
- * @param step The step increment (default: 1). Must be a non-zero safe integer.
648
- * - **Positive step:** generates increasing sequence from start to end
649
- * - **Negative step:** generates decreasing sequence from start to end
650
- * - **Zero step:** Not allowed (branded type prevents this)
651
- * @returns An immutable array containing the arithmetic sequence. Return type depends on parameters:
652
- * - `RangeList<S, E>` (precise tuple like `readonly [1, 2, 3, 4]`) when `S` and `E` are {@link SmallUint} literals and step is 1
653
- * - `readonly SafeUint[]` when all parameters are non-negative
654
- * - `readonly SafeInt[]` for general integer ranges including negative values
655
- *
656
- * @example
657
- * ```typescript
658
- * // Compile-time known ranges with step=1 produce precise tuple types
659
- * const range1to4 = Arr.range(1, 5); // readonly [1, 2, 3, 4]
660
- * const range0to2 = Arr.range(0, 3); // readonly [0, 1, 2]
661
- * const emptyRange = Arr.range(5, 5); // readonly []
662
- * const reverseEmpty = Arr.range(5, 1); // readonly [] (invalid with positive step)
663
- *
664
- * // SmallUint constraint examples (0-255 for precise typing)
665
- * const small = Arr.range(0, 10); // readonly [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
666
- * const maxSmall = Arr.range(250, 255); // readonly [250, 251, 252, 253, 254]
667
- * const beyondSmall = Arr.range(0, 300); // readonly SafeUint[] (loses precision)
668
- *
669
- * // Custom step increments
670
- * const evens = Arr.range(0, 10, 2); // readonly SafeUint[] -> [0, 2, 4, 6, 8]
671
- * const odds = Arr.range(1, 10, 2); // readonly SafeUint[] -> [1, 3, 5, 7, 9]
672
- * const countdown = Arr.range(5, 0, -1); // readonly SafeInt[] -> [5, 4, 3, 2, 1]
673
- * const bigStep = Arr.range(0, 20, 5); // readonly SafeUint[] -> [0, 5, 10, 15]
674
- *
675
- * // Edge cases that return empty arrays
676
- * const singleElement = Arr.range(3, 4); // readonly [3]
677
- * const invalidRange = Arr.range(10, 5, 2); // readonly [] (start > end with positive step)
678
- * const invalidReverse = Arr.range(1, 10, -1); // readonly [] (start < end with negative step)
679
- * const zeroRange = Arr.range(42, 42); // readonly [] (start equals end)
680
- *
681
- * // Runtime ranges lose precise typing but maintain safety
682
- * const dynamicStart = Math.floor(Math.random() * 10) as SafeInt;
683
- * const dynamicEnd = (dynamicStart + 5) as SafeInt;
684
- * const dynamicRange = Arr.range(dynamicStart, dynamicEnd); // readonly SafeInt[]
685
- *
686
- * // Negative numbers and mixed signs
687
- * const negativeRange = Arr.range(-5, 5); // readonly SafeInt[] -> [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]
688
- * const negativeCountdown = Arr.range(0, -5, -1); // readonly SafeInt[] -> [0, -1, -2, -3, -4]
689
- *
690
- * // Useful for generating index ranges and iteration
691
- * const indices = Arr.range(0, 10); // readonly [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
692
- * const reversedIndices = Arr.range(9, -1, -1); // readonly SafeInt[] -> [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
693
- *
694
- * // Functional programming patterns
695
- * const squares = Arr.range(1, 6).map(x => x * x); // [1, 4, 9, 16, 25]
696
- * const fibonacci = Arr.range(0, 10).reduce((acc, _, i) => {\n * if (i <= 1) return [...acc, i];\n * return [...acc, acc[i-1] + acc[i-2]];\n * }, [] as number[]); // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
697
- *
698
- * // Type inference examples showing precise vs general types
699
- * expectType<typeof range1to4, readonly [1, 2, 3, 4]>('='); // Precise tuple
700
- * expectType<typeof emptyRange, readonly []>('='); // Precise empty tuple
701
- * expectType<typeof evens, readonly SafeUint[]>('='); // General positive array
702
- * expectType<typeof countdown, readonly SafeInt[]>('='); // General integer array
703
- * expectType<typeof negativeRange, readonly SafeInt[]>('='); // General integer array
704
- * expectType<typeof small, readonly [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>('='); // Precise tuple
705
- * expectType<typeof beyondSmall, readonly SafeUint[]>('='); // General array (beyond SmallUint)
706
- * ```
707
- *
708
- * @throws Never throws - invalid ranges simply return empty arrays
709
- * @see {@link seq} for creating sequences starting from 0
710
- * @see {@link SmallUint} for understanding the constraint that enables precise typing
711
- * @see {@link SafeInt} and {@link SafeUint} for the safe integer types used
712
- */
713
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
714
- Arr.range = ((start, end, step = 1) => Array.from(range(start, end, step)));
715
- // element access
716
- /**
717
- * Safely retrieves an element at a given index from an array, returning an {@link Optional}.
718
- *
719
- * This function provides type-safe array access with support for negative indexing
720
- * (e.g., -1 for the last element). Unlike direct array access which can return
721
- * `undefined` for out-of-bounds indices, this function always returns a well-typed
722
- * {@link Optional} that explicitly represents the possibility of absence.
723
- *
724
- * **Negative Indexing:** Negative indices count from the end of the array:
725
- * - `-1` refers to the last element
726
- * - `-2` refers to the second-to-last element, etc.
727
- *
728
- * **Curried Usage:** This function supports currying - when called with only an index, it returns
729
- * a function that can be applied to arrays, making it ideal for use in pipe operations.
730
- *
731
- * **Optional Return Type:** The return type is always {@link Optional}<E> which provides:
732
- * - Type-safe access without `undefined` in your business logic
733
- * - Explicit handling of \"not found\" cases
734
- * - Composable error handling with {@link Optional} utilities
735
- *
736
- * @template E The type of elements in the array.
737
- * @param array The array to access (when using direct call syntax).
738
- * @param index The index to access. Must be a branded `SizeType.ArgArr` (safe integer). Can be:
739
- * - **Positive integer:** 0-based index from the start (0, 1, 2, ...)
740
- * - **Negative integer:** index from the end (-1 is last element, -2 is second-to-last, etc.)
741
- * - **Out of bounds:** any index beyond array bounds returns {@link Optional.None}
742
- * @returns An {@link Optional}<E> containing:
743
- * - {@link Optional.Some}<E> with the element if the index is valid
744
- * - {@link Optional.None} if the index is out of bounds (including empty arrays)
745
- *
746
- * @example
747
- * ```typescript
748
- * // Direct usage with positive indices
749
- * const fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry'];
750
- * const first = Arr.at(fruits, 0); // Optional.Some('apple')
751
- * const third = Arr.at(fruits, 2); // Optional.Some('cherry')
752
- * const outOfBounds = Arr.at(fruits, 10); // Optional.None
753
- *
754
- * // Negative indexing (accessing from the end)
755
- * const last = Arr.at(fruits, -1); // Optional.Some('elderberry')
756
- * const secondLast = Arr.at(fruits, -2); // Optional.Some('date')
757
- * const negativeOutOfBounds = Arr.at(fruits, -10); // Optional.None
758
- *
759
- * // Edge cases
760
- * const emptyResult = Arr.at([], 0); // Optional.None
761
- * const negativeOnEmpty = Arr.at([], -1); // Optional.None
762
- * const singleElement = Arr.at(['only'], 0); // Optional.Some('only')
763
- * const singleNegative = Arr.at(['only'], -1); // Optional.Some('only')
764
- *
765
- * // Safe access pattern with type-safe unwrapping
766
- * const maybeElement = Arr.at(fruits, 2);
767
- * if (Optional.isSome(maybeElement)) {
768
- * console.log(`Found: ${maybeElement.value}`); // Type-safe access, no undefined
769
- * } else {
770
- * console.log('Index out of bounds');
771
- * }
772
- *
773
- * // Alternative unwrapping with default
774
- * const elementOrDefault = Optional.unwrapOr(Arr.at(fruits, 100), 'not found');
775
- * console.log(elementOrDefault); // 'not found'
776
- *
777
- * // Curried usage for functional composition
778
- * const getSecondElement = Arr.at(1);
779
- * const getLastElement = Arr.at(-1);
780
- * const getMiddleElement = Arr.at(2);
781
- *
782
- * const nestedArrays = [
783
- * [10, 20, 30, 40],
784
- * [50, 60],
785
- * [70]
786
- * ];
787
- * const secondElements = nestedArrays.map(getSecondElement);
788
- * // [Optional.Some(20), Optional.None, Optional.None]
789
- *
790
- * const lastElements = nestedArrays.map(getLastElement);
791
- * // [Optional.Some(40), Optional.Some(60), Optional.Some(70)]
792
- *
793
- * // Pipe composition for data processing
794
- * const processArray = (arr: readonly string[]) => pipe(arr)
795
- * .map(getSecondElement)
796
- * .map(opt => Optional.map(opt, s => s.toUpperCase()))
797
- * .map(opt => Optional.unwrapOr(opt, 'MISSING'))
798
- * .value;
799
- *
800
- * console.log(processArray(['a', 'b', 'c'])); // 'B'
801
- * console.log(processArray(['x'])); // 'MISSING'
802
- *
803
- * // Advanced curried usage with transformation pipelines
804
- * const extractAndProcess = pipe([
805
- * ['hello', 'world', 'typescript'],
806
- * ['functional', 'programming'],
807
- * ['type', 'safety', 'matters', 'most']
808
- * ])
809
- * .map(arr => arr.map(getSecondElement))
810
- * .map(opts => opts.map(opt => Optional.unwrapOr(opt, '[missing]')))
811
- * .value;
812
- * // [['world'], ['[missing]'], ['safety']]
813
- *
814
- * // Type inference examples
815
- * expectType<typeof first, Optional<string>>('=');
816
- * expectType<typeof getSecondElement, <T>(array: readonly T[]) => Optional<T>>('=');
817
- * expectType<typeof negativeOutOfBounds, Optional<string>>('=');
818
- * ```
819
- *
820
- * @see {@link head} for getting the first element specifically
821
- * @see {@link last} for getting the last element specifically
822
- * @see {@link Optional} for working with the returned Optional values
823
- * @see {@link Optional.unwrapOr} for safe unwrapping with defaults
824
- * @see {@link Optional.map} for transforming Optional values
825
- */
826
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
827
- Arr.at = ((...args) => {
589
+ function range$1(start, end, step = 1) {
590
+ return Array.from(range(start, end, step));
591
+ }
592
+ Arr.range = range$1;
593
+ function at(...args) {
828
594
  switch (args.length) {
829
595
  case 2: {
830
596
  const [array, index] = args;
@@ -835,10 +601,11 @@ var Arr;
835
601
  }
836
602
  case 1: {
837
603
  const [index] = args;
838
- return (array) => Arr.at(array, index);
604
+ return (array) => at(array, index);
839
605
  }
840
606
  }
841
- });
607
+ }
608
+ Arr.at = at;
842
609
  /**
843
610
  * Returns the first element of an array wrapped in an Optional.
844
611
  *
@@ -910,11 +677,9 @@ var Arr;
910
677
  * @see {@link at} for accessing elements at specific indices
911
678
  * @see {@link tail} for getting all elements except the first
912
679
  */
680
+ Arr.head = (array) =>
913
681
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
914
- Arr.head = ((array) => {
915
- const element = array.at(0);
916
- return element === undefined ? Optional.none : Optional.some(element);
917
- });
682
+ (array.length === 0 ? Optional.none : Optional.some(array.at(0)));
918
683
  /**
919
684
  * Returns the last element of an array wrapped in an Optional.
920
685
  *
@@ -995,97 +760,10 @@ var Arr;
995
760
  * @see {@link at} for accessing elements at specific indices with negative indexing support
996
761
  * @see {@link butLast} for getting all elements except the last
997
762
  */
763
+ Arr.last = (array) =>
998
764
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
999
- Arr.last = ((array) => {
1000
- const element = array.at(-1);
1001
- return element === undefined ? Optional.none : Optional.some(element);
1002
- });
1003
- // slicing
1004
- /**
1005
- * Slices an array with automatically clamped start and end indices for safe bounds handling.
1006
- *
1007
- * This function provides a safer alternative to `Array.slice()` by automatically clamping
1008
- * the start and end indices to valid bounds, preventing out-of-bounds access and ensuring
1009
- * consistent behavior regardless of input values.
1010
- *
1011
- * **Clamping Behavior:**
1012
- * - `start` is clamped to `[0, array.length]`
1013
- * - `end` is clamped to `[clampedStart, array.length]` (ensuring end ≥ start)
1014
- * - Invalid ranges (start > end after clamping) return empty arrays
1015
- * - Negative indices are clamped to 0, large indices are clamped to array.length
1016
- *
1017
- * **Curried Usage:** This function supports currying - when called with only start and end
1018
- * indices, it returns a function that can be applied to arrays.
1019
- *
1020
- * @template E The type of elements in the array.
1021
- * @param array The array to slice (when using direct call syntax).
1022
- * @param start The start index for the slice (inclusive). Will be clamped to valid bounds.
1023
- * @param end The end index for the slice (exclusive). Will be clamped to valid bounds.
1024
- * @returns A new immutable array containing the sliced elements. Always returns a valid array,
1025
- * never throws for out-of-bounds indices.
1026
- *
1027
- * @example
1028
- * ```typescript
1029
- * const data = [10, 20, 30, 40, 50];
1030
- *
1031
- * // Normal slicing
1032
- * const middle = Arr.sliceClamped(data, 1, 4); // [20, 30, 40]
1033
- * const beginning = Arr.sliceClamped(data, 0, 2); // [10, 20]
1034
- * const end = Arr.sliceClamped(data, 3, 5); // [40, 50]
1035
- *
1036
- * // Automatic clamping for out-of-bounds indices
1037
- * const clampedStart = Arr.sliceClamped(data, -10, 3); // [10, 20, 30] (start clamped to 0)
1038
- * const clampedEnd = Arr.sliceClamped(data, 2, 100); // [30, 40, 50] (end clamped to length)
1039
- * const bothClamped = Arr.sliceClamped(data, -5, 100); // [10, 20, 30, 40, 50] (entire array)
1040
- *
1041
- * // Invalid ranges become empty arrays
1042
- * const emptyReversed = Arr.sliceClamped(data, 4, 1); // [] (start > end after clamping)
1043
- * const emptyAtEnd = Arr.sliceClamped(data, 5, 10); // [] (start at end of array)
1044
- *
1045
- * // Edge cases
1046
- * const emptyArray = Arr.sliceClamped([], 0, 5); // [] (empty input)
1047
- * const singleElement = Arr.sliceClamped([42], 0, 1); // [42]
1048
- * const fullCopy = Arr.sliceClamped(data, 0, data.length); // [10, 20, 30, 40, 50]
1049
- *
1050
- * // Curried usage for functional composition
1051
- * const takeFirst3 = Arr.sliceClamped(0, 3);
1052
- * const getMiddle2 = Arr.sliceClamped(1, 3);
1053
- *
1054
- * const arrays = [
1055
- * [1, 2, 3, 4, 5],
1056
- * [10, 20],
1057
- * [100, 200, 300, 400, 500, 600]
1058
- * ];
1059
- *
1060
- * const first3Elements = arrays.map(takeFirst3);
1061
- * // [[1, 2, 3], [10, 20], [100, 200, 300]]
1062
- *
1063
- * const middle2Elements = arrays.map(getMiddle2);
1064
- * // [[2, 3], [20], [200, 300]]
1065
- *
1066
- * // Pipe composition
1067
- * const result = pipe([1, 2, 3, 4, 5, 6])
1068
- * .map(takeFirst3)
1069
- * .map(Arr.sum)
1070
- * .value; // 6 (sum of [1, 2, 3])
1071
- *
1072
- * // Comparison with regular Array.slice (which can throw or behave unexpectedly)
1073
- * try {
1074
- * // Regular slice with out-of-bounds - works but may be unintuitive
1075
- * const regularSlice = data.slice(-10, 100); // [10, 20, 30, 40, 50]
1076
- * // sliceClamped provides same safe behavior explicitly
1077
- * const clampedSlice = Arr.sliceClamped(data, -10, 100); // [10, 20, 30, 40, 50]
1078
- * } catch (error) {
1079
- * // sliceClamped never throws
1080
- * }
1081
- * ```
1082
- *
1083
- * @see {@link take} for taking the first N elements
1084
- * @see {@link skip} for skipping the first N elements
1085
- * @see {@link takeLast} for taking the last N elements
1086
- */
1087
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1088
- Arr.sliceClamped = ((...args) => {
765
+ (array.length === 0 ? Optional.none : Optional.some(array.at(-1)));
766
+ function sliceClamped(...args) {
1089
767
  switch (args.length) {
1090
768
  case 3: {
1091
769
  const [array, start, end] = args;
@@ -1096,10 +774,11 @@ var Arr;
1096
774
  }
1097
775
  case 2: {
1098
776
  const [start, end] = args;
1099
- return (array) => Arr.sliceClamped(array, start, end);
777
+ return (array) => sliceClamped(array, start, end);
1100
778
  }
1101
779
  }
1102
- });
780
+ }
781
+ Arr.sliceClamped = sliceClamped;
1103
782
  /**
1104
783
  * Returns all elements of an array except the first one.
1105
784
  * @template E The type of the array (can be a tuple for more precise typing).
@@ -1130,342 +809,87 @@ var Arr;
1130
809
  Arr.butLast = (array) =>
1131
810
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1132
811
  (Arr.isEmpty(array) ? [] : array.slice(0, -1));
1133
- /**
1134
- * Takes the first N elements from an array.
1135
- *
1136
- * - If the array is a tuple, the return type is inferred as a tuple of the first N elements.
1137
- * - If the array is a NonEmptyArray and N is a SizeType.ArgArrPositive, returns a NonEmptyArray.
1138
- * - Otherwise, returns a readonly array of up to N elements.
1139
- *
1140
- * @template E The type of the array (can be a tuple for more precise typing).
1141
- * @template N The number of elements to take, constrained to `SmallUint`.
1142
- * @param array The input array.
1143
- * @param num The number of elements to take.
1144
- * @returns A new array containing the first N elements.
1145
- * @example
1146
- * ```ts
1147
- * // Regular usage
1148
- * Arr.take([1, 2, 3, 4] as const, 2); // [1, 2]
1149
- *
1150
- * // Curried usage for pipe composition
1151
- * const takeFirst3 = Arr.take(3);
1152
- * const result = pipe([1, 2, 3, 4, 5]).map(takeFirst3).value;
1153
- * console.log(result); // [1, 2, 3]
1154
- * ```
1155
- */
1156
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1157
- Arr.take = ((...args) => {
812
+ function take(...args) {
1158
813
  switch (args.length) {
1159
814
  case 2: {
1160
815
  const [array, num] = args;
1161
- return Arr.sliceClamped(array, 0, num);
816
+ return sliceClamped(array, 0, num);
1162
817
  }
1163
818
  case 1: {
1164
819
  const [num] = args;
1165
- return (array) => Arr.take(array, num);
820
+ return (array) => take(array, num);
1166
821
  }
1167
822
  }
1168
- });
1169
- /**
1170
- * Takes the last N elements from an array.
1171
- *
1172
- * - If the array is a tuple, the return type is inferred as a tuple of the last N elements.
1173
- * - If the array is a non-empty array and N is a positive integer, returns a non-empty array.
1174
- * - Otherwise, returns a readonly array of up to N elements.
1175
- *
1176
- * @template E The type of the array (can be a tuple for more precise typing).
1177
- * @template N The number of elements to take, constrained to `SmallUint`.
1178
- * @param array The input array.
1179
- * @param num The number of elements to take.
1180
- * @returns A new array containing the last N elements.
1181
- * @example
1182
- * ```ts
1183
- * // Regular usage
1184
- * Arr.takeLast([1, 2, 3, 4] as const, 2); // [3, 4]
1185
- *
1186
- * // Curried usage for pipe composition
1187
- * const takeLast2 = Arr.takeLast(2);
1188
- * const result = pipe([1, 2, 3, 4, 5]).map(takeLast2).value;
1189
- * console.log(result); // [4, 5]
1190
- * ```
1191
- */
1192
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1193
- Arr.takeLast = ((...args) => {
823
+ }
824
+ Arr.take = take;
825
+ function takeLast(...args) {
1194
826
  switch (args.length) {
1195
827
  case 2: {
1196
828
  const [array, num] = args;
1197
- return Arr.sliceClamped(array, Uint32.sub(Arr.size(array), num), Arr.size(array));
829
+ return sliceClamped(array, Uint32.sub(Arr.size(array), num), Arr.size(array));
1198
830
  }
1199
831
  case 1: {
1200
832
  const [num] = args;
1201
- return (array) => Arr.takeLast(array, num);
833
+ return (array) => takeLast(array, num);
1202
834
  }
1203
835
  }
1204
- });
1205
- /**
1206
- * Skips the first N elements of an array.
1207
- *
1208
- * - If the array is a tuple, the return type is inferred as a tuple with the first N elements removed.
1209
- * - If the array is a non-empty array and N is a positive integer, returns a readonly array (may be empty).
1210
- * - Otherwise, returns a readonly array with the first N elements skipped.
1211
- *
1212
- * @template E The type of the array (can be a tuple for more precise typing).
1213
- * @template N The number of elements to skip, constrained to `SmallUint`.
1214
- * @param array The input array.
1215
- * @param num The number of elements to skip.
1216
- * @returns A new array containing the elements after skipping the first N.
1217
- * @example
1218
- * ```ts
1219
- * // Regular usage
1220
- * Arr.skip([1, 2, 3, 4] as const, 2); // [3, 4]
1221
- *
1222
- * // Curried usage for pipe composition
1223
- * const skipFirst2 = Arr.skip(2);
1224
- * const result = pipe([1, 2, 3, 4, 5]).map(skipFirst2).value;
1225
- * console.log(result); // [3, 4, 5]
1226
- * ```
1227
- */
1228
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1229
- Arr.skip = ((...args) => {
836
+ }
837
+ Arr.takeLast = takeLast;
838
+ function skip(...args) {
1230
839
  switch (args.length) {
1231
840
  case 2: {
1232
841
  const [array, num] = args;
1233
- return Arr.sliceClamped(array, num, Arr.size(array));
842
+ return sliceClamped(array, num, Arr.size(array));
1234
843
  }
1235
844
  case 1: {
1236
845
  const [num] = args;
1237
- return (array) => Arr.skip(array, num);
846
+ return (array) => skip(array, num);
1238
847
  }
1239
848
  }
1240
- });
1241
- /**
1242
- * Skips the last N elements of an array.
1243
- *
1244
- * - If the array is a tuple, the return type is inferred as a tuple with the last N elements removed.
1245
- * - If the array is a non-empty array and N is a positive integer, returns a readonly array (may be empty).
1246
- * - Otherwise, returns a readonly array with the last N elements skipped.
1247
- *
1248
- * @template E The type of the array (can be a tuple for more precise typing).
1249
- * @template N The number of elements to skip, constrained to `SmallUint`.
1250
- * @param array The input array.
1251
- * @param num The number of elements to skip from the end.
1252
- * @returns A new array containing the elements after skipping the last N.
1253
- * @example
1254
- * ```ts
1255
- * // Regular usage
1256
- * Arr.skipLast([1, 2, 3, 4] as const, 2); // [1, 2]
1257
- *
1258
- * // Curried usage for pipe composition
1259
- * const skipLast2 = Arr.skipLast(2);
1260
- * const result = pipe([1, 2, 3, 4, 5]).map(skipLast2).value;
1261
- * console.log(result); // [1, 2, 3]
1262
- * ```
1263
- */
1264
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1265
- Arr.skipLast = ((...args) => {
849
+ }
850
+ Arr.skip = skip;
851
+ function skipLast(...args) {
1266
852
  switch (args.length) {
1267
853
  case 2: {
1268
854
  const [array, num] = args;
1269
- return Arr.sliceClamped(array, 0, Uint32.sub(Arr.size(array), num));
855
+ return sliceClamped(array, 0, Uint32.sub(Arr.size(array), num));
1270
856
  }
1271
857
  case 1: {
1272
858
  const [num] = args;
1273
- return (array) => Arr.skipLast(array, num);
859
+ return (array) => skipLast(array, num);
1274
860
  }
1275
861
  }
1276
- });
1277
- // modification (returns new array)
1278
- /**
1279
- * Returns a new array with the element at the specified index updated by a function.
1280
- *
1281
- * This function provides immutable array updates with type-safe bounds checking. It applies an updater
1282
- * function to the element at the given index and returns a new array with the transformed value.
1283
- * The original array is never modified, ensuring immutability.
1284
- *
1285
- * **Type Union Behavior:** When the updater function returns a different type `U` than the original
1286
- * element type `E`, the result type becomes `readonly (E | U)[]` to accommodate both original and
1287
- * updated element types. This ensures type safety when elements have different types after updating.
1288
- *
1289
- * **Bounds Checking:** Unlike native array access which can cause runtime errors, this function
1290
- * performs safe bounds checking:
1291
- * - **Valid index:** Creates new array with updated element
1292
- * - **Invalid index:** Returns the original array unchanged (no errors thrown)
1293
- * - **Negative index:** Treated as invalid (returns original array)
1294
- *
1295
- * **Curried Usage:** Supports currying for functional composition - when called with only index and
1296
- * updater, returns a reusable function that can be applied to arrays.
1297
- *
1298
- * @template E The type of elements in the original array.
1299
- * @template U The type of the value returned by the updater function.
1300
- * @param array The input array to update. Can be any readonly array.
1301
- * @param index The index of the element to update. Must be a non-negative {@link SizeType.ArgArrNonNegative}.
1302
- * - **Valid range:** `0 <= index < array.length`
1303
- * - **Out of bounds:** Returns original array unchanged
1304
- * - **Negative values:** Not allowed by type system (non-negative constraint)
1305
- * @param updater A function `(prev: E) => U` that transforms the existing element:
1306
- * - **prev:** The current element at the specified index
1307
- * - **returns:** The new value to place at that index (can be different type)
1308
- * @returns A new `readonly (E | U)[]` array where:
1309
- * - All elements except the target index remain unchanged (type `E`)
1310
- * - The element at the target index is replaced with the updater result (type `U`)
1311
- * - Type union `E | U` accommodates both original and updated element types
1312
- * - If index is out of bounds, returns the original array unchanged
1313
- *
1314
- * @example
1315
- * ```typescript
1316
- * // Basic usage with same type transformation
1317
- * const numbers = [1, 2, 3, 4, 5];
1318
- * const doubled = Arr.toUpdated(numbers, 2, x => x * 2);
1319
- * // readonly number[] -> [1, 2, 6, 4, 5]
1320
- *
1321
- * // Type union when updater returns different type
1322
- * const mixed = Arr.toUpdated(numbers, 1, x => `value: ${x}`);
1323
- * // readonly (number | string)[] -> [1, 'value: 2', 3, 4, 5]
1324
- *
1325
- * // Complex object updates
1326
- * const users = [
1327
- * { id: 1, name: 'Alice', active: true },
1328
- * { id: 2, name: 'Bob', active: false },
1329
- * { id: 3, name: 'Charlie', active: true }
1330
- * ];
1331
- *
1332
- * const activatedUser = Arr.toUpdated(users, 1, user => ({
1333
- * ...user,
1334
- * active: true,
1335
- * lastUpdated: new Date()
1336
- * }));
1337
- * // Bob is now active with lastUpdated field
1338
- *
1339
- * // Bounds checking behavior
1340
- * const safe1 = Arr.toUpdated([1, 2, 3], 10, x => x * 2); // [1, 2, 3] (index out of bounds)
1341
- * const safe2 = Arr.toUpdated([1, 2, 3], 0, x => x * 2); // [2, 2, 3] (valid index)
1342
- * const safe3 = Arr.toUpdated([], 0, x => x); // [] (empty array, index out of bounds)
1343
- *
1344
- * // Functional transformations
1345
- * const products = [
1346
- * { name: 'laptop', price: 1000 },
1347
- * { name: 'mouse', price: 25 },
1348
- * { name: 'keyboard', price: 75 }
1349
- * ];
1350
- *
1351
- * const discounted = Arr.toUpdated(products, 0, product => ({
1352
- * ...product,
1353
- * price: Math.round(product.price * 0.8), // 20% discount
1354
- * onSale: true
1355
- * }));
1356
- * // First product now has discounted price and onSale flag
1357
- *
1358
- * // Curried usage for reusable updates
1359
- * const doubleAtIndex2 = Arr.toUpdated(2, (x: number) => x * 2);
1360
- * const capitalizeAtIndex0 = Arr.toUpdated(0, (s: string) => s.toUpperCase());
1361
- * const markCompleteAtIndex = (index: number) =>
1362
- * Arr.toUpdated(index, (task: {done: boolean}) => ({...task, done: true}));
1363
- *
1364
- * const numberArrays = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
1365
- * const allDoubled = numberArrays.map(doubleAtIndex2);
1366
- * // [[1, 2, 6], [4, 5, 12], [7, 8, 18]]
1367
- *
1368
- * const words = [['hello', 'world'], ['foo', 'bar'], ['type', 'script']];
1369
- * const capitalized = words.map(capitalizeAtIndex0);
1370
- * // [['HELLO', 'world'], ['FOO', 'bar'], ['TYPE', 'script']]
1371
- *
1372
- * // Pipe composition for data processing
1373
- * const processArray = (arr: readonly number[]) => pipe(arr)
1374
- * .map(Arr.toUpdated(0, x => x * 10)) // Scale first element
1375
- * .map(Arr.toUpdated(1, x => typeof x === 'number' ? x + 100 : x)) // Add to second if number
1376
- * .value;
1377
- *
1378
- * console.log(processArray([1, 2, 3])); // [10, 102, 3]
1379
- *
1380
- * // Multiple sequential updates
1381
- * const pipeline = (data: readonly number[]) => pipe(data)
1382
- * .map(Arr.toUpdated(0, x => x * 2))
1383
- * .map(Arr.toUpdated(1, x => typeof x === 'number' ? x + 10 : x))
1384
- * .map(Arr.toUpdated(2, x => typeof x === 'number' ? x.toString() : x))
1385
- * .value;
1386
- *
1387
- * console.log(pipeline([1, 2, 3])); // [2, 12, '3'] - readonly (number | string)[]
1388
- *
1389
- * // Error-safe updates in data processing
1390
- * const safeUpdate = <T, U>(
1391
- * array: readonly T[],
1392
- * index: number,
1393
- * updater: (value: T) => U
1394
- * ) => {
1395
- * if (index < 0 || index >= array.length) {
1396
- * console.warn(`Index ${index} out of bounds for array of length ${array.length}`);
1397
- * return array;
1398
- * }
1399
- * return Arr.toUpdated(array, index as SizeType.ArgArrNonNegative, updater);
1400
- * };
1401
- *
1402
- * // Advanced: State management pattern
1403
- * type AppState = {
1404
- * users: Array<{id: number, name: string}>;
1405
- * currentUserId: number;
1406
- * };
1407
- *
1408
- * const updateUserName = (state: AppState, userId: number, newName: string): AppState => {
1409
- * const userIndex = state.users.findIndex(u => u.id === userId);
1410
- * if (userIndex === -1) return state;
1411
- *
1412
- * return {
1413
- * ...state,
1414
- * users: Arr.toUpdated(state.users, userIndex as SizeType.ArgArrNonNegative, user => ({
1415
- * ...user,
1416
- * name: newName
1417
- * }))
1418
- * };
1419
- * };
1420
- *
1421
- * // Type inference examples showing union types
1422
- * expectType<typeof doubled, readonly number[]>('='); // Same type
1423
- * expectType<typeof mixed, readonly (number | string)[]>('='); // Union type
1424
- * expectType<typeof doubleAtIndex2, <T extends readonly number[]>(array: T) => readonly (number | number)[]>('=');
1425
- * expectType<typeof safe1, readonly number[]>('='); // Bounds check preserves type
1426
- * ```
1427
- *
1428
- * @see {@link Array.prototype.with} for the native method with different error handling
1429
- * @see {@link SizeType.ArgArrNonNegative} for the index type constraint
1430
- * @see Immutable update patterns for functional programming approaches
1431
- */
1432
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1433
- Arr.toUpdated = ((...args) => {
862
+ }
863
+ Arr.skipLast = skipLast;
864
+ function set(...args) {
865
+ switch (args.length) {
866
+ case 3: {
867
+ const [array, index, newValue] = args;
868
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
869
+ return array.with(index, newValue);
870
+ }
871
+ case 2: {
872
+ const [index, newValue] = args;
873
+ return (array) => set(array, index, newValue);
874
+ }
875
+ }
876
+ }
877
+ Arr.set = set;
878
+ function toUpdated(...args) {
1434
879
  switch (args.length) {
1435
880
  case 3: {
1436
881
  const [array, index, updater] = args;
1437
- return index < 0 || index >= array.length
1438
- ? array // Return a copy if index is out of bounds
1439
- : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unsafe-type-assertion
1440
- array.with(index, updater(array[index]));
882
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unsafe-type-assertion
883
+ return array.with(index, updater(array[index]));
1441
884
  }
1442
885
  case 2: {
1443
886
  const [index, updater] = args;
1444
- return (array) => Arr.toUpdated(array, index, updater);
887
+ return (array) => toUpdated(array, index, updater);
1445
888
  }
1446
889
  }
1447
- });
1448
- /**
1449
- * Returns a new array with a new value inserted at the specified index.
1450
- * Index can be out of bounds (e.g., negative or greater than length), `toSpliced` handles this.
1451
- * @template E The type of elements in the array.
1452
- * @param array The input array.
1453
- * @param index The index at which to insert the new value.
1454
- * @param newValue The value to insert.
1455
- * @returns A new array with the value inserted.
1456
- * @example
1457
- * ```ts
1458
- * // Regular usage
1459
- * Arr.toInserted([1, 2, 3], 1, 10); // [1, 10, 2, 3]
1460
- *
1461
- * // Curried usage for pipe composition
1462
- * const insertAtStart = Arr.toInserted(0, 99);
1463
- * const result = pipe([1, 2, 3]).map(insertAtStart).value;
1464
- * console.log(result); // [99, 1, 2, 3]
1465
- * ```
1466
- */
1467
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1468
- Arr.toInserted = ((...args) => {
890
+ }
891
+ Arr.toUpdated = toUpdated;
892
+ function toInserted(...args) {
1469
893
  switch (args.length) {
1470
894
  case 3: {
1471
895
  const [array, index, newValue] = args;
@@ -1474,30 +898,12 @@ var Arr;
1474
898
  }
1475
899
  case 2: {
1476
900
  const [index, newValue] = args;
1477
- return (array) => Arr.toInserted(array, index, newValue);
901
+ return (array) => toInserted(array, index, newValue);
1478
902
  }
1479
903
  }
1480
- });
1481
- /**
1482
- * Returns a new array with the element at the specified index removed.
1483
- * If index is out of bounds, `toSpliced` handles this (usually by returning a copy).
1484
- * @template E The type of elements in the array.
1485
- * @param array The input array.
1486
- * @param index The index of the element to remove.
1487
- * @returns A new array with the element removed.
1488
- * @example
1489
- * ```ts
1490
- * // Regular usage
1491
- * Arr.toRemoved([1, 2, 3], 1); // [1, 3]
1492
- *
1493
- * // Curried usage for pipe composition
1494
- * const removeFirst = Arr.toRemoved(0);
1495
- * const result = pipe([10, 20, 30]).map(removeFirst).value;
1496
- * console.log(result); // [20, 30]
1497
- * ```
1498
- */
1499
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1500
- Arr.toRemoved = ((...args) => {
904
+ }
905
+ Arr.toInserted = toInserted;
906
+ function toRemoved(...args) {
1501
907
  switch (args.length) {
1502
908
  case 2: {
1503
909
  const [array, index] = args;
@@ -1505,109 +911,53 @@ var Arr;
1505
911
  }
1506
912
  case 1: {
1507
913
  const [index] = args;
1508
- return (array) => Arr.toRemoved(array, index);
914
+ return (array) => toRemoved(array, index);
1509
915
  }
1510
916
  }
1511
- });
1512
- /**
1513
- * Returns a new array with a value added to the end.
1514
- * @template E The type of the input array (can be a tuple).
1515
- * @template V The type of the value to add.
1516
- * @param array The input array.
1517
- * @param newValue The value to add.
1518
- * @returns A new array with the value added to the end. Type is `readonly [...E, V]`.
1519
- * @example
1520
- * ```ts
1521
- * // Regular usage
1522
- * Arr.toPushed([1, 2] as const, 3); // [1, 2, 3]
1523
- *
1524
- * // Curried usage for pipe composition
1525
- * const addZero = Arr.toPushed(0);
1526
- * const result = pipe([1, 2, 3]).map(addZero).value;
1527
- * console.log(result); // [1, 2, 3, 0]
1528
- * ```
1529
- */
1530
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1531
- Arr.toPushed = ((...args) => {
917
+ }
918
+ Arr.toRemoved = toRemoved;
919
+ function toPushed(...args) {
1532
920
  switch (args.length) {
1533
921
  case 2: {
1534
922
  const [array, newValue] = args;
923
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1535
924
  return array.toSpliced(array.length, 0, newValue);
1536
925
  }
1537
926
  case 1: {
1538
927
  const [newValue] = args;
1539
- return (array) => Arr.toPushed(array, newValue);
928
+ return (array) => toPushed(array, newValue);
1540
929
  }
1541
930
  }
1542
- });
1543
- /**
1544
- * Returns a new array with a value added to the beginning.
1545
- * @template E The type of the input array (can be a tuple).
1546
- * @template V The type of the value to add.
1547
- * @param array The input array.
1548
- * @param newValue The value to add.
1549
- * @returns A new array with the value added to the beginning. Type is `readonly [V, ...E]`.
1550
- * @example
1551
- * ```ts
1552
- * // Regular usage
1553
- * Arr.toUnshifted([1, 2] as const, 0); // [0, 1, 2]
1554
- *
1555
- * // Curried usage for pipe composition
1556
- * const prependZero = Arr.toUnshifted(0);
1557
- * const result = pipe([1, 2, 3]).map(prependZero).value;
1558
- * console.log(result); // [0, 1, 2, 3]
1559
- * ```
1560
- */
1561
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1562
- Arr.toUnshifted = ((...args) => {
931
+ }
932
+ Arr.toPushed = toPushed;
933
+ function toUnshifted(...args) {
1563
934
  switch (args.length) {
1564
935
  case 2: {
1565
936
  const [array, newValue] = args;
937
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1566
938
  return array.toSpliced(0, 0, newValue);
1567
939
  }
1568
940
  case 1: {
1569
941
  const [newValue] = args;
1570
- return (array) => Arr.toUnshifted(array, newValue);
942
+ return (array) => toUnshifted(array, newValue);
1571
943
  }
1572
944
  }
1573
- });
1574
- /**
1575
- * Fills an array with a value (creates a new filled array).
1576
- * @param array The array.
1577
- * @param value The value to fill with.
1578
- * @param start The start index.
1579
- * @param end The end index.
1580
- * @returns A new filled array.
1581
- * @example
1582
- * ```typescript
1583
- * // Regular usage
1584
- * const arr = [1, 2, 3, 4, 5];
1585
- * const result = Arr.toFilled(arr, 0, 1, 4);
1586
- * console.log(result); // [1, 0, 0, 0, 5]
1587
- *
1588
- * // Curried usage for pipe composition
1589
- * const fillWithZeros = Arr.toFilled(0, 1, 3);
1590
- * const result2 = pipe([1, 2, 3, 4]).map(fillWithZeros).value;
1591
- * console.log(result2); // [1, 0, 0, 4]
1592
- * ```
1593
- */
1594
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1595
- Arr.toFilled = ((...args) => {
945
+ }
946
+ Arr.toUnshifted = toUnshifted;
947
+ function toFilled(...args) {
1596
948
  switch (args.length) {
1597
949
  case 2: {
1598
950
  const [array, value] = args;
1599
- const cp = castMutable(Arr.copy(array));
1600
- cp.fill(value);
1601
- return cp;
951
+ return Arr.create(asPositiveUint32(array.length), value);
1602
952
  }
1603
953
  case 1: {
1604
954
  const [value] = args;
1605
- return (array) => Arr.toFilled(array, value);
955
+ return (array) => toFilled(array, value);
1606
956
  }
1607
957
  }
1608
- });
1609
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1610
- Arr.toRangeFilled = ((...args) => {
958
+ }
959
+ Arr.toFilled = toFilled;
960
+ function toRangeFilled(...args) {
1611
961
  switch (args.length) {
1612
962
  case 3: {
1613
963
  const [array, value, [start, end]] = args;
@@ -1617,50 +967,12 @@ var Arr;
1617
967
  }
1618
968
  case 2: {
1619
969
  const [value, fillRange] = args;
1620
- return (array) => Arr.toRangeFilled(array, value, fillRange);
970
+ return (array) => toRangeFilled(array, value, fillRange);
1621
971
  }
1622
972
  }
1623
- });
1624
- // searching
1625
- /**
1626
- * Safely finds the first element in an array that satisfies a predicate function.
1627
- *
1628
- * This function provides type-safe searching with no risk of runtime errors. It returns
1629
- * the first element that matches the predicate wrapped in an Optional, or Optional.None
1630
- * if no element is found. The predicate receives the element, its index, and the entire array.
1631
- *
1632
- * **Curried Usage:** This function supports currying - when called with only a predicate,
1633
- * it returns a function that can be applied to arrays, making it ideal for functional composition.
1634
- *
1635
- * @template E The type of elements in the array.
1636
- * @param array The array to search through (when using direct call syntax).
1637
- * @param predicate A function that tests each element. Called with:
1638
- * - `value`: The current element being tested
1639
- * - `index`: The index of the current element (branded as `SizeType.Arr`)
1640
- * - `arr`: The entire array being searched
1641
- * @returns An `Optional<E>` containing:
1642
- * - `Optional.Some<E>` with the first matching element if found
1643
- * - `Optional.None` if no element satisfies the predicate
1644
- *
1645
- * @example
1646
- * ```typescript
1647
- * const numbers = [1, 2, 3, 4, 5];
1648
- * const firstEven = Arr.find(numbers, x => x % 2 === 0);
1649
- * if (Optional.isSome(firstEven)) {
1650
- * console.log(firstEven.value); // 2
1651
- * }
1652
- *
1653
- * const users = [{ id: 1, name: 'Alice', age: 25 }, { id: 2, name: 'Bob', age: 30 }];
1654
- * const adult = Arr.find(users, user => user.age >= 30);
1655
- * // Optional.Some({ id: 2, name: 'Bob', age: 30 })
1656
- * ```
1657
- *
1658
- * @see {@link findIndex} for finding the index instead of the element
1659
- * @see {@link indexOf} for finding elements by equality
1660
- * @see {@link Optional} for working with the returned Optional values
1661
- */
1662
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1663
- Arr.find = ((...args) => {
973
+ }
974
+ Arr.toRangeFilled = toRangeFilled;
975
+ function find(...args) {
1664
976
  switch (args.length) {
1665
977
  case 2: {
1666
978
  const [array, predicate] = args;
@@ -1674,117 +986,31 @@ var Arr;
1674
986
  }
1675
987
  case 1: {
1676
988
  const [predicate] = args;
1677
- return (array) => Arr.find(array, predicate);
989
+ return (array) => find(array, predicate);
1678
990
  }
1679
991
  }
1680
- });
1681
- /**
1682
- * Safely finds the index of the first element in an array that satisfies a predicate function.
1683
- *
1684
- * This function provides type-safe index searching with no risk of runtime errors. It returns
1685
- * the index of the first element that matches the predicate wrapped in an Optional, or Optional.None
1686
- * if no element is found. The returned index is branded as `SizeType.Arr` for type safety.
1687
- *
1688
- * **Curried Usage:** This function supports currying - when called with only a predicate,
1689
- * it returns a function that can be applied to arrays, making it ideal for functional composition.
1690
- *
1691
- * @template E The type of elements in the array.
1692
- * @param array The array to search through (when using direct call syntax).
1693
- * @param predicate A function that tests each element. Called with:
1694
- * - `value`: The current element being tested
1695
- * - `index`: The index of the current element (branded as `SizeType.Arr`)
1696
- * @returns An `Optional<SizeType.Arr>` containing:
1697
- * - `Optional.Some<SizeType.Arr>` with the index of the first matching element if found
1698
- * - `Optional.None` if no element satisfies the predicate
1699
- *
1700
- * @example
1701
- * ```typescript
1702
- * // Basic index finding
1703
- * const fruits = ['apple', 'banana', 'cherry', 'banana'];
1704
- * const bananaIndex = Arr.findIndex(fruits, fruit => fruit === 'banana');
1705
- * if (Optional.isSome(bananaIndex)) {
1706
- * console.log(bananaIndex.value); // 1 - index of first 'banana'
1707
- * }
1708
- *
1709
- * // Finding with complex conditions
1710
- * const numbers = [1, 5, 10, 15, 20];
1711
- * const firstLargeIndex = Arr.findIndex(numbers, (value, index) =>
1712
- * value > 10 && index > 1
1713
- * );
1714
- * // Optional.Some(3) - index of 15 (first value > 10 after index 1)
1715
- *
1716
- * // Finding objects by property
1717
- * const users = [
1718
- * { id: 1, active: false },
1719
- * { id: 2, active: true },
1720
- * { id: 3, active: true }
1721
- * ];
1722
- *
1723
- * const firstActiveIndex = Arr.findIndex(users, user => user.active);
1724
- * // Optional.Some(1) - index of first active user
1725
- *
1726
- * const inactiveAdminIndex = Arr.findIndex(users, user => !user.active && user.id > 5);
1727
- * // Optional.None - no inactive user with id > 5
1728
- *
1729
- * // Empty array handling
1730
- * const emptyResult = Arr.findIndex([], x => x > 0); // Optional.None
1731
- *
1732
- * // Curried usage for functional composition
1733
- * const findNegativeIndex = Arr.findIndex((x: number) => x < 0);
1734
- * const findLongStringIndex = Arr.findIndex((s: string) => s.length > 5);
1735
- *
1736
- * const datasets = [
1737
- * [1, 2, -3, 4], // index 2 has negative
1738
- * [5, 6, 7, 8], // no negative
1739
- * [-1, 0, 1] // index 0 has negative
1740
- * ];
1741
- *
1742
- * const negativeIndices = datasets.map(findNegativeIndex);
1743
- * // [Optional.Some(2), Optional.None, Optional.Some(0)]
1744
- *
1745
- * // Using found indices for further operations
1746
- * const data = ['short', 'medium', 'very long string', 'tiny'];
1747
- * const longStringIndex = Arr.findIndex(data, s => s.length > 8);
1748
- *
1749
- * if (Optional.isSome(longStringIndex)) {
1750
- * const index = longStringIndex.value;
1751
- * console.log(`Found at position ${index}: ${data[index]}`);
1752
- * // "Found at position 2: very long string"
1753
- * }
1754
- *
1755
- * // Pipe composition
1756
- * const result = pipe(['a', 'bb', 'ccc'])
1757
- * .map(findLongStringIndex)
1758
- * .map(opt => Optional.unwrapOr(opt, -1))
1759
- * .value; // 2 (index of 'ccc')
1760
- *
1761
- * // Comparing with native findIndex (which returns -1)
1762
- * const nativeResult = fruits.findIndex(fruit => fruit === 'grape'); // -1
1763
- * const safeResult = Arr.findIndex(fruits, fruit => fruit === 'grape'); // Optional.None
1764
- *
1765
- * // Safe index usage patterns
1766
- * const maybeIndex = Arr.findIndex(numbers, x => x > 100);
1767
- * const indexOrDefault = Optional.unwrapOr(maybeIndex, 0); // 0 (not found)
1768
- *
1769
- * // Using index for array access
1770
- * const foundIndex = Arr.findIndex(fruits, f => f.startsWith('c'));
1771
- * const foundElement = Optional.isSome(foundIndex)
1772
- * ? fruits[foundIndex.value]
1773
- * : 'not found';
1774
- * // 'cherry'
1775
- *
1776
- * // Type inference examples
1777
- * expectType<typeof bananaIndex, Optional<SizeType.Arr>>('=');
1778
- * expectType<typeof findNegativeIndex, (array: readonly number[]) => Optional<SizeType.Arr>>('=');
1779
- * ```
1780
- *
1781
- * @see {@link find} for finding the element instead of its index
1782
- * @see {@link indexOf} for finding elements by equality (not predicate)
1783
- * @see {@link lastIndexOf} for finding the last occurrence
1784
- * @see {@link Optional} for working with the returned Optional values
1785
- */
1786
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1787
- Arr.findIndex = ((...args) => {
992
+ }
993
+ Arr.find = find;
994
+ function findLast(...args) {
995
+ switch (args.length) {
996
+ case 2: {
997
+ const [array, predicate] = args;
998
+ const foundIndex = array.findLastIndex(
999
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1000
+ predicate);
1001
+ return foundIndex === -1
1002
+ ? Optional.none
1003
+ : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1004
+ Optional.some(array[foundIndex]);
1005
+ }
1006
+ case 1: {
1007
+ const [predicate] = args;
1008
+ return (array) => findLast(array, predicate);
1009
+ }
1010
+ }
1011
+ }
1012
+ Arr.findLast = findLast;
1013
+ function findIndex(...args) {
1788
1014
  switch (args.length) {
1789
1015
  case 2: {
1790
1016
  const [array, predicate] = args;
@@ -1794,33 +1020,27 @@ var Arr;
1794
1020
  }
1795
1021
  case 1: {
1796
1022
  const [predicate] = args;
1797
- return (array) => Arr.findIndex(array, predicate);
1023
+ return (array) => findIndex(array, predicate);
1798
1024
  }
1799
1025
  }
1800
- });
1801
- /**
1802
- * Gets the index of a value in an array.
1803
- * @param array The array to search.
1804
- * @param searchElement The element to search for.
1805
- * @param fromIndex The index to start searching from.
1806
- * @returns The index if found, -1 otherwise.
1807
- * @example
1808
- * ```typescript
1809
- * // Regular usage
1810
- * const arr = ['a', 'b', 'c', 'b'];
1811
- * const result = Arr.indexOf(arr, 'b');
1812
- * if (Optional.isSome(result)) {
1813
- * console.log(result.value); // 1 (branded as SizeType.Arr)
1814
- * }
1815
- *
1816
- * // Curried usage for pipe composition
1817
- * const findB = Arr.indexOf('b');
1818
- * const result2 = pipe(['a', 'b', 'c']).map(findB).value;
1819
- * console.log(Optional.unwrapOr(result2, -1)); // 1
1820
- * ```
1821
- */
1822
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1823
- Arr.indexOf = ((...args) => {
1026
+ }
1027
+ Arr.findIndex = findIndex;
1028
+ function findLastIndex(...args) {
1029
+ switch (args.length) {
1030
+ case 2: {
1031
+ const [array, predicate] = args;
1032
+ return pipe(array.findLastIndex(
1033
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1034
+ predicate)).map((idx) => (idx >= 0 ? asUint32(idx) : -1)).value;
1035
+ }
1036
+ case 1: {
1037
+ const [predicate] = args;
1038
+ return (array) => findLastIndex(array, predicate);
1039
+ }
1040
+ }
1041
+ }
1042
+ Arr.findLastIndex = findLastIndex;
1043
+ function indexOf(...args) {
1824
1044
  switch (args.length) {
1825
1045
  case 2: {
1826
1046
  const [array, searchElement] = args;
@@ -1829,12 +1049,12 @@ var Arr;
1829
1049
  }
1830
1050
  case 1: {
1831
1051
  const [searchElement] = args;
1832
- return (array) => Arr.indexOf(array, searchElement);
1052
+ return (array) => indexOf(array, searchElement);
1833
1053
  }
1834
1054
  }
1835
- });
1836
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1837
- Arr.indexOfFrom = ((...args) => {
1055
+ }
1056
+ Arr.indexOf = indexOf;
1057
+ function indexOfFrom(...args) {
1838
1058
  switch (args.length) {
1839
1059
  case 3: {
1840
1060
  const [array, searchElement, fromIndex] = args;
@@ -1843,33 +1063,12 @@ var Arr;
1843
1063
  }
1844
1064
  case 2: {
1845
1065
  const [searchElement, fromIndex] = args;
1846
- return (array) => Arr.indexOfFrom(array, searchElement, fromIndex);
1066
+ return (array) => indexOfFrom(array, searchElement, fromIndex);
1847
1067
  }
1848
1068
  }
1849
- });
1850
- /**
1851
- * Gets the last index of a value in an array.
1852
- * @param array The array to search.
1853
- * @param searchElement The element to search for.
1854
- * @param fromIndex The index to start searching from (searches backwards).
1855
- * @returns Optional.Some with the index if found, Optional.None otherwise.
1856
- * @example
1857
- * ```typescript
1858
- * // Regular usage
1859
- * const arr = ['a', 'b', 'c', 'b'];
1860
- * const result = Arr.lastIndexOf(arr, 'b');
1861
- * if (Optional.isSome(result)) {
1862
- * console.log(result.value); // 3 (branded as SizeType.Arr)
1863
- * }
1864
- *
1865
- * // Curried usage for pipe composition
1866
- * const findLastB = Arr.lastIndexOf('b');
1867
- * const result2 = pipe(['a', 'b', 'c', 'b']).map(findLastB).value;
1868
- * console.log(Optional.unwrapOr(result2, -1)); // 3
1869
- * ```
1870
- */
1871
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1872
- Arr.lastIndexOf = ((...args) => {
1069
+ }
1070
+ Arr.indexOfFrom = indexOfFrom;
1071
+ function lastIndexOf(...args) {
1873
1072
  switch (args.length) {
1874
1073
  case 2: {
1875
1074
  const [array, searchElement] = args;
@@ -1878,12 +1077,12 @@ var Arr;
1878
1077
  }
1879
1078
  case 1: {
1880
1079
  const [searchElement] = args;
1881
- return (array) => Arr.lastIndexOf(array, searchElement);
1080
+ return (array) => lastIndexOf(array, searchElement);
1882
1081
  }
1883
1082
  }
1884
- });
1885
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1886
- Arr.lastIndexOfFrom = ((...args) => {
1083
+ }
1084
+ Arr.lastIndexOf = lastIndexOf;
1085
+ function lastIndexOfFrom(...args) {
1887
1086
  switch (args.length) {
1888
1087
  case 3: {
1889
1088
  const [array, searchElement, fromIndex] = args;
@@ -1892,27 +1091,38 @@ var Arr;
1892
1091
  }
1893
1092
  case 2: {
1894
1093
  const [searchElement, fromIndex] = args;
1895
- return (array) => Arr.lastIndexOfFrom(array, searchElement, fromIndex);
1094
+ return (array) => lastIndexOfFrom(array, searchElement, fromIndex);
1896
1095
  }
1897
1096
  }
1898
- });
1899
- // reducing value
1900
- /**
1901
- * Applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value.
1902
- * This is an alias for `Array.prototype.reduce`.
1903
- * @template E The type of elements in the array.
1904
- * @template S The type of the accumulated value.
1905
- * @param array The input array.
1906
- * @param callbackfn A function to execute on each element in the array: `(previousValue: S, currentValue: A, currentIndex: SizeType.Arr) => S`.
1907
- * @param initialValue The initial value of the accumulator.
1908
- * @returns The single value that results from the reduction.
1909
- * @example
1910
- * ```ts
1911
- * Arr.foldl([1, 2, 3], (sum, n) => sum + n, 0); // 6
1912
- * Arr.foldl(['a', 'b', 'c'], (acc, str) => acc + str.toUpperCase(), ''); // 'ABC'
1913
- * ```
1914
- */
1915
- Arr.foldl = (...args) => {
1097
+ }
1098
+ Arr.lastIndexOfFrom = lastIndexOfFrom;
1099
+ function every(...args) {
1100
+ switch (args.length) {
1101
+ case 2: {
1102
+ const [array, predicate] = args;
1103
+ return array.every((a, i) => predicate(a, asUint32(i)));
1104
+ }
1105
+ case 1: {
1106
+ const [predicate] = args;
1107
+ return (array) => every(array, predicate);
1108
+ }
1109
+ }
1110
+ }
1111
+ Arr.every = every;
1112
+ function some(...args) {
1113
+ switch (args.length) {
1114
+ case 2: {
1115
+ const [array, predicate] = args;
1116
+ return array.some((a, i) => predicate(a, asUint32(i)));
1117
+ }
1118
+ case 1: {
1119
+ const [predicate] = args;
1120
+ return (array) => some(array, predicate);
1121
+ }
1122
+ }
1123
+ }
1124
+ Arr.some = some;
1125
+ function foldl(...args) {
1916
1126
  switch (args.length) {
1917
1127
  case 3: {
1918
1128
  const [array, callbackfn, initialValue] = args;
@@ -1920,31 +1130,12 @@ var Arr;
1920
1130
  }
1921
1131
  case 2: {
1922
1132
  const [callbackfn, initialValue] = args;
1923
- return (array) => Arr.foldl(array, callbackfn, initialValue);
1133
+ return (array) => foldl(array, callbackfn, initialValue);
1924
1134
  }
1925
1135
  }
1926
- };
1927
- /**
1928
- * Applies a function against an accumulator and each element in the array (from right to left) to reduce it to a single value.
1929
- * This is an alias for `Array.prototype.reduceRight`.
1930
- * @template E The type of elements in the array.
1931
- * @template S The type of the accumulated value.
1932
- * @param array The input array.
1933
- * @param callbackfn A function to execute on each element in the array: `(previousValue: S, currentValue: A, currentIndex: SizeType.Arr) => S`.
1934
- * @param initialValue The initial value of the accumulator.
1935
- * @returns The single value that results from the reduction.
1936
- * @example
1937
- * ```ts
1938
- * // Regular usage
1939
- * Arr.foldr([1, 2, 3], (sum, n) => sum + n, 0); // 6
1940
- *
1941
- * // Curried usage for pipe composition
1942
- * const concatRight = Arr.foldr((acc: string, curr: string) => curr + acc, '');
1943
- * const result = pipe(['a', 'b', 'c']).map(concatRight).value;
1944
- * console.log(result); // "abc"
1945
- * ```
1946
- */
1947
- Arr.foldr = (...args) => {
1136
+ }
1137
+ Arr.foldl = foldl;
1138
+ function foldr(...args) {
1948
1139
  switch (args.length) {
1949
1140
  case 3: {
1950
1141
  const [array, callbackfn, initialValue] = args;
@@ -1952,124 +1143,40 @@ var Arr;
1952
1143
  }
1953
1144
  case 2: {
1954
1145
  const [callbackfn, initialValue] = args;
1955
- return (array) => Arr.foldr(array, callbackfn, initialValue);
1146
+ return (array) => foldr(array, callbackfn, initialValue);
1956
1147
  }
1957
1148
  }
1958
- };
1959
- /**
1960
- * Finds the minimum value in an array.
1961
- * @template E The type of numbers in the array (must extend `number`).
1962
- * @param array The input array.
1963
- * @param comparator An optional custom comparator function `(x: N, y: N) => number`. Should return < 0 if x is smaller, 0 if equal, > 0 if x is larger. Defaults to `x - y`.
1964
- * @returns The minimum value in the array wrapped in Optional.
1965
- * @example
1966
- * ```ts
1967
- * Arr.min([3, 1, 4, 1, 5] as const); // Optional.some(1)
1968
- * Arr.min([{v:3}, {v:1}], (a,b) => a.v - b.v) // Optional.some({v:1})
1969
- * Arr.min([]); // Optional.none
1970
- * ```
1971
- */
1972
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1973
- Arr.min = ((array, comparator) => {
1149
+ }
1150
+ Arr.foldr = foldr;
1151
+ function min(array, comparator) {
1974
1152
  if (!Arr.isNonEmpty(array)) {
1975
1153
  return Optional.none;
1976
1154
  }
1977
1155
  const cmp = comparator ?? ((x, y) => Num.from(x) - Num.from(y));
1978
1156
  return Optional.some(array.reduce((currentMin, curr) => (cmp(curr, currentMin) < 0 ? curr : currentMin), array[0]));
1979
- });
1980
- /**
1981
- * Finds the maximum value in an array.
1982
- *
1983
- * - If the array is non-empty, returns the maximum value.
1984
- * - If the array is empty, returns `Optional.none`.
1985
- * - You can provide a custom comparator for arbitrary types.
1986
- *
1987
- * @template E The type of elements in the array.
1988
- * @param array The input array.
1989
- * @param comparator An optional custom comparator function `(x: A, y: A) => number`. Should return < 0 if x is smaller, 0 if equal, > 0 if x is larger. Defaults to numeric comparison.
1990
- * @returns The maximum value in the array wrapped in Optional.
1991
- * @example
1992
- * ```ts
1993
- * Arr.max([3, 1, 4, 1, 5] as const); // Optional.some(5)
1994
- * Arr.max([{v:3}, {v:1}], (a,b) => a.v - b.v) // Optional.some({v:3})
1995
- * Arr.max([]); // Optional.none
1996
- * ```
1997
- */
1998
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1999
- Arr.max = ((array, comparator) => {
1157
+ }
1158
+ Arr.min = min;
1159
+ function max(array, comparator) {
2000
1160
  const cmp = comparator ?? ((x, y) => Num.from(x) - Num.from(y));
2001
1161
  // Find max by finding min with an inverted comparator
2002
- return Arr.min(array, (x, y) => -cmp(x, y));
2003
- });
2004
- /**
2005
- * Finds the element with the minimum value according to a mapped numeric value.
2006
- *
2007
- * - If the array is non-empty, returns the element with the minimum mapped value.
2008
- * - If the array is empty, returns `Optional.none`.
2009
- * - You can provide a custom comparator for the mapped values.
2010
- *
2011
- * @template E The type of elements in the array.
2012
- * @template V The type of the value to compare by.
2013
- * @param array The input array.
2014
- * @param comparatorValueMapper A function that maps an element to a value for comparison.
2015
- * @param comparator An optional custom comparator function for the mapped values.
2016
- * @returns The element with the minimum mapped value wrapped in Optional.
2017
- * @example
2018
- * ```ts
2019
- * const people = [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 20 }] as const;
2020
- * Arr.minBy(people, p => p.age); // Optional.some({ name: 'Bob', age: 20 })
2021
- * Arr.minBy([], p => p.age); // Optional.none
2022
- * ```
2023
- */
2024
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
2025
- Arr.minBy = ((array, comparatorValueMapper, comparator) => Arr.min(array, (x, y) => comparator === undefined
2026
- ? Num.from(comparatorValueMapper(x)) -
2027
- Num.from(comparatorValueMapper(y))
2028
- : comparator(comparatorValueMapper(x), comparatorValueMapper(y))));
2029
- /**
2030
- * Finds the element with the maximum value according to a mapped numeric value.
2031
- *
2032
- * - If the array is non-empty, returns the element with the maximum mapped value.
2033
- * - If the array is empty, returns `Optional.none`.
2034
- * - You can provide a custom comparator for the mapped values.
2035
- *
2036
- * @template E The type of elements in the array.
2037
- * @template V The type of the value to compare by.
2038
- * @param array The input array.
2039
- * @param comparatorValueMapper A function that maps an element to a value for comparison.
2040
- * @param comparator An optional custom comparator function for the mapped values.
2041
- * @returns The element with the maximum mapped value wrapped in Optional.
2042
- * @example
2043
- * ```ts
2044
- * const people = [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 20 }] as const;
2045
- * Arr.maxBy(people, p => p.age); // Optional.some({ name: 'Alice', age: 30 })
2046
- * Arr.maxBy([], p => p.age); // Optional.none
2047
- * ```
2048
- */
2049
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
2050
- Arr.maxBy = ((array, comparatorValueMapper, comparator) => Arr.max(array, (x, y) => comparator === undefined
2051
- ? Num.from(comparatorValueMapper(x)) -
2052
- Num.from(comparatorValueMapper(y))
2053
- : comparator(comparatorValueMapper(x), comparatorValueMapper(y))));
2054
- /**
2055
- * Counts the number of elements in an array that satisfy a predicate.
2056
- * @template E The type of elements in the array.
2057
- * @param array The input array.
2058
- * @param predicate A function `(value: A, index: number) => boolean` to test each element for a condition.
2059
- * @returns The number of elements that satisfy the predicate.
2060
- * @example
2061
- * ```ts
2062
- * // Regular usage
2063
- * Arr.count([1, 2, 3, 4], (x) => x > 2); // 2
2064
- *
2065
- * // Curried usage for pipe composition
2066
- * const countEvens = Arr.count((x: number) => x % 2 === 0);
2067
- * const result = pipe([1, 2, 3, 4, 5, 6]).map(countEvens).value;
2068
- * console.log(result); // 3
2069
- * ```
2070
- */
2071
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
2072
- Arr.count = ((...args) => {
1162
+ return min(array, (x, y) => -cmp(x, y));
1163
+ }
1164
+ Arr.max = max;
1165
+ function minBy(array, comparatorValueMapper, comparator) {
1166
+ return min(array, (x, y) => comparator === undefined
1167
+ ? Num.from(comparatorValueMapper(x)) -
1168
+ Num.from(comparatorValueMapper(y))
1169
+ : comparator(comparatorValueMapper(x), comparatorValueMapper(y)));
1170
+ }
1171
+ Arr.minBy = minBy;
1172
+ function maxBy(array, comparatorValueMapper, comparator) {
1173
+ return max(array, (x, y) => comparator === undefined
1174
+ ? Num.from(comparatorValueMapper(x)) -
1175
+ Num.from(comparatorValueMapper(y))
1176
+ : comparator(comparatorValueMapper(x), comparatorValueMapper(y)));
1177
+ }
1178
+ Arr.maxBy = maxBy;
1179
+ function count(...args) {
2073
1180
  switch (args.length) {
2074
1181
  case 2: {
2075
1182
  const [array, predicate] = args;
@@ -2077,32 +1184,12 @@ var Arr;
2077
1184
  }
2078
1185
  case 1: {
2079
1186
  const [predicate] = args;
2080
- return (array) => Arr.count(array, predicate);
1187
+ return (array) => count(array, predicate);
2081
1188
  }
2082
1189
  }
2083
- });
2084
- /**
2085
- * Groups elements of an array by a key derived from each element and counts the elements in each group.
2086
- * @template E The type of elements in the array.
2087
- * @template G The type of the group key (must be a primitive type: `string`, `number`, `boolean`, `symbol`, `bigint`, `null`, or `undefined`).
2088
- * @param array The input array.
2089
- * @param grouper A function `(value: A, index: number) => G` that maps an element and its index to a group key.
2090
- * @returns An `IMap` where keys are group keys and values are the counts of elements in each group.
2091
- * @example
2092
- * ```ts
2093
- * // Regular usage
2094
- * Arr.countBy([1, 2, 2, 3, 1, 1], (x) => x);
2095
- * // IMap { 1 => 3, 2 => 2, 3 => 1 }
2096
- *
2097
- * // Curried usage for pipe composition
2098
- * const countByType = Arr.countBy((x: {type: string}) => x.type);
2099
- * const data = [{type: 'a'}, {type: 'b'}, {type: 'a'}];
2100
- * const result = pipe(data).map(countByType).value;
2101
- * // IMap { 'a' => 2, 'b' => 1 }
2102
- * ```
2103
- */
2104
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
2105
- Arr.countBy = ((...args) => {
1190
+ }
1191
+ Arr.count = count;
1192
+ function countBy(...args) {
2106
1193
  switch (args.length) {
2107
1194
  case 2: {
2108
1195
  const [array, grouper] = args;
@@ -2116,45 +1203,16 @@ var Arr;
2116
1203
  }
2117
1204
  case 1: {
2118
1205
  const [grouper] = args;
2119
- return (array) => Arr.countBy(array, grouper);
1206
+ return (array) => countBy(array, grouper);
2120
1207
  }
2121
1208
  }
2122
- });
2123
- /**
2124
- * Calculates the sum of numbers in an array.
2125
- * @param array The input array of numbers.
2126
- * @returns The sum of the numbers. Returns 0 for an empty array.
2127
- * @example
2128
- * ```ts
2129
- * Arr.sum([1, 2, 3]); // 6
2130
- * Arr.sum([]); // 0
2131
- * Arr.sum([-1, 0, 1]); // 0
2132
- * ```
2133
- */
2134
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
2135
- Arr.sum = ((array) => array.reduce((prev, curr) => prev + curr, 0));
2136
- /**
2137
- * Joins array elements into a string.
2138
- * @param array The array to join.
2139
- * @param separator The separator string.
2140
- * @returns Result.Ok with the joined string, Result.Err if the operation throws.
2141
- * @example
2142
- * ```typescript
2143
- * // Regular usage
2144
- * const arr = ['Hello', 'World'];
2145
- * const result = Arr.join(arr, ' ');
2146
- * if (Result.isOk(result)) {
2147
- * console.log(result.value); // "Hello World"
2148
- * }
2149
- *
2150
- * // Curried usage for pipe composition
2151
- * const joinWithComma = Arr.join(',');
2152
- * const result2 = pipe(['a', 'b', 'c']).map(joinWithComma).value;
2153
- * console.log(Result.unwrapOr(result2, '')); // "a,b,c"
2154
- * ```
2155
- */
2156
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
2157
- Arr.join = ((...args) => {
1209
+ }
1210
+ Arr.countBy = countBy;
1211
+ function sum(array) {
1212
+ return array.reduce((prev, curr) => prev + curr, 0);
1213
+ }
1214
+ Arr.sum = sum;
1215
+ function join(...args) {
2158
1216
  switch (args.length) {
2159
1217
  case 0:
2160
1218
  return (array) => joinImpl(array, undefined);
@@ -2170,7 +1228,8 @@ var Arr;
2170
1228
  return joinImpl(array, separator);
2171
1229
  }
2172
1230
  }
2173
- });
1231
+ }
1232
+ Arr.join = join;
2174
1233
  const joinImpl = (array, separator) => {
2175
1234
  try {
2176
1235
  const result = array.join(separator);
@@ -2207,26 +1266,34 @@ var Arr;
2207
1266
  // Non-null assertion is safe here because `i` is always within bounds of both arrays up to the length of the shorter one.
2208
1267
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
2209
1268
  tp(array1[i], array2[i]));
2210
- /**
2211
- * Filters an array by excluding elements for which the predicate returns true.
2212
- * This is the opposite of `Array.prototype.filter`.
2213
- * @template E The type of elements in the array.
2214
- * @param array The input array.
2215
- * @param predicate A function `(a: A, index: number) => boolean` that returns `true` for elements to be excluded.
2216
- * @returns A new array with elements for which the predicate returned `false`.
2217
- * @example
2218
- * ```ts
2219
- * // Regular usage
2220
- * Arr.filterNot([1, 2, 3, 4], (x) => x % 2 === 0); // [1, 3] (excludes even numbers)
2221
- *
2222
- * // Curried usage for pipe composition
2223
- * const excludeEvens = Arr.filterNot((x: number) => x % 2 === 0);
2224
- * const result = pipe([1, 2, 3, 4, 5, 6]).map(excludeEvens).value;
2225
- * console.log(result); // [1, 3, 5]
2226
- * ```
2227
- */
2228
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
2229
- Arr.filterNot = ((...args) => {
1269
+ function map(...args) {
1270
+ switch (args.length) {
1271
+ case 2: {
1272
+ const [array, mapFn] = args;
1273
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1274
+ return array.map(mapFn);
1275
+ }
1276
+ case 1: {
1277
+ const [mapFn] = args;
1278
+ return (array) => map(array, mapFn);
1279
+ }
1280
+ }
1281
+ }
1282
+ Arr.map = map;
1283
+ function filter(...args) {
1284
+ switch (args.length) {
1285
+ case 2: {
1286
+ const [array, predicate] = args;
1287
+ return array.filter((a, i) => predicate(a, asUint32(i)));
1288
+ }
1289
+ case 1: {
1290
+ const [predicate] = args;
1291
+ return (array) => filter(array, predicate);
1292
+ }
1293
+ }
1294
+ }
1295
+ Arr.filter = filter;
1296
+ function filterNot(...args) {
2230
1297
  switch (args.length) {
2231
1298
  case 2: {
2232
1299
  const [array, predicate] = args;
@@ -2234,10 +1301,48 @@ var Arr;
2234
1301
  }
2235
1302
  case 1: {
2236
1303
  const [predicate] = args;
2237
- return (array) => Arr.filterNot(array, predicate);
1304
+ return (array) => filterNot(array, predicate);
1305
+ }
1306
+ }
1307
+ }
1308
+ Arr.filterNot = filterNot;
1309
+ function flat(...args) {
1310
+ switch (args.length) {
1311
+ case 2: {
1312
+ const [array, depth] = args;
1313
+ return array.flat(depth);
1314
+ }
1315
+ case 1: {
1316
+ const [arrayOrDepth] = args;
1317
+ if (typeof arrayOrDepth === 'number') {
1318
+ const depth = arrayOrDepth;
1319
+ return (array) => flat(array, depth);
1320
+ }
1321
+ else if (arrayOrDepth === undefined) {
1322
+ return (array) => flat(array, 1);
1323
+ }
1324
+ else {
1325
+ return arrayOrDepth.flat(1);
1326
+ }
1327
+ }
1328
+ case 0:
1329
+ return (array) => flat(array, 1);
1330
+ }
1331
+ }
1332
+ Arr.flat = flat;
1333
+ function flatMap(...args) {
1334
+ switch (args.length) {
1335
+ case 2: {
1336
+ const [array, mapFn] = args;
1337
+ return array.flatMap((a, i) => mapFn(a, asUint32(i)));
1338
+ }
1339
+ case 1: {
1340
+ const [mapFn] = args;
1341
+ return (array) => flatMap(array, mapFn);
2238
1342
  }
2239
1343
  }
2240
- });
1344
+ }
1345
+ Arr.flatMap = flatMap;
2241
1346
  /**
2242
1347
  * Concatenates two arrays.
2243
1348
  * @template E1 The type of the first array (can be a tuple).
@@ -2253,23 +1358,7 @@ var Arr;
2253
1358
  * ```
2254
1359
  */
2255
1360
  Arr.concat = (array1, array2) => [...array1, ...array2];
2256
- /**
2257
- * Partitions an array into sub-arrays of a specified size.
2258
- * The last partition may be smaller if the array length is not a multiple of `chunkSize`.
2259
- * Returns an empty array if chunkSize < 2.
2260
- * @template N The size of each partition (must be a number type, typically a literal for precise typing).
2261
- * @template E The type of elements in the array.
2262
- * @param array The input array.
2263
- * @param chunkSize The size of each partition.
2264
- * @returns An array of arrays, where each inner array has up to `chunkSize` elements.
2265
- * @example
2266
- * ```ts
2267
- * Arr.partition([1, 2, 3, 4, 5, 6], 2); // [[1, 2], [3, 4], [5, 6]]
2268
- * Arr.partition([1, 2, 3, 4, 5, 6, 7], 3); // [[1, 2, 3], [4, 5, 6], [7]]
2269
- * ```
2270
- */
2271
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
2272
- Arr.partition = ((...args) => {
1361
+ function partition(...args) {
2273
1362
  switch (args.length) {
2274
1363
  case 2: {
2275
1364
  const [array, chunkSize] = args;
@@ -2279,10 +1368,43 @@ var Arr;
2279
1368
  }
2280
1369
  case 1: {
2281
1370
  const [chunkSize] = args;
2282
- return (array) => Arr.partition(array, chunkSize);
1371
+ return (array) => partition(array, chunkSize);
2283
1372
  }
2284
1373
  }
2285
- });
1374
+ }
1375
+ Arr.partition = partition;
1376
+ /**
1377
+ * Reverses a tuple, preserving element types in their new positions.
1378
+ *
1379
+ * The type system precisely tracks the reversal, so the returned tuple
1380
+ * has its element types in the exact reverse order. This is more precise
1381
+ * than array reversal which loses positional type information.
1382
+ *
1383
+ * @template T - The tuple type to reverse
1384
+ * @param array - The input tuple
1385
+ * @returns A new tuple with elements in reverse order and precise typing
1386
+ *
1387
+ * @example
1388
+ * ```typescript
1389
+ * // Basic reversal
1390
+ * const nums = [1, 2, 3] as const;
1391
+ * const reversed = Arr.toReversed(nums); // readonly [3, 2, 1]
1392
+ *
1393
+ * // Mixed types preserved in reverse positions
1394
+ * const mixed = [1, 'hello', true, null] as const;
1395
+ * const revMixed = Arr.toReversed(mixed);
1396
+ * // readonly [null, true, 'hello', 1]
1397
+ *
1398
+ * // Empty and single-element tuples
1399
+ * const empty = [] as const;
1400
+ * const revEmpty = Arr.toReversed(empty); // readonly []
1401
+ * const single = [42] as const;
1402
+ * const revSingle = Arr.toReversed(single); // readonly [42]
1403
+ * ```
1404
+ */
1405
+ Arr.toReversed = (array) =>
1406
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1407
+ array.toReversed();
2286
1408
  /**
2287
1409
  * Sorts an array by a value derived from its elements, using a numeric mapping.
2288
1410
  * @template E The type of elements in the array.
@@ -2299,172 +1421,25 @@ var Arr;
2299
1421
  * // [{ name: 'Adam', score: 90 }, { name: 'Bob', score: 80 }, { name: 'Eve', score: 70 }]
2300
1422
  * ```
2301
1423
  */
2302
- Arr.toSortedBy = (array, comparatorValueMapper, comparator) => array.toSorted((x, y) => comparator === undefined
2303
- ? // This branch assumes B is number if comparator is undefined.
2304
- // The overloads should handle this, but explicit cast might be needed if B is not number.
2305
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
2306
- comparatorValueMapper(x) -
2307
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
2308
- comparatorValueMapper(y)
2309
- : comparator(comparatorValueMapper(x), comparatorValueMapper(y)));
2310
- /**
2311
- * Returns an array of successively reduced values from an array, starting with an initial value.
2312
- *
2313
- * This function creates a \"running tally\" by applying a reducer function to each element and
2314
- * accumulating the results. Unlike {@link reduce} which returns a single final value, `scan`
2315
- * returns all intermediate accumulated values, providing visibility into the reduction process.
2316
- *
2317
- * **Key Differences from Reduce:**
2318
- * - {@link reduce}: `[1, 2, 3] -> 6` (final sum only)
2319
- * - `scan`: `[1, 2, 3] -> [0, 1, 3, 6]` (all intermediate sums including initial value)
2320
- *
2321
- * **Guaranteed Non-Empty Return:** The result is always a {@link NonEmptyArray}<S> because it includes
2322
- * the initial value as the first element, even for empty input arrays. This provides type safety
2323
- * and eliminates the need for empty array checks.
2324
- *
2325
- * **Array Length Relationship:** `result.length === array.length + 1` (includes initial value)
2326
- *
2327
- * **Curried Usage:** Supports currying for functional composition - when called with only the reducer
2328
- * and initial value, returns a reusable function that can be applied to arrays.
2329
- *
2330
- * @template E The type of elements in the input array.
2331
- * @template S The type of the accumulated values and the initial value.
2332
- * @param array The input array to scan over. Can be empty (result will still contain the initial value).
2333
- * @param reducer A function `(accumulator: S, currentValue: E, currentIndex: SizeType.Arr) => S` that:
2334
- * - **accumulator:** The current accumulated value (starts with `init`, then previous results)
2335
- * - **currentValue:** The current array element being processed
2336
- * - **currentIndex:** The 0-based index of the current element (typed as {@link SizeType.Arr})
2337
- * - **returns:** The new accumulated value to include in the result array
2338
- * @param init The initial accumulated value. Becomes the first element of the result array.
2339
- * @returns A {@link NonEmptyArray}<S> of accumulated values with length `array.length + 1`:
2340
- * - `result[0]` is always the `init` value
2341
- * - `result[i+1]` is the result of applying the reducer to `result[i]` and `array[i]`
2342
- * - Guaranteed to be non-empty regardless of input array length
2343
- *
2344
- * @example
2345
- * ```typescript
2346
- * // Basic running sum example
2347
- * const numbers = [1, 2, 3, 4];
2348
- * const runningSum = Arr.scan(numbers, (acc, curr) => acc + curr, 0);
2349
- * // NonEmptyArray<number> -> [0, 1, 3, 6, 10]
2350
- * // ^ ^ ^ ^ ^
2351
- * // | | | | └─ 0+1+2+3+4 = 10
2352
- * // | | | └─ 0+1+2+3 = 6
2353
- * // | | └─ 0+1+2 = 3
2354
- * // | └─ 0+1 = 1
2355
- * // └─ init = 0
2356
- *
2357
- * // Difference from reduce
2358
- * const reduced = numbers.reduce((acc, curr) => acc + curr, 0); // 10 (final only)
2359
- * const scanned = Arr.scan(numbers, (acc, curr) => acc + curr, 0); // [0, 1, 3, 6, 10] (all steps)
2360
- *
2361
- * // Running product
2362
- * const factorial = Arr.scan([1, 2, 3, 4, 5], (acc, curr) => acc * curr, 1);
2363
- * // [1, 1, 2, 6, 24, 120] - factorial sequence
2364
- *
2365
- * // Running maximum
2366
- * const temperatures = [20, 25, 18, 30, 22];
2367
- * const runningMax = Arr.scan(temperatures, (max, temp) => Math.max(max, temp), -Infinity);
2368
- * // [-Infinity, 20, 25, 25, 30, 30]
2369
- *
2370
- * // Building strings incrementally
2371
- * const words = ['Hello', 'beautiful', 'world'];
2372
- * const sentences = Arr.scan(words, (sentence, word) => sentence + ' ' + word, '');
2373
- * // ['', ' Hello', ' Hello beautiful', ' Hello beautiful world']
2374
- *
2375
- * // Array accumulation (collecting elements)
2376
- * const items = ['a', 'b', 'c'];
2377
- * const growing = Arr.scan(items, (acc, item) => [...acc, item], [] as string[]);
2378
- * // [[], ['a'], ['a', 'b'], ['a', 'b', 'c']]
2379
- *
2380
- * // Financial running balance
2381
- * const transactions = [100, -20, 50, -30];
2382
- * const balances = Arr.scan(transactions, (balance, transaction) => balance + transaction, 1000);
2383
- * // [1000, 1100, 1080, 1130, 1100] - account balance after each transaction
2384
- *
2385
- * // Using index information
2386
- * const letters = ['a', 'b', 'c'];
2387
- * const indexed = Arr.scan(letters, (acc, letter, index) => acc + `${index}:${letter} `, '');
2388
- * // ['', '0:a ', '0:a 1:b ', '0:a 1:b 2:c ']
2389
- *
2390
- * // Edge cases
2391
- * const emptyArray: number[] = [];
2392
- * const emptyResult = Arr.scan(emptyArray, (acc, curr) => acc + curr, 42);
2393
- * // [42] - NonEmptyArray even for empty input
2394
- *
2395
- * const singleElement = Arr.scan([5], (acc, curr) => acc * curr, 2);
2396
- * // [2, 10] - init value plus one result
2397
- *
2398
- * // Complex object accumulation
2399
- * const sales = [
2400
- * { product: 'A', amount: 100 },
2401
- * { product: 'B', amount: 200 },
2402
- * { product: 'A', amount: 150 }
2403
- * ];
2404
- *
2405
- * const runningSales = Arr.scan(sales, (totals, sale) => ({
2406
- * ...totals,
2407
- * [sale.product]: (totals[sale.product] || 0) + sale.amount
2408
- * }), {} as Record<string, number>);
2409
- * // [
2410
- * // {},
2411
- * // { A: 100 },
2412
- * // { A: 100, B: 200 },
2413
- * // { A: 250, B: 200 }
2414
- * // ]
2415
- *
2416
- * // Curried usage for functional composition
2417
- * const runningSumFn = Arr.scan((acc: number, curr: number) => acc + curr, 0);
2418
- * const runningProductFn = Arr.scan((acc: number, curr: number) => acc * curr, 1);
2419
- * const collectingFn = Arr.scan((acc: string[], curr: string) => [...acc, curr], [] as string[]);
2420
- *
2421
- * const datasets = [[1, 2, 3], [4, 5], [6, 7, 8, 9]];
2422
- * const allSums = datasets.map(runningSumFn);
2423
- * // [
2424
- * // [0, 1, 3, 6],
2425
- * // [0, 4, 9],
2426
- * // [0, 6, 13, 21, 30]
2427
- * // ]
2428
- *
2429
- * // Pipe composition for data analysis
2430
- * const analysisResult = pipe([10, 20, 30, 40])
2431
- * .map(runningSumFn)
2432
- * .map(sums => sums.slice(1)) // Remove initial value to get pure running sums
2433
- * .map(sums => sums.map((sum, i) => ({ step: i + 1, total: sum })))
2434
- * .value;
2435
- * // [{ step: 1, total: 10 }, { step: 2, total: 30 }, { step: 3, total: 60 }, { step: 4, total: 100 }]
2436
- *
2437
- * // Advanced: State machine simulation
2438
- * type State = 'idle' | 'loading' | 'success' | 'error';
2439
- * type Event = 'start' | 'complete' | 'fail' | 'reset';
2440
- *
2441
- * const events: Event[] = ['start', 'complete', 'reset', 'start', 'fail'];
2442
- * const stateTransition = (state: State, event: Event): State => {
2443
- * switch (state) {
2444
- * case 'idle': return event === 'start' ? 'loading' : state;
2445
- * case 'loading': return event === 'complete' ? 'success' : event === 'fail' ? 'error' : state;
2446
- * case 'success': return event === 'reset' ? 'idle' : state;
2447
- * case 'error': return event === 'reset' ? 'idle' : state;
2448
- * }
2449
- * };
2450
- *
2451
- * const stateHistory = Arr.scan(events, stateTransition, 'idle' as State);
2452
- * // ['idle', 'loading', 'success', 'idle', 'loading', 'error']
2453
- *
2454
- * // Type inference examples
2455
- * expectType<typeof runningSum, NonEmptyArray<number>>('=');
2456
- * expectType<typeof emptyResult, NonEmptyArray<number>>('=');
2457
- * expectType<typeof runningSumFn, <T extends readonly number[]>(array: T) => NonEmptyArray<number>>('=');
2458
- * expectType<typeof stateHistory, NonEmptyArray<State>>('=');
2459
- * ```
2460
- *
2461
- * @see {@link reduce} for getting only the final accumulated value
2462
- * @see {@link NonEmptyArray} for understanding the guaranteed non-empty return type
2463
- * @see {@link SizeType.Arr} for the index parameter type
2464
- * @see Array.prototype.reduce for the standard reduce function
2465
- */
1424
+ Arr.toSorted = (...[array, comparator]) =>
1425
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1426
+ array.toSorted(
2466
1427
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
2467
- Arr.scan = ((...args) => {
1428
+ comparator ??
1429
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1430
+ ((x, y) => x - y));
1431
+ function toSortedBy(array, comparatorValueMapper, comparator) {
1432
+ return array.toSorted((x, y) => comparator === undefined
1433
+ ? // This branch assumes V is number if comparator is undefined.
1434
+ // The overloads should handle this, but explicit cast might be needed if V is not number.
1435
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1436
+ comparatorValueMapper(x) -
1437
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1438
+ comparatorValueMapper(y)
1439
+ : comparator(comparatorValueMapper(x), comparatorValueMapper(y)));
1440
+ }
1441
+ Arr.toSortedBy = toSortedBy;
1442
+ function scan(...args) {
2468
1443
  switch (args.length) {
2469
1444
  case 3: {
2470
1445
  const [array, reducer, init] = args;
@@ -2478,161 +1453,12 @@ var Arr;
2478
1453
  }
2479
1454
  case 2: {
2480
1455
  const [reducer, init] = args;
2481
- return (array) => Arr.scan(array, reducer, init);
1456
+ return (array) => scan(array, reducer, init);
2482
1457
  }
2483
1458
  }
2484
- });
2485
- /**
2486
- * Groups elements of an array by a key derived from each element, returning an immutable {@link IMap}.
2487
- *
2488
- * This function categorizes array elements into groups based on a computed key, using the efficient
2489
- * {@link IMap} data structure for the result. The grouper function receives both the element and its
2490
- * index, enabling flexible grouping strategies.
2491
- *
2492
- * **MapSetKeyType Constraint:** The group key type `G` must extend {@link MapSetKeyType}, which includes
2493
- * primitive types that can be used as Map keys (string, number, boolean, symbol, null, undefined).
2494
- * This constraint ensures type safety and efficient key-based operations.
2495
- *
2496
- * **IMap Return Type:** Returns an {@link IMap}<G, readonly E[]> where:
2497
- * - Keys are the computed group identifiers of type `G`
2498
- * - Values are immutable arrays containing all elements that belong to each group
2499
- * - Preserves insertion order of first occurrence of each group
2500
- * - Maintains type safety with precise generic types
2501
- *
2502
- * **Curried Usage:** Supports currying for functional composition - when called with only the grouper
2503
- * function, returns a reusable function that can be applied to arrays.
2504
- *
2505
- * @template E The type of elements in the input array.
2506
- * @template G The type of the group key, constrained to {@link MapSetKeyType} (primitives usable as Map keys).
2507
- * Must be one of: `string | number | boolean | symbol | null | undefined`
2508
- * @param array The input array to group. Can be empty (returns empty {@link IMap}).
2509
- * @param grouper A function `(value: E, index: SizeType.Arr) => G` that computes the group key for each element.
2510
- * - **value:** The current array element
2511
- * - **index:** The 0-based index of the element (typed as {@link SizeType.Arr})
2512
- * - **returns:** The group key (must be {@link MapSetKeyType})
2513
- * @returns An {@link IMap}<G, readonly E[]> where:
2514
- * - Keys are unique group identifiers computed by the grouper function
2515
- * - Values are immutable arrays of elements belonging to each group
2516
- * - Empty groups are not included (only groups with at least one element)
2517
- * - Insertion order is preserved based on first occurrence of each group key
2518
- *
2519
- * @example
2520
- * ```typescript
2521
- * // Basic grouping by object property
2522
- * const products = [
2523
- * { type: 'fruit', name: 'apple', price: 1.2 },
2524
- * { type: 'vegetable', name: 'carrot', price: 0.8 },
2525
- * { type: 'fruit', name: 'banana', price: 0.9 },
2526
- * { type: 'vegetable', name: 'broccoli', price: 2.1 },
2527
- * { type: 'fruit', name: 'orange', price: 1.5 }
2528
- * ];
2529
- *
2530
- * const byType = Arr.groupBy(products, item => item.type);
2531
- * // IMap<string, readonly Product[]> {
2532
- * // 'fruit' => [
2533
- * // { type: 'fruit', name: 'apple', price: 1.2 },
2534
- * // { type: 'fruit', name: 'banana', price: 0.9 },
2535
- * // { type: 'fruit', name: 'orange', price: 1.5 }
2536
- * // ],
2537
- * // 'vegetable' => [
2538
- * // { type: 'vegetable', name: 'carrot', price: 0.8 },
2539
- * // { type: 'vegetable', name: 'broccoli', price: 2.1 }
2540
- * // ]
2541
- * // }
2542
- *
2543
- * // Access grouped results with IMap methods
2544
- * const fruits = IMap.get(byType, 'fruit'); // Optional<readonly Product[]>
2545
- * const fruitCount = Optional.map(fruits, arr => arr.length); // Optional<number>
2546
- * const fruitNames = Optional.map(fruits, arr => arr.map(p => p.name)); // Optional<string[]>
2547
- *
2548
- * // Grouping by computed values
2549
- * const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
2550
- * const byParity = Arr.groupBy(numbers, n => n % 2 === 0 ? 'even' : 'odd');
2551
- * // IMap<string, readonly number[]> {
2552
- * // 'odd' => [1, 3, 5, 7, 9],
2553
- * // 'even' => [2, 4, 6, 8, 10]
2554
- * // }
2555
- *
2556
- * // Grouping by price ranges using index information
2557
- * const byPriceRange = Arr.groupBy(products, (product, index) => {
2558
- * const category = product.price < 1.0 ? 'cheap' :
2559
- * product.price < 2.0 ? 'moderate' : 'expensive';
2560
- * return `${category}_${index < 2 ? 'early' : 'late'}`;
2561
- * });
2562
- *
2563
- * // MapSetKeyType constraint examples (valid key types)
2564
- * const byStringKey = Arr.groupBy([1, 2, 3], n => `group_${n}`); // string keys
2565
- * const byNumberKey = Arr.groupBy(['a', 'b', 'c'], (_, i) => i); // number keys
2566
- * const byBooleanKey = Arr.groupBy([1, 2, 3, 4], n => n > 2); // boolean keys
2567
- * const bySymbolKey = Arr.groupBy([1, 2], n => Symbol(n.toString())); // symbol keys
2568
- *
2569
- * // Edge cases
2570
- * const emptyGroup = Arr.groupBy([], x => x); // IMap<never, readonly never[]> (empty)
2571
- * const singleGroup = Arr.groupBy([1, 2, 3], () => 'all'); // All elements in one group
2572
- * const uniqueGroups = Arr.groupBy([1, 2, 3], x => x); // Each element in its own group
2573
- *
2574
- * // Curried usage for functional composition
2575
- * const groupByType = Arr.groupBy((item: { type: string }) => item.type);
2576
- * const groupByLength = Arr.groupBy((str: string) => str.length);
2577
- * const groupByFirstChar = Arr.groupBy((str: string) => str.charAt(0).toLowerCase());
2578
- *
2579
- * const datasets = [
2580
- * [{ type: 'A' }, { type: 'B' }, { type: 'A' }],
2581
- * [{ type: 'C' }, { type: 'A' }],
2582
- * [{ type: 'B' }, { type: 'B' }, { type: 'C' }]
2583
- * ];
2584
- * const allGrouped = datasets.map(groupByType);
2585
- * // Array of IMap instances, each grouped by type
2586
- *
2587
- * // Pipe composition for complex data processing
2588
- * const words = ['apple', 'banana', 'apricot', 'blueberry', 'avocado', 'blackberry'];
2589
- * const processedGroups = pipe(words)
2590
- * .map(groupByFirstChar)
2591
- * .map(groupMap => IMap.map(groupMap, (wordsInGroup, firstLetter) => ({
2592
- * letter: firstLetter,
2593
- * count: wordsInGroup.length,
2594
- * longest: wordsInGroup.reduce((longest, word) =>
2595
- * word.length > longest.length ? word : longest
2596
- * )
2597
- * })))
2598
- * .value;
2599
- * // IMap<string, {letter: string, count: number, longest: string}>
2600
- *
2601
- * // Advanced: Grouping with complex transformations
2602
- * const students = [
2603
- * { name: 'Alice', grade: 85, subject: 'Math' },
2604
- * { name: 'Bob', grade: 92, subject: 'Science' },
2605
- * { name: 'Charlie', grade: 78, subject: 'Math' },
2606
- * { name: 'Diana', grade: 96, subject: 'Science' }
2607
- * ];
2608
- *
2609
- * const byGradeLevel = Arr.groupBy(students, student => {
2610
- * if (student.grade >= 90) return 'A';
2611
- * if (student.grade >= 80) return 'B';
2612
- * return 'C';
2613
- * });
2614
- *
2615
- * // Working with the grouped results
2616
- * const aStudents = Optional.unwrapOr(IMap.get(byGradeLevel, 'A'), []);
2617
- * const averageAGrade = aStudents.length > 0
2618
- * ? aStudents.reduce((sum, s) => sum + s.grade, 0) / aStudents.length
2619
- * : 0;
2620
- *
2621
- * // Type inference examples
2622
- * expectType<typeof byType, IMap<string, readonly typeof products[number][]>>('=');
2623
- * expectType<typeof byParity, IMap<string, readonly number[]>>('=');
2624
- * expectType<typeof groupByType, <T extends {type: string}>(array: readonly T[]) => IMap<string, readonly T[]>>('=');
2625
- * expectType<typeof emptyGroup, IMap<never, readonly never[]>>('=');
2626
- * ```
2627
- *
2628
- * @see {@link IMap} for working with the returned immutable map
2629
- * @see {@link MapSetKeyType} for understanding valid key types
2630
- * @see {@link IMap.get} for safely accessing grouped results
2631
- * @see {@link IMap.map} for transforming grouped data
2632
- * @see {@link Optional} for handling potentially missing groups
2633
- */
2634
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
2635
- Arr.groupBy = ((...args) => {
1459
+ }
1460
+ Arr.scan = scan;
1461
+ function groupBy(...args) {
2636
1462
  switch (args.length) {
2637
1463
  case 2: {
2638
1464
  const [array, grouper] = args;
@@ -2652,10 +1478,11 @@ var Arr;
2652
1478
  }
2653
1479
  case 1: {
2654
1480
  const [grouper] = args;
2655
- return (array) => Arr.groupBy(array, grouper);
1481
+ return (array) => groupBy(array, grouper);
2656
1482
  }
2657
1483
  }
2658
- });
1484
+ }
1485
+ Arr.groupBy = groupBy;
2659
1486
  /**
2660
1487
  * Creates a new array with unique elements from the input array. Order is preserved from the first occurrence.
2661
1488
  * Uses `Set` internally for efficient uniqueness checking.
@@ -2667,7 +1494,9 @@ var Arr;
2667
1494
  * Arr.uniq([1, 2, 2, 3, 1, 4]); // [1, 2, 3, 4]
2668
1495
  * ```
2669
1496
  */
2670
- Arr.uniq = (array) => Array.from(new Set(array));
1497
+ Arr.uniq = (array) =>
1498
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1499
+ Array.from(new Set(array));
2671
1500
  /**
2672
1501
  * Creates a new array with unique elements from the input array, based on the values returned by `mapFn`.
2673
1502
  *
@@ -2689,9 +1518,9 @@ var Arr;
2689
1518
  * Arr.uniqBy(users, user => user.id); // [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
2690
1519
  * ```
2691
1520
  */
2692
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
2693
- Arr.uniqBy = ((array, mapFn) => {
1521
+ Arr.uniqBy = (array, mapFn) => {
2694
1522
  const mut_mappedValues = new Set();
1523
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
2695
1524
  return array.filter((val) => {
2696
1525
  const mappedValue = mapFn(val);
2697
1526
  if (mut_mappedValues.has(mappedValue))
@@ -2699,7 +1528,7 @@ var Arr;
2699
1528
  mut_mappedValues.add(mappedValue);
2700
1529
  return true;
2701
1530
  });
2702
- });
1531
+ };
2703
1532
  // set operations & equality
2704
1533
  /**
2705
1534
  * Checks if two arrays are equal by performing a shallow comparison of their elements.
@@ -2842,6 +1671,95 @@ var Arr;
2842
1671
  }
2843
1672
  return mut_result;
2844
1673
  };
1674
+ // iterators
1675
+ /**
1676
+ * Returns an iterable of key-value pairs for every entry in the array.
1677
+ *
1678
+ * This function returns an array where each element is a tuple containing the index and value.
1679
+ * The indices are branded as `SizeType.Arr` for type safety.
1680
+ *
1681
+ * @template Ar The exact type of the input array.
1682
+ * @param array The array to get entries from.
1683
+ * @returns An array of `[index, value]` pairs.
1684
+ *
1685
+ * @example
1686
+ * ```typescript
1687
+ * // Direct usage
1688
+ * const fruits = ['apple', 'banana', 'cherry'];
1689
+ * const entries = Arr.entries(fruits); // [[0, 'apple'], [1, 'banana'], [2, 'cherry']]
1690
+ *
1691
+ * // Curried usage
1692
+ * const getEntries = Arr.entries;
1693
+ * const result = getEntries(['a', 'b']); // [[0, 'a'], [1, 'b']]
1694
+ *
1695
+ * // With tuples
1696
+ * const tuple = [10, 20, 30] as const;
1697
+ * const tupleEntries = Arr.entries(tuple); // [[0, 10], [1, 20], [2, 30]]
1698
+ * ```
1699
+ */
1700
+ function* entries(array) {
1701
+ for (const [index, value] of array.entries()) {
1702
+ yield [asUint32(index), value];
1703
+ }
1704
+ }
1705
+ Arr.entries = entries;
1706
+ /**
1707
+ * Returns an iterable of values in the array.
1708
+ *
1709
+ * This function is essentially an identity function that returns a copy of the array.
1710
+ * It's included for API completeness and consistency with native Array methods.
1711
+ *
1712
+ * @template Ar The exact type of the input array.
1713
+ * @param array The array to get values from.
1714
+ * @returns A copy of the input array.
1715
+ *
1716
+ * @example
1717
+ * ```typescript
1718
+ * // Direct usage
1719
+ * const numbers = [1, 2, 3];
1720
+ * const values = Arr.values(numbers); // [1, 2, 3]
1721
+ *
1722
+ * // Curried usage
1723
+ * const getValues = Arr.values;
1724
+ * const result = getValues(['a', 'b']); // ['a', 'b']
1725
+ * ```
1726
+ */
1727
+ function* values(array) {
1728
+ for (const value of array.values()) {
1729
+ yield value;
1730
+ }
1731
+ }
1732
+ Arr.values = values;
1733
+ /**
1734
+ * Returns an iterable of keys in the array.
1735
+ *
1736
+ * This function returns an array of branded indices (`SizeType.Arr`) for type safety.
1737
+ *
1738
+ * @template Ar The exact type of the input array.
1739
+ * @param array The array to get indices from.
1740
+ * @returns An array of indices.
1741
+ *
1742
+ * @example
1743
+ * ```typescript
1744
+ * // Direct usage
1745
+ * const fruits = ['apple', 'banana', 'cherry'];
1746
+ * const indices = Arr.indices(fruits); // [0, 1, 2]
1747
+ *
1748
+ * // Curried usage
1749
+ * const getIndices = Arr.indices;
1750
+ * const result = getIndices(['a', 'b']); // [0, 1]
1751
+ *
1752
+ * // Empty array
1753
+ * const empty: string[] = [];
1754
+ * const emptyIndices = Arr.indices(empty); // []
1755
+ * ```
1756
+ */
1757
+ function* indices(array) {
1758
+ for (const key of array.keys()) {
1759
+ yield asUint32(key);
1760
+ }
1761
+ }
1762
+ Arr.indices = indices;
2845
1763
  // aliases
2846
1764
  /**
2847
1765
  * Alias for `head`. Returns the first element of an array.
@@ -2857,22 +1775,37 @@ var Arr;
2857
1775
  * Alias for `skip`. Skips the first N elements of an array.
2858
1776
  * @see {@link skip}
2859
1777
  */
2860
- Arr.drop = Arr.skip;
1778
+ Arr.drop = skip;
2861
1779
  /**
2862
1780
  * Alias for `foldl`. Applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value.
2863
1781
  * @see {@link foldl}
2864
1782
  */
2865
- Arr.reduce = Arr.foldl;
1783
+ Arr.reduce = foldl;
2866
1784
  /**
2867
1785
  * Alias for `foldr`. Applies a function against an accumulator and each element in the array (from right to left) to reduce it to a single value.
2868
1786
  * @see {@link foldr}
2869
1787
  */
2870
- Arr.reduceRight = Arr.foldr;
1788
+ Arr.reduceRight = foldr;
2871
1789
  /**
2872
1790
  * Alias for `partition`. Splits an array into chunks of a specified size.
2873
1791
  * @see {@link partition}
2874
1792
  */
2875
- Arr.chunk = Arr.partition;
1793
+ Arr.chunk = partition;
1794
+ /**
1795
+ * Alias for `create`. Creates a new array of the specified length, with each position filled with the provided initial value.
1796
+ * @see {@link create}
1797
+ */
1798
+ Arr.newArray = Arr.create;
1799
+ /**
1800
+ * Alias for `size`. Returns the length of an array.
1801
+ * @see {@link size}
1802
+ */
1803
+ Arr.length = Arr.size;
1804
+ /**
1805
+ * Alias for `indices`. Returns an iterable of keys in the array.
1806
+ * @see {@link indices}
1807
+ */
1808
+ Arr.keys = indices;
2876
1809
  })(Arr || (Arr = {}));
2877
1810
 
2878
1811
  export { Arr };