ts-data-forge 1.0.0 → 1.0.2

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 (292) hide show
  1. package/README.md +1 -1
  2. package/dist/array/array-utils.d.mts +2617 -0
  3. package/dist/array/array-utils.d.mts.map +1 -0
  4. package/dist/array/array-utils.mjs +2915 -0
  5. package/dist/array/array-utils.mjs.map +1 -0
  6. package/dist/array/index.d.mts +3 -0
  7. package/dist/array/index.d.mts.map +1 -0
  8. package/dist/array/index.mjs +3 -0
  9. package/dist/array/index.mjs.map +1 -0
  10. package/dist/array/tuple-utils.d.mts +421 -0
  11. package/dist/array/tuple-utils.d.mts.map +1 -0
  12. package/dist/array/tuple-utils.mjs +391 -0
  13. package/dist/array/tuple-utils.mjs.map +1 -0
  14. package/dist/collections/imap-mapped.d.mts +445 -0
  15. package/dist/collections/imap-mapped.d.mts.map +1 -0
  16. package/dist/collections/imap-mapped.mjs +424 -0
  17. package/dist/collections/imap-mapped.mjs.map +1 -0
  18. package/dist/collections/imap.d.mts +359 -0
  19. package/dist/collections/imap.d.mts.map +1 -0
  20. package/dist/collections/imap.mjs +338 -0
  21. package/dist/collections/imap.mjs.map +1 -0
  22. package/dist/collections/index.d.mts +7 -0
  23. package/dist/collections/index.d.mts.map +1 -0
  24. package/dist/collections/index.mjs +7 -0
  25. package/dist/collections/index.mjs.map +1 -0
  26. package/dist/collections/iset-mapped.d.mts +576 -0
  27. package/dist/collections/iset-mapped.d.mts.map +1 -0
  28. package/dist/collections/iset-mapped.mjs +522 -0
  29. package/dist/collections/iset-mapped.mjs.map +1 -0
  30. package/dist/collections/iset.d.mts +426 -0
  31. package/dist/collections/iset.d.mts.map +1 -0
  32. package/dist/collections/iset.mjs +437 -0
  33. package/dist/collections/iset.mjs.map +1 -0
  34. package/dist/collections/queue.d.mts +190 -0
  35. package/dist/collections/queue.d.mts.map +1 -0
  36. package/dist/collections/queue.mjs +317 -0
  37. package/dist/collections/queue.mjs.map +1 -0
  38. package/dist/collections/stack.d.mts +210 -0
  39. package/dist/collections/stack.d.mts.map +1 -0
  40. package/dist/collections/stack.mjs +353 -0
  41. package/dist/collections/stack.mjs.map +1 -0
  42. package/dist/expect-type.d.mts +199 -0
  43. package/dist/expect-type.d.mts.map +1 -0
  44. package/dist/expect-type.mjs +201 -0
  45. package/dist/expect-type.mjs.map +1 -0
  46. package/dist/functional/index.d.mts +5 -0
  47. package/dist/functional/index.d.mts.map +1 -0
  48. package/dist/functional/index.mjs +5 -0
  49. package/dist/functional/index.mjs.map +1 -0
  50. package/dist/functional/match.d.mts +215 -0
  51. package/dist/functional/match.d.mts.map +1 -0
  52. package/dist/functional/match.mjs +139 -0
  53. package/dist/functional/match.mjs.map +1 -0
  54. package/dist/functional/optional.d.mts +517 -0
  55. package/dist/functional/optional.d.mts.map +1 -0
  56. package/dist/functional/optional.mjs +532 -0
  57. package/dist/functional/optional.mjs.map +1 -0
  58. package/dist/functional/pipe.d.mts +185 -0
  59. package/dist/functional/pipe.d.mts.map +1 -0
  60. package/dist/functional/pipe.mjs +129 -0
  61. package/dist/functional/pipe.mjs.map +1 -0
  62. package/dist/functional/result.d.mts +796 -0
  63. package/dist/functional/result.d.mts.map +1 -0
  64. package/dist/functional/result.mjs +844 -0
  65. package/dist/functional/result.mjs.map +1 -0
  66. package/dist/globals.d.mts +38 -0
  67. package/dist/guard/has-key.d.mts +100 -0
  68. package/dist/guard/has-key.d.mts.map +1 -0
  69. package/dist/guard/has-key.mjs +94 -0
  70. package/dist/guard/has-key.mjs.map +1 -0
  71. package/dist/guard/index.d.mts +8 -0
  72. package/dist/guard/index.d.mts.map +1 -0
  73. package/dist/guard/index.mjs +8 -0
  74. package/dist/guard/index.mjs.map +1 -0
  75. package/dist/guard/is-non-empty-string.d.mts +106 -0
  76. package/dist/guard/is-non-empty-string.d.mts.map +1 -0
  77. package/dist/guard/is-non-empty-string.mjs +108 -0
  78. package/dist/guard/is-non-empty-string.mjs.map +1 -0
  79. package/dist/guard/is-non-null-object.d.mts +105 -0
  80. package/dist/guard/is-non-null-object.d.mts.map +1 -0
  81. package/dist/guard/is-non-null-object.mjs +108 -0
  82. package/dist/guard/is-non-null-object.mjs.map +1 -0
  83. package/dist/guard/is-primitive.d.mts +146 -0
  84. package/dist/guard/is-primitive.d.mts.map +1 -0
  85. package/dist/guard/is-primitive.mjs +161 -0
  86. package/dist/guard/is-primitive.mjs.map +1 -0
  87. package/dist/guard/is-record.d.mts +151 -0
  88. package/dist/guard/is-record.d.mts.map +1 -0
  89. package/dist/guard/is-record.mjs +155 -0
  90. package/dist/guard/is-record.mjs.map +1 -0
  91. package/dist/guard/is-type.d.mts +430 -0
  92. package/dist/guard/is-type.d.mts.map +1 -0
  93. package/dist/guard/is-type.mjs +432 -0
  94. package/dist/guard/is-type.mjs.map +1 -0
  95. package/dist/guard/key-is-in.d.mts +158 -0
  96. package/dist/guard/key-is-in.d.mts.map +1 -0
  97. package/dist/guard/key-is-in.mjs +160 -0
  98. package/dist/guard/key-is-in.mjs.map +1 -0
  99. package/dist/index.d.mts +11 -0
  100. package/dist/index.d.mts.map +1 -0
  101. package/dist/index.mjs +61 -0
  102. package/dist/index.mjs.map +1 -0
  103. package/dist/iterator/index.d.mts +2 -0
  104. package/dist/iterator/index.d.mts.map +1 -0
  105. package/dist/iterator/index.mjs +2 -0
  106. package/dist/iterator/index.mjs.map +1 -0
  107. package/dist/iterator/range.d.mts +97 -0
  108. package/dist/iterator/range.d.mts.map +1 -0
  109. package/dist/iterator/range.mjs +130 -0
  110. package/dist/iterator/range.mjs.map +1 -0
  111. package/dist/json/index.d.mts +2 -0
  112. package/dist/json/index.d.mts.map +1 -0
  113. package/dist/json/index.mjs +2 -0
  114. package/dist/json/index.mjs.map +1 -0
  115. package/dist/json/json.d.mts +597 -0
  116. package/dist/json/json.d.mts.map +1 -0
  117. package/dist/json/json.mjs +687 -0
  118. package/dist/json/json.mjs.map +1 -0
  119. package/dist/number/branded-types/finite-number.d.mts +291 -0
  120. package/dist/number/branded-types/finite-number.d.mts.map +1 -0
  121. package/dist/number/branded-types/finite-number.mjs +296 -0
  122. package/dist/number/branded-types/finite-number.mjs.map +1 -0
  123. package/dist/number/branded-types/index.d.mts +27 -0
  124. package/dist/number/branded-types/index.d.mts.map +1 -0
  125. package/dist/number/branded-types/index.mjs +27 -0
  126. package/dist/number/branded-types/index.mjs.map +1 -0
  127. package/dist/number/branded-types/int.d.mts +242 -0
  128. package/dist/number/branded-types/int.d.mts.map +1 -0
  129. package/dist/number/branded-types/int.mjs +239 -0
  130. package/dist/number/branded-types/int.mjs.map +1 -0
  131. package/dist/number/branded-types/int16.d.mts +162 -0
  132. package/dist/number/branded-types/int16.d.mts.map +1 -0
  133. package/dist/number/branded-types/int16.mjs +141 -0
  134. package/dist/number/branded-types/int16.mjs.map +1 -0
  135. package/dist/number/branded-types/int32.d.mts +155 -0
  136. package/dist/number/branded-types/int32.d.mts.map +1 -0
  137. package/dist/number/branded-types/int32.mjs +142 -0
  138. package/dist/number/branded-types/int32.mjs.map +1 -0
  139. package/dist/number/branded-types/non-negative-finite-number.d.mts +165 -0
  140. package/dist/number/branded-types/non-negative-finite-number.d.mts.map +1 -0
  141. package/dist/number/branded-types/non-negative-finite-number.mjs +160 -0
  142. package/dist/number/branded-types/non-negative-finite-number.mjs.map +1 -0
  143. package/dist/number/branded-types/non-negative-int16.d.mts +160 -0
  144. package/dist/number/branded-types/non-negative-int16.d.mts.map +1 -0
  145. package/dist/number/branded-types/non-negative-int16.mjs +138 -0
  146. package/dist/number/branded-types/non-negative-int16.mjs.map +1 -0
  147. package/dist/number/branded-types/non-negative-int32.d.mts +156 -0
  148. package/dist/number/branded-types/non-negative-int32.d.mts.map +1 -0
  149. package/dist/number/branded-types/non-negative-int32.mjs +138 -0
  150. package/dist/number/branded-types/non-negative-int32.mjs.map +1 -0
  151. package/dist/number/branded-types/non-zero-finite-number.d.mts +154 -0
  152. package/dist/number/branded-types/non-zero-finite-number.d.mts.map +1 -0
  153. package/dist/number/branded-types/non-zero-finite-number.mjs +160 -0
  154. package/dist/number/branded-types/non-zero-finite-number.mjs.map +1 -0
  155. package/dist/number/branded-types/non-zero-int.d.mts +131 -0
  156. package/dist/number/branded-types/non-zero-int.d.mts.map +1 -0
  157. package/dist/number/branded-types/non-zero-int.mjs +128 -0
  158. package/dist/number/branded-types/non-zero-int.mjs.map +1 -0
  159. package/dist/number/branded-types/non-zero-int16.d.mts +166 -0
  160. package/dist/number/branded-types/non-zero-int16.d.mts.map +1 -0
  161. package/dist/number/branded-types/non-zero-int16.mjs +145 -0
  162. package/dist/number/branded-types/non-zero-int16.mjs.map +1 -0
  163. package/dist/number/branded-types/non-zero-int32.d.mts +158 -0
  164. package/dist/number/branded-types/non-zero-int32.d.mts.map +1 -0
  165. package/dist/number/branded-types/non-zero-int32.mjs +145 -0
  166. package/dist/number/branded-types/non-zero-int32.mjs.map +1 -0
  167. package/dist/number/branded-types/non-zero-safe-int.d.mts +148 -0
  168. package/dist/number/branded-types/non-zero-safe-int.d.mts.map +1 -0
  169. package/dist/number/branded-types/non-zero-safe-int.mjs +145 -0
  170. package/dist/number/branded-types/non-zero-safe-int.mjs.map +1 -0
  171. package/dist/number/branded-types/non-zero-uint16.d.mts +160 -0
  172. package/dist/number/branded-types/non-zero-uint16.d.mts.map +1 -0
  173. package/dist/number/branded-types/non-zero-uint16.mjs +140 -0
  174. package/dist/number/branded-types/non-zero-uint16.mjs.map +1 -0
  175. package/dist/number/branded-types/non-zero-uint32.d.mts +156 -0
  176. package/dist/number/branded-types/non-zero-uint32.d.mts.map +1 -0
  177. package/dist/number/branded-types/non-zero-uint32.mjs +140 -0
  178. package/dist/number/branded-types/non-zero-uint32.mjs.map +1 -0
  179. package/dist/number/branded-types/positive-finite-number.d.mts +171 -0
  180. package/dist/number/branded-types/positive-finite-number.d.mts.map +1 -0
  181. package/dist/number/branded-types/positive-finite-number.mjs +165 -0
  182. package/dist/number/branded-types/positive-finite-number.mjs.map +1 -0
  183. package/dist/number/branded-types/positive-int.d.mts +270 -0
  184. package/dist/number/branded-types/positive-int.d.mts.map +1 -0
  185. package/dist/number/branded-types/positive-int.mjs +257 -0
  186. package/dist/number/branded-types/positive-int.mjs.map +1 -0
  187. package/dist/number/branded-types/positive-int16.d.mts +162 -0
  188. package/dist/number/branded-types/positive-int16.d.mts.map +1 -0
  189. package/dist/number/branded-types/positive-int16.mjs +139 -0
  190. package/dist/number/branded-types/positive-int16.mjs.map +1 -0
  191. package/dist/number/branded-types/positive-int32.d.mts +158 -0
  192. package/dist/number/branded-types/positive-int32.d.mts.map +1 -0
  193. package/dist/number/branded-types/positive-int32.mjs +139 -0
  194. package/dist/number/branded-types/positive-int32.mjs.map +1 -0
  195. package/dist/number/branded-types/positive-safe-int.d.mts +152 -0
  196. package/dist/number/branded-types/positive-safe-int.d.mts.map +1 -0
  197. package/dist/number/branded-types/positive-safe-int.mjs +138 -0
  198. package/dist/number/branded-types/positive-safe-int.mjs.map +1 -0
  199. package/dist/number/branded-types/positive-uint16.d.mts +160 -0
  200. package/dist/number/branded-types/positive-uint16.d.mts.map +1 -0
  201. package/dist/number/branded-types/positive-uint16.mjs +139 -0
  202. package/dist/number/branded-types/positive-uint16.mjs.map +1 -0
  203. package/dist/number/branded-types/positive-uint32.d.mts +156 -0
  204. package/dist/number/branded-types/positive-uint32.d.mts.map +1 -0
  205. package/dist/number/branded-types/positive-uint32.mjs +139 -0
  206. package/dist/number/branded-types/positive-uint32.mjs.map +1 -0
  207. package/dist/number/branded-types/safe-int.d.mts +243 -0
  208. package/dist/number/branded-types/safe-int.d.mts.map +1 -0
  209. package/dist/number/branded-types/safe-int.mjs +240 -0
  210. package/dist/number/branded-types/safe-int.mjs.map +1 -0
  211. package/dist/number/branded-types/safe-uint.d.mts +151 -0
  212. package/dist/number/branded-types/safe-uint.d.mts.map +1 -0
  213. package/dist/number/branded-types/safe-uint.mjs +138 -0
  214. package/dist/number/branded-types/safe-uint.mjs.map +1 -0
  215. package/dist/number/branded-types/uint.d.mts +144 -0
  216. package/dist/number/branded-types/uint.d.mts.map +1 -0
  217. package/dist/number/branded-types/uint.mjs +132 -0
  218. package/dist/number/branded-types/uint.mjs.map +1 -0
  219. package/dist/number/branded-types/uint16.d.mts +157 -0
  220. package/dist/number/branded-types/uint16.d.mts.map +1 -0
  221. package/dist/number/branded-types/uint16.mjs +137 -0
  222. package/dist/number/branded-types/uint16.mjs.map +1 -0
  223. package/dist/number/branded-types/uint32.d.mts +185 -0
  224. package/dist/number/branded-types/uint32.d.mts.map +1 -0
  225. package/dist/number/branded-types/uint32.mjs +169 -0
  226. package/dist/number/branded-types/uint32.mjs.map +1 -0
  227. package/dist/number/enum/index.d.mts +3 -0
  228. package/dist/number/enum/index.d.mts.map +1 -0
  229. package/dist/number/enum/index.mjs +3 -0
  230. package/dist/number/enum/index.mjs.map +1 -0
  231. package/dist/number/enum/int8.d.mts +202 -0
  232. package/dist/number/enum/int8.d.mts.map +1 -0
  233. package/dist/number/enum/int8.mjs +296 -0
  234. package/dist/number/enum/int8.mjs.map +1 -0
  235. package/dist/number/enum/uint8.d.mts +128 -0
  236. package/dist/number/enum/uint8.d.mts.map +1 -0
  237. package/dist/number/enum/uint8.mjs +251 -0
  238. package/dist/number/enum/uint8.mjs.map +1 -0
  239. package/dist/number/index.d.mts +5 -0
  240. package/dist/number/index.d.mts.map +1 -0
  241. package/dist/number/index.mjs +31 -0
  242. package/dist/number/index.mjs.map +1 -0
  243. package/dist/number/num.d.mts +515 -0
  244. package/dist/number/num.d.mts.map +1 -0
  245. package/dist/number/num.mjs +513 -0
  246. package/dist/number/num.mjs.map +1 -0
  247. package/dist/number/refined-number-utils.d.mts +191 -0
  248. package/dist/number/refined-number-utils.d.mts.map +1 -0
  249. package/dist/number/refined-number-utils.mjs +179 -0
  250. package/dist/number/refined-number-utils.mjs.map +1 -0
  251. package/dist/object/index.d.mts +2 -0
  252. package/dist/object/index.d.mts.map +1 -0
  253. package/dist/object/index.mjs +2 -0
  254. package/dist/object/index.mjs.map +1 -0
  255. package/dist/object/object.d.mts +296 -0
  256. package/dist/object/object.d.mts.map +1 -0
  257. package/dist/object/object.mjs +295 -0
  258. package/dist/object/object.mjs.map +1 -0
  259. package/dist/others/cast-mutable.d.mts +110 -0
  260. package/dist/others/cast-mutable.d.mts.map +1 -0
  261. package/dist/others/cast-mutable.mjs +114 -0
  262. package/dist/others/cast-mutable.mjs.map +1 -0
  263. package/dist/others/cast-readonly.d.mts +189 -0
  264. package/dist/others/cast-readonly.d.mts.map +1 -0
  265. package/dist/others/cast-readonly.mjs +193 -0
  266. package/dist/others/cast-readonly.mjs.map +1 -0
  267. package/dist/others/if-then.d.mts +98 -0
  268. package/dist/others/if-then.d.mts.map +1 -0
  269. package/dist/others/if-then.mjs +100 -0
  270. package/dist/others/if-then.mjs.map +1 -0
  271. package/dist/others/index.d.mts +8 -0
  272. package/dist/others/index.d.mts.map +1 -0
  273. package/dist/others/index.mjs +8 -0
  274. package/dist/others/index.mjs.map +1 -0
  275. package/dist/others/map-nullable.d.mts +151 -0
  276. package/dist/others/map-nullable.d.mts.map +1 -0
  277. package/dist/others/map-nullable.mjs +159 -0
  278. package/dist/others/map-nullable.mjs.map +1 -0
  279. package/dist/others/memoize-function.d.mts +173 -0
  280. package/dist/others/memoize-function.d.mts.map +1 -0
  281. package/dist/others/memoize-function.mjs +189 -0
  282. package/dist/others/memoize-function.mjs.map +1 -0
  283. package/dist/others/tuple.d.mts +159 -0
  284. package/dist/others/tuple.d.mts.map +1 -0
  285. package/dist/others/tuple.mjs +161 -0
  286. package/dist/others/tuple.mjs.map +1 -0
  287. package/dist/others/unknown-to-string.d.mts +180 -0
  288. package/dist/others/unknown-to-string.d.mts.map +1 -0
  289. package/dist/others/unknown-to-string.mjs +211 -0
  290. package/dist/others/unknown-to-string.mjs.map +1 -0
  291. package/dist/tsconfig.json +1 -0
  292. package/package.json +18 -16
@@ -0,0 +1,2617 @@
1
+ import { IMap } from '../collections/index.mjs';
2
+ import { Optional, Result } from '../functional/index.mjs';
3
+ /**
4
+ * A comprehensive, immutable utility library for array manipulations in TypeScript.
5
+ * Provides a wide range of functions for array creation, validation, transformation,
6
+ * reduction, slicing, set operations, and more, with a focus on type safety and
7
+ * leveraging TypeScript's type inference capabilities.
8
+ * All functions operate on `readonly` arrays and return new `readonly` arrays,
9
+ * ensuring immutability.
10
+ */
11
+ export declare namespace Arr {
12
+ /**
13
+ * Returns the size (length) of an array as a type-safe branded integer.
14
+ *
15
+ * This function provides the array length with enhanced type safety through branded types:
16
+ * - For arrays known to be non-empty at compile time: returns `PositiveNumber & SizeType.Arr`
17
+ * - For general arrays that may be empty: returns `SizeType.Arr` (branded Uint32)
18
+ *
19
+ * The returned value is always a non-negative integer that can be safely used for array indexing
20
+ * and size comparisons. The branded type prevents common integer overflow issues and provides
21
+ * better type checking than plain numbers.
22
+ *
23
+ * @template Ar The exact type of the input array, used for precise return type inference.
24
+ * @param array The array to measure. Can be any readonly array type.
25
+ * @returns The length of the array as a branded type:
26
+ * - `IntersectBrand<PositiveNumber, SizeType.Arr>` for known non-empty arrays
27
+ * - `SizeType.Arr` for general arrays (branded Uint32, may be 0)
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * // Known non-empty arrays get positive branded type
32
+ * const tuple = [1, 2, 3] as const;
33
+ * const tupleSize = Arr.size(tuple);
34
+ * // Type: IntersectBrand<PositiveNumber, SizeType.Arr>
35
+ * // Value: 3 (branded, guaranteed positive)
36
+ *
37
+ * const nonEmpty: NonEmptyArray<string> = ['a', 'b'] as NonEmptyArray<string>;
38
+ * const nonEmptySize = Arr.size(nonEmpty);
39
+ * // Type: IntersectBrand<PositiveNumber, SizeType.Arr>
40
+ * // Guaranteed to be > 0
41
+ *
42
+ * // General arrays may be empty, get regular branded type
43
+ * const generalArray: number[] = [1, 2, 3];
44
+ * const generalSize = Arr.size(generalArray);
45
+ * // Type: SizeType.Arr (branded Uint32)
46
+ * // May be 0 or positive
47
+ *
48
+ * // Empty arrays
49
+ * const emptyArray = [] as const;
50
+ * const emptySize = Arr.size(emptyArray);
51
+ * // Type: SizeType.Arr
52
+ * // Value: 0 (branded)
53
+ *
54
+ * // Runtime arrays with unknown content
55
+ * const dynamicArray = Array.from({ length: Math.random() * 10 }, (_, i) => i);
56
+ * const dynamicSize = Arr.size(dynamicArray);
57
+ * // Type: SizeType.Arr (may be 0)
58
+ *
59
+ * // Using size for safe operations
60
+ * const data = [10, 20, 30];
61
+ * const dataSize = Arr.size(data);
62
+ *
63
+ * // Safe for array creation
64
+ * const indices = Arr.seq(dataSize); // Creates [0, 1, 2]
65
+ * const zeros = Arr.zeros(dataSize); // Creates [0, 0, 0]
66
+ *
67
+ * // Safe for bounds checking
68
+ * const isValidIndex = (index: number) => index >= 0 && index < dataSize;
69
+ *
70
+ * // Comparison with other sizes
71
+ * const otherArray = ['a', 'b'];
72
+ * const sizeDiff = Uint32.sub(Arr.size(data), Arr.size(otherArray)); // 1
73
+ *
74
+ * // Functional composition
75
+ * const arrays = [
76
+ * [1, 2],
77
+ * [3, 4, 5],
78
+ * [],
79
+ * [6]
80
+ * ];
81
+ * const sizes = arrays.map(Arr.size); // [2, 3, 0, 1] (all branded)
82
+ * const totalElements = sizes.reduce(Uint32.add, 0); // 6
83
+ *
84
+ * // Type guards work with size
85
+ * if (Arr.size(data) > 0) {
86
+ * // TypeScript knows data is non-empty here
87
+ * const firstElement = data[0]; // Safe access
88
+ * }
89
+ *
90
+ * // Type inference examples
91
+ * expectType<typeof tupleSize, IntersectBrand<PositiveNumber, SizeType.Arr>>('=');
92
+ * expectType<typeof generalSize, SizeType.Arr>('=');
93
+ * expectType<typeof emptySize, SizeType.Arr>('=');
94
+ * ```
95
+ *
96
+ * @see {@link length} - Alias for this function
97
+ * @see {@link isEmpty} for checking if size is 0
98
+ * @see {@link isNonEmpty} for checking if size > 0
99
+ */
100
+ export const size: SizeFnOverload;
101
+ type SizeFnOverload = {
102
+ <Ar extends NonEmptyArray<unknown>>(array: Ar): IntersectBrand<PositiveNumber, SizeType.Arr>;
103
+ <Ar extends readonly unknown[]>(array: Ar): SizeType.Arr;
104
+ };
105
+ export const length: SizeFnOverload;
106
+ /**
107
+ * Type guard that checks if a value is an array, excluding types that cannot be arrays.
108
+ * This function refines the type by filtering out non-array types from unions.
109
+ * @template E The input type that may or may not be an array.
110
+ * @param value The value to check.
111
+ * @returns `true` if the value is an array, `false` otherwise.
112
+ * @example
113
+ * ```ts
114
+ * function processValue(value: string | number[] | null) {
115
+ * if (Arr.isArray(value)) {
116
+ * // value is now typed as number[]
117
+ * console.log(value.length);
118
+ * }
119
+ * }
120
+ *
121
+ * Arr.isArray([1, 2, 3]); // true
122
+ * Arr.isArray("hello"); // false
123
+ * Arr.isArray(null); // false
124
+ * ```
125
+ */
126
+ export const isArray: <E>(value: E) => value is FilterArray<E>;
127
+ type FilterArray<T> = T extends T ? BoolOr<TypeEq<T, unknown>, TypeEq<T, any>> extends true ? Cast<readonly unknown[], T> : T extends readonly unknown[] ? T : never : never;
128
+ type Cast<A, B> = A extends B ? A : never;
129
+ /**
130
+ * Type guard that checks if an array is empty (has no elements).
131
+ *
132
+ * This function serves as both a runtime check and a TypeScript type guard,
133
+ * narrowing the array type to `readonly []` when the check passes. It's useful
134
+ * for conditional logic and type-safe handling of potentially empty arrays.
135
+ *
136
+ * @template E The type of elements in the array.
137
+ * @param array The array to check for emptiness.
138
+ * @returns `true` if the array has length 0, `false` otherwise.
139
+ * When `true`, TypeScript narrows the type to `readonly []`.
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * // Basic emptiness checking
144
+ * const emptyArray: number[] = [];
145
+ * const nonEmptyArray = [1, 2, 3];
146
+ *
147
+ * console.log(Arr.isEmpty(emptyArray)); // true
148
+ * console.log(Arr.isEmpty(nonEmptyArray)); // false
149
+ *
150
+ * // Type guard behavior
151
+ * function processArray(arr: readonly number[]) {
152
+ * if (Arr.isEmpty(arr)) {
153
+ * // arr is now typed as readonly []
154
+ * console.log('Array is empty');
155
+ * return 0;
156
+ * } else {
157
+ * // arr is now typed as NonEmptyArray<number>
158
+ * return arr[0]; // Safe access - TypeScript knows it's non-empty
159
+ * }
160
+ * }
161
+ *
162
+ * // Conditional processing
163
+ * const data = [10, 20, 30];
164
+ * if (!Arr.isEmpty(data)) {
165
+ * // Safe to access elements
166
+ * const firstElement = data[0]; // No undefined risk
167
+ * const lastElement = data[data.length - 1];
168
+ * }
169
+ *
170
+ * // Filtering empty arrays
171
+ * const arrayList: readonly number[][] = [[1, 2], [], [3], []];
172
+ * const nonEmptyArrays = arrayList.filter(arr => !Arr.isEmpty(arr));
173
+ * // nonEmptyArrays: [[1, 2], [3]]
174
+ *
175
+ * // Early returns
176
+ * function sumArray(numbers: readonly number[]): number {
177
+ * if (Arr.isEmpty(numbers)) {
178
+ * return 0; // Handle empty case early
179
+ * }
180
+ * return numbers.reduce((sum, n) => sum + n, 0);
181
+ * }
182
+ *
183
+ * // Type inference examples
184
+ * const testEmpty = [] as const;
185
+ * const testNonEmpty = [1, 2] as const;
186
+ *
187
+ * expectType<Parameters<typeof Arr.isEmpty>[0], readonly unknown[]>('=');
188
+ * expectType<ReturnType<typeof Arr.isEmpty>, boolean>('=');
189
+ * ```
190
+ *
191
+ * @see {@link isNonEmpty} for the opposite check (non-empty arrays)
192
+ * @see {@link size} for getting the exact length
193
+ * @see {@link isArrayOfLength} for checking specific lengths
194
+ */
195
+ export const isEmpty: <E>(array: readonly E[]) => array is readonly [];
196
+ /**
197
+ * Type guard that checks if an array is non-empty (has at least one element).
198
+ *
199
+ * This function serves as both a runtime check and a TypeScript type guard,
200
+ * narrowing the array type to `NonEmptyArray<E>` when the check passes. This enables
201
+ * safe access to array elements without undefined checks, as TypeScript knows the array
202
+ * has at least one element.
203
+ *
204
+ * @template E The type of elements in the array.
205
+ * @param array The array to check for non-emptiness.
206
+ * @returns `true` if the array has length > 0, `false` otherwise.
207
+ * When `true`, TypeScript narrows the type to `NonEmptyArray<E>`.
208
+ *
209
+ * @example
210
+ * ```typescript
211
+ * // Basic non-emptiness checking
212
+ * const emptyArray: number[] = [];
213
+ * const nonEmptyArray = [1, 2, 3];
214
+ *
215
+ * console.log(Arr.isNonEmpty(emptyArray)); // false
216
+ * console.log(Arr.isNonEmpty(nonEmptyArray)); // true
217
+ *
218
+ * // Type guard behavior enables safe element access
219
+ * function getFirstElement(arr: readonly number[]): number | undefined {
220
+ * if (Arr.isNonEmpty(arr)) {
221
+ * // arr is now typed as NonEmptyArray<number>
222
+ * return arr[0]; // Safe - no undefined, TypeScript knows this exists
223
+ * }
224
+ * return undefined;
225
+ * }
226
+ *
227
+ * // Safe operations on non-empty arrays
228
+ * function processData(data: readonly string[]) {
229
+ * if (Arr.isNonEmpty(data)) {
230
+ * // All of these are now safe without undefined checks
231
+ * const first = data[0];
232
+ * const last = data[data.length - 1];
233
+ * const middle = data[Math.floor(data.length / 2)];
234
+ *
235
+ * // Can safely use non-empty array methods
236
+ * const joined = data.join(', ');
237
+ * const reduced = data.reduce((acc, item) => acc + item.length, 0);
238
+ * }
239
+ * }
240
+ *
241
+ * // Filtering and working with arrays
242
+ * const possiblyEmptyArrays: readonly number[][] = [
243
+ * [1, 2, 3],
244
+ * [],
245
+ * [4, 5],
246
+ * []
247
+ * ];
248
+ *
249
+ * // Get only non-empty arrays with proper typing
250
+ * const definitelyNonEmpty = possiblyEmptyArrays.filter(Arr.isNonEmpty);
251
+ * // Type: NonEmptyArray<number>[]
252
+ *
253
+ * // Now safe to access elements
254
+ * const firstElements = definitelyNonEmpty.map(arr => arr[0]); // [1, 4]
255
+ *
256
+ * // Early validation
257
+ * function calculateAverage(numbers: readonly number[]): number {
258
+ * if (!Arr.isNonEmpty(numbers)) {
259
+ * throw new Error('Cannot calculate average of empty array');
260
+ * }
261
+ *
262
+ * // numbers is now NonEmptyArray<number>
263
+ * return numbers.reduce((sum, n) => sum + n, 0) / numbers.length;
264
+ * }
265
+ *
266
+ * // Functional composition
267
+ * const arrayGroups = [
268
+ * [1, 2],
269
+ * [],
270
+ * [3, 4, 5],
271
+ * []
272
+ * ];
273
+ *
274
+ * const nonEmptyGroups = arrayGroups
275
+ * .filter(Arr.isNonEmpty) // Filter to NonEmptyArray<number>[]
276
+ * .map(group => group[0]); // Safe access to first element: [1, 3]
277
+ *
278
+ * // Combined with other array operations
279
+ * function processArraySafely<T>(
280
+ * arr: readonly T[],
281
+ * processor: (item: T) => string
282
+ * ): string {
283
+ * if (Arr.isNonEmpty(arr)) {
284
+ * return arr.map(processor).join(' -> ');
285
+ * }
286
+ * return 'No items to process';
287
+ * }
288
+ *
289
+ * // Type inference examples
290
+ * const testArray = [1, 2, 3];
291
+ * const isNonEmptyResult = Arr.isNonEmpty(testArray);
292
+ *
293
+ * expectType<typeof isNonEmptyResult, boolean>('=');
294
+ * expectType<Parameters<typeof Arr.isNonEmpty>[0], readonly unknown[]>('=');
295
+ *
296
+ * // Type narrowing in conditional
297
+ * if (Arr.isNonEmpty(testArray)) {
298
+ * expectType<typeof testArray, NonEmptyArray<number>>('=');
299
+ * }
300
+ * ```
301
+ *
302
+ * @see {@link isEmpty} for the opposite check (empty arrays)
303
+ * @see {@link size} for getting the exact length
304
+ * @see {@link head} for safely getting the first element
305
+ * @see {@link last} for safely getting the last element
306
+ */
307
+ export const isNonEmpty: <E>(array: readonly E[]) => array is NonEmptyArray<E>;
308
+ /**
309
+ * Checks if an array has a specific length.
310
+ * @template E The type of elements in the array.
311
+ * @template N The expected length of the array (must be a number type).
312
+ * @param array The array to check.
313
+ * @param len The expected length.
314
+ * @returns `true` if the array has the specified length, `false` otherwise.
315
+ * @example
316
+ * ```ts
317
+ * const arr: readonly number[] = [1, 2, 3];
318
+ * if (Arr.isArrayOfLength(arr, 3)) {
319
+ * // arr is now typed as readonly [number, number, number]
320
+ * }
321
+ * Arr.isArrayOfLength([1, 2], 3); // false
322
+ * ```
323
+ */
324
+ export const isArrayOfLength: <E, N extends SizeType.ArgArrNonNegative>(array: readonly E[], len: N) => array is ArrayOfLength<N, E>;
325
+ /**
326
+ * Checks if an array has at least a specific length.
327
+ * @template E The type of elements in the array.
328
+ * @template N The minimum expected length of the array (must be a number type).
329
+ * @param array The array to check.
330
+ * @param len The minimum expected length.
331
+ * @returns `true` if the array has at least the specified length, `false` otherwise.
332
+ * @example
333
+ * ```ts
334
+ * const arr: readonly number[] = [1, 2, 3];
335
+ * if (Arr.isArrayAtLeastLength(arr, 2)) {
336
+ * // arr is now typed as readonly [number, number, ...number[]]
337
+ * }
338
+ * Arr.isArrayAtLeastLength([1], 2); // false
339
+ * ```
340
+ */
341
+ export const isArrayAtLeastLength: <E, N extends SizeType.ArgArrNonNegative>(array: readonly E[], len: N) => array is ArrayAtLeastLen<N, E>;
342
+ /**
343
+ * Checks if an index is within the valid range of an array (i.e., `0 <= index < array.length`).
344
+ * @template E The type of elements in the array.
345
+ * @param array The input array.
346
+ * @param index The index to check.
347
+ * @returns `true` if the index is within the array bounds, `false` otherwise.
348
+ * @example
349
+ * ```ts
350
+ * Arr.indexIsInRange([10, 20], 0); // true
351
+ * Arr.indexIsInRange([10, 20], 1); // true
352
+ * Arr.indexIsInRange([10, 20], 2); // false
353
+ * Arr.indexIsInRange([10, 20], -1); // false
354
+ * Arr.indexIsInRange([], 0); // false
355
+ * ```
356
+ */
357
+ export const indexIsInRange: <E>(array: readonly E[], index: SizeType.ArgArrNonNegative) => boolean;
358
+ /**
359
+ * Creates an array of zeros with the specified length.
360
+ *
361
+ * This function provides compile-time type safety with precise return types:
362
+ * - When `len` is a compile-time known `SmallUint` (0-100), returns a tuple with exact length
363
+ * - When `len` is a positive runtime value, returns a `NonEmptyArray<0>`
364
+ * - Otherwise, returns a `readonly 0[]` that may be empty
365
+ *
366
+ * @template N The type of the length parameter. When a `SmallUint` literal is provided,
367
+ * the return type will be a tuple of exactly that length filled with zeros.
368
+ * @param len The length of the array to create. Must be a non-negative integer.
369
+ * @returns An immutable array of zeros. The exact return type depends on the input:
370
+ * - `ArrayOfLength<N, 0>` when `N` is a `SmallUint` literal
371
+ * - `NonEmptyArray<0>` when `len` is a positive runtime value
372
+ * - `readonly 0[]` for general non-negative values
373
+ *
374
+ * @example
375
+ * ```typescript
376
+ * // Compile-time known lengths produce precise tuple types
377
+ * const exactLength = Arr.zeros(3); // readonly [0, 0, 0]
378
+ * const empty = Arr.zeros(0); // readonly []
379
+ *
380
+ * // Runtime positive values produce non-empty arrays
381
+ * const count = Math.floor(Math.random() * 5) + 1;
382
+ * const nonEmpty = Arr.zeros(count); // NonEmptyArray<0>
383
+ *
384
+ * // General runtime values may be empty
385
+ * const maybeEmpty = Arr.zeros(Math.floor(Math.random() * 5)); // readonly 0[]
386
+ *
387
+ * // Type inference examples
388
+ * expectType<typeof exactLength, readonly [0, 0, 0]>('=');
389
+ * expectType<typeof empty, readonly []>('=');
390
+ * expectType<typeof nonEmpty, NonEmptyArray<0>>('=');
391
+ * expectType<typeof maybeEmpty, readonly 0[]>('=');
392
+ * ```
393
+ */
394
+ export const zeros: ZerosFnOverload;
395
+ type ZerosFnOverload = {
396
+ /**
397
+ * Create array of zeros with compile-time length.
398
+ */
399
+ <N extends SmallUint>(len: N): ArrayOfLength<N, 0>;
400
+ /**
401
+ * Create non-empty array of zeros.
402
+ */
403
+ (len: SizeType.ArgArrPositive): NonEmptyArray<0>;
404
+ /**
405
+ * Create array of zeros.
406
+ */
407
+ (len: SizeType.ArgArrNonNegative): readonly 0[];
408
+ };
409
+ /**
410
+ * Creates a sequence of consecutive integers from 0 to `len-1`.
411
+ *
412
+ * This function generates index sequences with precise compile-time typing:
413
+ * - When `len` is a compile-time known `SmallUint` (0-100), returns a tuple of consecutive integers
414
+ * - When `len` is a positive runtime value, returns a `NonEmptyArray<SizeType.Arr>`
415
+ * - Otherwise, returns a `readonly SizeType.Arr[]` that may be empty
416
+ *
417
+ * @template N The type of the length parameter. When a `SmallUint` literal is provided,
418
+ * the return type will be a tuple containing the sequence [0, 1, 2, ..., N-1].
419
+ * @param len The length of the sequence to create. Must be a non-negative integer.
420
+ * @returns An immutable array containing the sequence [0, 1, 2, ..., len-1].
421
+ * The exact return type depends on the input:
422
+ * - `Seq<N>` (precise tuple) when `N` is a `SmallUint` literal
423
+ * - `NonEmptyArray<SizeType.Arr>` when `len` is a positive runtime value
424
+ * - `readonly SizeType.Arr[]` for general non-negative values
425
+ *
426
+ * @example
427
+ * ```typescript
428
+ * // Compile-time known lengths produce precise tuple types
429
+ * const indices = Arr.seq(4); // readonly [0, 1, 2, 3]
430
+ * const empty = Arr.seq(0); // readonly []
431
+ * const single = Arr.seq(1); // readonly [0]
432
+ *
433
+ * // Runtime positive values produce non-empty arrays
434
+ * const count = Math.floor(Math.random() * 5) + 1;
435
+ * const nonEmpty = Arr.seq(count); // NonEmptyArray<SizeType.Arr>
436
+ *
437
+ * // General runtime values may be empty
438
+ * const maybeEmpty = Arr.seq(Math.floor(Math.random() * 5)); // readonly SizeType.Arr[]
439
+ *
440
+ * // Useful for generating array indices
441
+ * const data = ['a', 'b', 'c', 'd'];
442
+ * const indexSequence = Arr.seq(data.length); // [0, 1, 2, 3]
443
+ *
444
+ * // Type inference examples
445
+ * expectType<typeof indices, readonly [0, 1, 2, 3]>('=');
446
+ * expectType<typeof empty, readonly []>('=');
447
+ * expectType<typeof single, readonly [0]>('=');
448
+ * ```
449
+ */
450
+ export const seq: SeqFnOverload;
451
+ type SeqFnOverload = {
452
+ <N extends SmallUint>(len: N): Seq<N>;
453
+ (len: SizeType.ArgArrPositive): NonEmptyArray<SizeType.Arr>;
454
+ (len: SizeType.ArgArrNonNegative): readonly SizeType.Arr[];
455
+ };
456
+ /**
457
+ * Creates a new array of the specified length, with each position filled with the provided initial value.
458
+ *
459
+ * This function provides compile-time type safety with precise return types and performs shallow copying
460
+ * of the initial value (the same reference is used for all positions):
461
+ * - When `len` is a compile-time known `SmallUint` (0-100), returns a tuple of exactly that length
462
+ * - When `len` is a positive runtime value, returns a `NonEmptyArray<V>`
463
+ * - Otherwise, returns a `readonly V[]` that may be empty
464
+ *
465
+ * @template V The type of the initial value. The `const` constraint preserves literal types.
466
+ * @template N The type of the length parameter when it's a `SmallUint` literal.
467
+ * @param len The length of the array to create. Must be a non-negative integer.
468
+ * @param init The value to fill each position with. The same reference is used for all positions.
469
+ * @returns An immutable array filled with the initial value. The exact return type depends on the length:
470
+ * - `ArrayOfLength<N, V>` when `len` is a `SmallUint` literal
471
+ * - `NonEmptyArray<V>` when `len` is a positive runtime value
472
+ * - `readonly V[]` for general non-negative values
473
+ *
474
+ * @example
475
+ * ```typescript
476
+ * // Compile-time known lengths produce precise tuple types
477
+ * const strings = Arr.create(3, 'hello'); // readonly ['hello', 'hello', 'hello']
478
+ * const numbers = Arr.create(2, 42); // readonly [42, 42]
479
+ * const empty = Arr.create(0, 'unused'); // readonly []
480
+ *
481
+ * // Object references are shared (shallow copy behavior)
482
+ * const obj = { id: 1, name: 'test' };
483
+ * const objects = Arr.create(3, obj); // readonly [obj, obj, obj]
484
+ * objects[0] === objects[1]; // true - same reference
485
+ * objects[0].id = 999; // Mutates the shared object
486
+ * console.log(objects[1].id); // 999 - all positions affected
487
+ *
488
+ * // Runtime positive values produce non-empty arrays
489
+ * const count = Math.floor(Math.random() * 5) + 1;
490
+ * const nonEmpty = Arr.create(count, 'item'); // NonEmptyArray<string>
491
+ *
492
+ * // Literal type preservation with const assertion
493
+ * const literals = Arr.create(2, 'success' as const); // readonly ['success', 'success']
494
+ *
495
+ * // Type inference examples
496
+ * expectType<typeof strings, readonly ['hello', 'hello', 'hello']>('=');
497
+ * expectType<typeof numbers, readonly [42, 42]>('=');
498
+ * expectType<typeof empty, readonly []>('=');
499
+ * ```
500
+ *
501
+ * @see {@link zeros} for creating arrays filled with zeros
502
+ * @see {@link seq} for creating sequences of consecutive integers
503
+ */
504
+ export const create: CreateFnOverload;
505
+ type CreateFnOverload = {
506
+ <const V, N extends SmallUint>(len: N, init: V): ArrayOfLength<N, V>;
507
+ <const V>(len: SizeType.ArgArrPositive, init: V): NonEmptyArray<V>;
508
+ <const V>(len: SizeType.ArgArrNonNegative, init: V): readonly V[];
509
+ };
510
+ export const newArray: CreateFnOverload;
511
+ /**
512
+ * Creates a shallow copy of an array, preserving the exact type signature.
513
+ *
514
+ * This function creates a new array with the same elements as the input, but with a new array reference.
515
+ * Object references within the array are preserved (shallow copy), and the readonly/mutable status
516
+ * of the array type is maintained.
517
+ *
518
+ * @template Ar The exact type of the input array, preserving tuple types, readonly status, and element types.
519
+ * @param array The array to copy. Can be any array type: mutable, readonly, tuple, or general array.
520
+ * @returns A new array that is a shallow copy of the input. The return type exactly matches the input type,
521
+ * preserving readonly status, tuple structure, and element types.
522
+ *
523
+ * @example
524
+ * ```typescript
525
+ * // Mutable arrays remain mutable
526
+ * const mutableOriginal = [1, 2, 3];
527
+ * const mutableCopy = Arr.copy(mutableOriginal); // number[]
528
+ * mutableCopy[0] = 999; // OK - still mutable
529
+ * mutableOriginal[0]; // 1 - original unchanged
530
+ *
531
+ * // Readonly arrays remain readonly
532
+ * const readonlyOriginal = [1, 2, 3] as const;
533
+ * const readonlyCopy = Arr.copy(readonlyOriginal); // readonly [1, 2, 3]
534
+ * // readonlyCopy[0] = 999; // Error - readonly array
535
+ *
536
+ * // Tuple types are preserved
537
+ * const tupleOriginal: [string, number, boolean] = ['hello', 42, true];
538
+ * const tupleCopy = Arr.copy(tupleOriginal); // [string, number, boolean]
539
+ *
540
+ * // Shallow copy behavior with objects
541
+ * const objectArray = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
542
+ * const objectCopy = Arr.copy(objectArray);
543
+ * objectCopy[0].name = 'Charlie'; // Mutates the shared object reference
544
+ * console.log(objectArray[0].name); // 'Charlie' - original affected
545
+ * objectCopy.push({ id: 3, name: 'Dave' }); // Array structure changes don't affect original
546
+ * console.log(objectArray.length); // 2 - original array length unchanged
547
+ *
548
+ * // Empty arrays
549
+ * const emptyArray: number[] = [];
550
+ * const emptyCopy = Arr.copy(emptyArray); // number[]
551
+ * const emptyTuple = [] as const;
552
+ * const emptyTupleCopy = Arr.copy(emptyTuple); // readonly []
553
+ *
554
+ * // Type inference examples
555
+ * expectType<typeof mutableCopy, number[]>('=');
556
+ * expectType<typeof readonlyCopy, readonly [1, 2, 3]>('=');
557
+ * expectType<typeof tupleCopy, [string, number, boolean]>('=');
558
+ * ```
559
+ *
560
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice | Array.prototype.slice}
561
+ * The underlying implementation uses `slice()` for efficient shallow copying
562
+ */
563
+ export const copy: <Ar extends readonly unknown[]>(array: Ar) => Ar;
564
+ /**
565
+ * @internal
566
+ * Helper type for `range` function to represent a sequence of numbers up to N-1.
567
+ * `LEQ[N]` would be `0 | 1 | ... | N-1`.
568
+ */
569
+ type LT = Readonly<{
570
+ [N in SmallUint]: Index<N>;
571
+ }>;
572
+ /**
573
+ * @internal
574
+ * This type is used to avoid incorrect type calculation results for unions with `Seq`.
575
+ * It computes the type of an array generated by `Arr.range(S, E)`.
576
+ * If `S` or `E` is a union type, it falls back to a more general `readonly number[]` type
577
+ * to prevent overly complex or incorrect tuple/union types.
578
+ * Otherwise, it computes a precise tuple type like `readonly [S, S+1, ..., E-1]`.
579
+ * @template S The start of the range (inclusive), constrained to `SmallUint`.
580
+ * @template E The end of the range (exclusive), constrained to `SmallUint`.
581
+ */
582
+ type RangeList<S extends SmallUint, E extends SmallUint> = BoolOr<IsUnion<S>, IsUnion<E>> extends true ? readonly RelaxedExclude<LT[E], LT[Min<S>]>[] : List.Skip<S, Seq<E>>;
583
+ /**
584
+ * Creates an array of numbers within a specified range with optional step increment.
585
+ *
586
+ * This function generates arithmetic sequences with advanced compile-time type inference:
587
+ * - When `start` and `end` are {@link SmallUint} literals and `step` is 1 (or omitted), returns a precise tuple type
588
+ * - When parameters are runtime values, returns appropriate array types based on sign constraints
589
+ * - Empty arrays are returned for invalid ranges (e.g., start ≥ end with positive step)
590
+ * - Never throws exceptions - invalid parameters result in empty arrays
591
+ *
592
+ * **SmallUint Constraint:** The {@link SmallUint} constraint (0-255) enables precise tuple type inference
593
+ * for compile-time known ranges. This allows TypeScript to compute exact tuple types like `readonly [1, 2, 3, 4]`
594
+ * instead of generic `readonly number[]`.
595
+ *
596
+ * **Type Inference Behavior:**
597
+ * - Literal {@link SmallUint} values with step=1 → precise tuple type (`RangeList<S, E>`)
598
+ * - Non-negative parameters → `readonly SafeUint[]`
599
+ * - Mixed signs or negative parameters → `readonly SafeInt[]`
600
+ * - Runtime values → lose precise typing but maintain safety
601
+ *
602
+ * @template S The type of the start value. When a {@link SmallUint} literal (0-255), enables precise tuple typing.
603
+ * @template E The type of the end value. When a {@link SmallUint} literal (0-255), enables precise tuple typing.
604
+ * @param start The start of the range (inclusive). Must be a safe integer. Supports:
605
+ * - **Literal {@link SmallUint}:** Enables precise tuple types (0-255)
606
+ * - **Runtime {@link SafeInt}:** Fallback to general array types
607
+ * - **Negative values:** Supported for countdown sequences
608
+ * @param end The end of the range (exclusive). Must be a safe integer. Supports:
609
+ * - **Literal {@link SmallUint}:** Enables precise tuple types (0-255)
610
+ * - **Runtime {@link SafeInt}:** Fallback to general array types
611
+ * - **Equal to start:** Results in empty array
612
+ * @param step The step increment (default: 1). Must be a non-zero safe integer.
613
+ * - **Positive step:** generates increasing sequence from start to end
614
+ * - **Negative step:** generates decreasing sequence from start to end
615
+ * - **Zero step:** Not allowed (branded type prevents this)
616
+ * @returns An immutable array containing the arithmetic sequence. Return type depends on parameters:
617
+ * - `RangeList<S, E>` (precise tuple like `readonly [1, 2, 3, 4]`) when `S` and `E` are {@link SmallUint} literals and step is 1
618
+ * - `readonly SafeUint[]` when all parameters are non-negative
619
+ * - `readonly SafeInt[]` for general integer ranges including negative values
620
+ *
621
+ * @example
622
+ * ```typescript
623
+ * // Compile-time known ranges with step=1 produce precise tuple types
624
+ * const range1to4 = Arr.range(1, 5); // readonly [1, 2, 3, 4]
625
+ * const range0to2 = Arr.range(0, 3); // readonly [0, 1, 2]
626
+ * const emptyRange = Arr.range(5, 5); // readonly []
627
+ * const reverseEmpty = Arr.range(5, 1); // readonly [] (invalid with positive step)
628
+ *
629
+ * // SmallUint constraint examples (0-255 for precise typing)
630
+ * const small = Arr.range(0, 10); // readonly [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
631
+ * const maxSmall = Arr.range(250, 255); // readonly [250, 251, 252, 253, 254]
632
+ * const beyondSmall = Arr.range(0, 300); // readonly SafeUint[] (loses precision)
633
+ *
634
+ * // Custom step increments
635
+ * const evens = Arr.range(0, 10, 2); // readonly SafeUint[] -> [0, 2, 4, 6, 8]
636
+ * const odds = Arr.range(1, 10, 2); // readonly SafeUint[] -> [1, 3, 5, 7, 9]
637
+ * const countdown = Arr.range(5, 0, -1); // readonly SafeInt[] -> [5, 4, 3, 2, 1]
638
+ * const bigStep = Arr.range(0, 20, 5); // readonly SafeUint[] -> [0, 5, 10, 15]
639
+ *
640
+ * // Edge cases that return empty arrays
641
+ * const singleElement = Arr.range(3, 4); // readonly [3]
642
+ * const invalidRange = Arr.range(10, 5, 2); // readonly [] (start > end with positive step)
643
+ * const invalidReverse = Arr.range(1, 10, -1); // readonly [] (start < end with negative step)
644
+ * const zeroRange = Arr.range(42, 42); // readonly [] (start equals end)
645
+ *
646
+ * // Runtime ranges lose precise typing but maintain safety
647
+ * const dynamicStart = Math.floor(Math.random() * 10) as SafeInt;
648
+ * const dynamicEnd = (dynamicStart + 5) as SafeInt;
649
+ * const dynamicRange = Arr.range(dynamicStart, dynamicEnd); // readonly SafeInt[]
650
+ *
651
+ * // Negative numbers and mixed signs
652
+ * const negativeRange = Arr.range(-5, 5); // readonly SafeInt[] -> [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]
653
+ * const negativeCountdown = Arr.range(0, -5, -1); // readonly SafeInt[] -> [0, -1, -2, -3, -4]
654
+ *
655
+ * // Useful for generating index ranges and iteration
656
+ * const indices = Arr.range(0, 10); // readonly [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
657
+ * const reversedIndices = Arr.range(9, -1, -1); // readonly SafeInt[] -> [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
658
+ *
659
+ * // Functional programming patterns
660
+ * const squares = Arr.range(1, 6).map(x => x * x); // [1, 4, 9, 16, 25]
661
+ * 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]
662
+ *
663
+ * // Type inference examples showing precise vs general types
664
+ * expectType<typeof range1to4, readonly [1, 2, 3, 4]>('='); // Precise tuple
665
+ * expectType<typeof emptyRange, readonly []>('='); // Precise empty tuple
666
+ * expectType<typeof evens, readonly SafeUint[]>('='); // General positive array
667
+ * expectType<typeof countdown, readonly SafeInt[]>('='); // General integer array
668
+ * expectType<typeof negativeRange, readonly SafeInt[]>('='); // General integer array
669
+ * expectType<typeof small, readonly [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>('='); // Precise tuple
670
+ * expectType<typeof beyondSmall, readonly SafeUint[]>('='); // General array (beyond SmallUint)
671
+ * ```
672
+ *
673
+ * @throws Never throws - invalid ranges simply return empty arrays
674
+ * @see {@link seq} for creating sequences starting from 0
675
+ * @see {@link SmallUint} for understanding the constraint that enables precise typing
676
+ * @see {@link SafeInt} and {@link SafeUint} for the safe integer types used
677
+ */
678
+ export const range: RangeFnOverload;
679
+ type RangeFnOverload = {
680
+ <S extends SmallUint, E extends SmallUint>(start: S, end: E, step?: 1): RangeList<S, E>;
681
+ (start: SafeUintWithSmallInt, end: SafeUintWithSmallInt, step?: PositiveSafeIntWithSmallInt): readonly SafeUint[];
682
+ (start: SafeIntWithSmallInt, end: SafeIntWithSmallInt, step?: NonZeroSafeIntWithSmallInt): readonly SafeInt[];
683
+ };
684
+ /**
685
+ * Safely retrieves an element at a given index from an array, returning an {@link Optional}.
686
+ *
687
+ * This function provides type-safe array access with support for negative indexing
688
+ * (e.g., -1 for the last element). Unlike direct array access which can return
689
+ * `undefined` for out-of-bounds indices, this function always returns a well-typed
690
+ * {@link Optional} that explicitly represents the possibility of absence.
691
+ *
692
+ * **Negative Indexing:** Negative indices count from the end of the array:
693
+ * - `-1` refers to the last element
694
+ * - `-2` refers to the second-to-last element, etc.
695
+ *
696
+ * **Curried Usage:** This function supports currying - when called with only an index, it returns
697
+ * a function that can be applied to arrays, making it ideal for use in pipe operations.
698
+ *
699
+ * **Optional Return Type:** The return type is always {@link Optional}<E> which provides:
700
+ * - Type-safe access without `undefined` in your business logic
701
+ * - Explicit handling of \"not found\" cases
702
+ * - Composable error handling with {@link Optional} utilities
703
+ *
704
+ * @template E The type of elements in the array.
705
+ * @param array The array to access (when using direct call syntax).
706
+ * @param index The index to access. Must be a branded `SizeType.ArgArr` (safe integer). Can be:
707
+ * - **Positive integer:** 0-based index from the start (0, 1, 2, ...)
708
+ * - **Negative integer:** index from the end (-1 is last element, -2 is second-to-last, etc.)
709
+ * - **Out of bounds:** any index beyond array bounds returns {@link Optional.None}
710
+ * @returns An {@link Optional}<E> containing:
711
+ * - {@link Optional.Some}<E> with the element if the index is valid
712
+ * - {@link Optional.None} if the index is out of bounds (including empty arrays)
713
+ *
714
+ * @example
715
+ * ```typescript
716
+ * // Direct usage with positive indices
717
+ * const fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry'];
718
+ * const first = Arr.at(fruits, 0); // Optional.Some('apple')
719
+ * const third = Arr.at(fruits, 2); // Optional.Some('cherry')
720
+ * const outOfBounds = Arr.at(fruits, 10); // Optional.None
721
+ *
722
+ * // Negative indexing (accessing from the end)
723
+ * const last = Arr.at(fruits, -1); // Optional.Some('elderberry')
724
+ * const secondLast = Arr.at(fruits, -2); // Optional.Some('date')
725
+ * const negativeOutOfBounds = Arr.at(fruits, -10); // Optional.None
726
+ *
727
+ * // Edge cases
728
+ * const emptyResult = Arr.at([], 0); // Optional.None
729
+ * const negativeOnEmpty = Arr.at([], -1); // Optional.None
730
+ * const singleElement = Arr.at(['only'], 0); // Optional.Some('only')
731
+ * const singleNegative = Arr.at(['only'], -1); // Optional.Some('only')
732
+ *
733
+ * // Safe access pattern with type-safe unwrapping
734
+ * const maybeElement = Arr.at(fruits, 2);
735
+ * if (Optional.isSome(maybeElement)) {
736
+ * console.log(`Found: ${maybeElement.value}`); // Type-safe access, no undefined
737
+ * } else {
738
+ * console.log('Index out of bounds');
739
+ * }
740
+ *
741
+ * // Alternative unwrapping with default
742
+ * const elementOrDefault = Optional.unwrapOr(Arr.at(fruits, 100), 'not found');
743
+ * console.log(elementOrDefault); // 'not found'
744
+ *
745
+ * // Curried usage for functional composition
746
+ * const getSecondElement = Arr.at(1);
747
+ * const getLastElement = Arr.at(-1);
748
+ * const getMiddleElement = Arr.at(2);
749
+ *
750
+ * const nestedArrays = [
751
+ * [10, 20, 30, 40],
752
+ * [50, 60],
753
+ * [70]
754
+ * ];
755
+ * const secondElements = nestedArrays.map(getSecondElement);
756
+ * // [Optional.Some(20), Optional.None, Optional.None]
757
+ *
758
+ * const lastElements = nestedArrays.map(getLastElement);
759
+ * // [Optional.Some(40), Optional.Some(60), Optional.Some(70)]
760
+ *
761
+ * // Pipe composition for data processing
762
+ * const processArray = (arr: readonly string[]) => pipe(arr)
763
+ * .map(getSecondElement)
764
+ * .map(opt => Optional.map(opt, s => s.toUpperCase()))
765
+ * .map(opt => Optional.unwrapOr(opt, 'MISSING'))
766
+ * .value;
767
+ *
768
+ * console.log(processArray(['a', 'b', 'c'])); // 'B'
769
+ * console.log(processArray(['x'])); // 'MISSING'
770
+ *
771
+ * // Advanced curried usage with transformation pipelines
772
+ * const extractAndProcess = pipe([
773
+ * ['hello', 'world', 'typescript'],
774
+ * ['functional', 'programming'],
775
+ * ['type', 'safety', 'matters', 'most']
776
+ * ])
777
+ * .map(arr => arr.map(getSecondElement))
778
+ * .map(opts => opts.map(opt => Optional.unwrapOr(opt, '[missing]')))
779
+ * .value;
780
+ * // [['world'], ['[missing]'], ['safety']]
781
+ *
782
+ * // Type inference examples
783
+ * expectType<typeof first, Optional<string>>('=');
784
+ * expectType<typeof getSecondElement, <T>(array: readonly T[]) => Optional<T>>('=');
785
+ * expectType<typeof negativeOutOfBounds, Optional<string>>('=');
786
+ * ```
787
+ *
788
+ * @see {@link head} for getting the first element specifically
789
+ * @see {@link last} for getting the last element specifically
790
+ * @see {@link Optional} for working with the returned Optional values
791
+ * @see {@link Optional.unwrapOr} for safe unwrapping with defaults
792
+ * @see {@link Optional.map} for transforming Optional values
793
+ */
794
+ export const at: AtFnOverload;
795
+ /**
796
+ * Function type for safely accessing an array element at a given index.
797
+ */
798
+ type AtFnOverload = {
799
+ <E>(array: readonly E[], index: SizeType.ArgArr): Optional<E>;
800
+ (index: SizeType.ArgArr): <E>(array: readonly E[]) => Optional<E>;
801
+ };
802
+ /**
803
+ * Returns the first element of an array wrapped in an Optional.
804
+ *
805
+ * This function provides type-safe access to the first element with precise return types:
806
+ * - For empty arrays: returns `Optional.None`
807
+ * - For tuples with known first element: returns `Optional.Some<FirstElementType>`
808
+ * - For non-empty arrays: returns `Optional.Some<ElementType>`
809
+ * - For general arrays: returns `Optional<ElementType>`
810
+ *
811
+ * The function leverages TypeScript's type system to provide the most precise return type
812
+ * based on the input array type, making it safer than direct indexing.
813
+ *
814
+ * @template E The type of elements in the array.
815
+ * @param array The array to get the first element from.
816
+ * @returns An Optional containing the first element:
817
+ * - `Optional.None` if the array is empty
818
+ * - `Optional.Some<E>` containing the first element if the array is non-empty
819
+ *
820
+ * @example
821
+ * ```typescript
822
+ * // Empty array - precise None type
823
+ * const emptyResult = Arr.head([]); // Optional.None
824
+ * console.log(Optional.isNone(emptyResult)); // true
825
+ *
826
+ * // Tuple with known structure - precise Some type
827
+ * const tupleResult = Arr.head(['first', 'second', 'third'] as const);
828
+ * // Type: Optional.Some<'first'>
829
+ * if (Optional.isSome(tupleResult)) {
830
+ * console.log(tupleResult.value); // 'first' - TypeScript knows exact type
831
+ * }
832
+ *
833
+ * // Non-empty array - guaranteed Some type
834
+ * const nonEmpty: NonEmptyArray<number> = [10, 20, 30] as NonEmptyArray<number>;
835
+ * const guaranteedResult = Arr.head(nonEmpty); // Optional.Some<number>
836
+ * // No need to check - always Some for NonEmptyArray
837
+ *
838
+ * // General array - may be Some or None
839
+ * const generalArray: number[] = [1, 2, 3];
840
+ * const maybeResult = Arr.head(generalArray); // Optional<number>
841
+ * if (Optional.isSome(maybeResult)) {
842
+ * console.log(`First element: ${maybeResult.value}`);
843
+ * } else {
844
+ * console.log('Array is empty');
845
+ * }
846
+ *
847
+ * // Working with different types
848
+ * const strings = ['hello', 'world'];
849
+ * const firstString = Arr.head(strings); // Optional<string>
850
+ *
851
+ * const objects = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
852
+ * const firstObject = Arr.head(objects); // Optional<{id: number, name: string}>
853
+ *
854
+ * // Functional composition
855
+ * const getFirstElements = (arrays: readonly number[][]) =>
856
+ * arrays.map(Arr.head).filter(Optional.isSome);
857
+ *
858
+ * const nestedArrays = [[1, 2], [3, 4], [], [5]];
859
+ * const firstElements = getFirstElements(nestedArrays);
860
+ * // [Optional.Some(1), Optional.Some(3), Optional.Some(5)]
861
+ *
862
+ * // Type inference examples
863
+ * expectType<typeof emptyResult, Optional.None>('=');
864
+ * expectType<typeof tupleResult, Optional.Some<'first'>>('=');
865
+ * expectType<typeof guaranteedResult, Optional.Some<number>>('=');
866
+ * expectType<typeof maybeResult, Optional<number>>('=');
867
+ * ```
868
+ *
869
+ * @see {@link last} for getting the last element
870
+ * @see {@link at} for accessing elements at specific indices
871
+ * @see {@link tail} for getting all elements except the first
872
+ */
873
+ export const head: HeadFnOverload;
874
+ type HeadFnOverload = {
875
+ /**
876
+ * Get head of empty array.
877
+ */
878
+ (array: readonly []): Optional.None;
879
+ /**
880
+ * Get head of tuple.
881
+ */
882
+ <E, L extends readonly unknown[]>(array: readonly [E, ...L]): Optional.Some<E>;
883
+ /**
884
+ * Get head of non-empty array.
885
+ */
886
+ <E>(array: NonEmptyArray<E>): Optional.Some<E>;
887
+ /**
888
+ * Get head of any array.
889
+ */
890
+ <E>(array: readonly E[]): Optional<E>;
891
+ };
892
+ /**
893
+ * Returns the last element of an array wrapped in an Optional.
894
+ *
895
+ * This function provides type-safe access to the last element with precise return types:
896
+ * - For empty arrays: returns `Optional.None`
897
+ * - For tuples with known last element: returns `Optional.Some<LastElementType>`
898
+ * - For non-empty arrays: returns `Optional.Some<ElementType>`
899
+ * - For general arrays: returns `Optional<ElementType>`
900
+ *
901
+ * The function leverages TypeScript's type system to provide the most precise return type
902
+ * based on the input array type, making it safer than direct indexing.
903
+ *
904
+ * @template E The type of elements in the array.
905
+ * @param array The array to get the last element from.
906
+ * @returns An Optional containing the last element:
907
+ * - `Optional.None` if the array is empty
908
+ * - `Optional.Some<E>` containing the last element if the array is non-empty
909
+ *
910
+ * @example
911
+ * ```typescript
912
+ * // Empty array - precise None type
913
+ * const emptyResult = Arr.last([]); // Optional.None
914
+ * console.log(Optional.isNone(emptyResult)); // true
915
+ *
916
+ * // Tuple with known structure - precise Some type
917
+ * const tupleResult = Arr.last(['first', 'middle', 'last'] as const);
918
+ * // Type: Optional.Some<'last'>
919
+ * if (Optional.isSome(tupleResult)) {
920
+ * console.log(tupleResult.value); // 'last' - TypeScript knows exact type
921
+ * }
922
+ *
923
+ * // Non-empty array - guaranteed Some type
924
+ * const nonEmpty: NonEmptyArray<number> = [10, 20, 30] as NonEmptyArray<number>;
925
+ * const guaranteedResult = Arr.last(nonEmpty); // Optional.Some<number>
926
+ * // No need to check - always Some for NonEmptyArray
927
+ *
928
+ * // General array - may be Some or None
929
+ * const generalArray: number[] = [1, 2, 3];
930
+ * const maybeResult = Arr.last(generalArray); // Optional<number>
931
+ * if (Optional.isSome(maybeResult)) {
932
+ * console.log(`Last element: ${maybeResult.value}`);
933
+ * } else {
934
+ * console.log('Array is empty');
935
+ * }
936
+ *
937
+ * // Working with different types
938
+ * const strings = ['hello', 'world', 'example'];
939
+ * const lastString = Arr.last(strings); // Optional<string>
940
+ *
941
+ * const coordinates = [{x: 0, y: 0}, {x: 1, y: 1}, {x: 2, y: 2}];
942
+ * const lastCoordinate = Arr.last(coordinates); // Optional<{x: number, y: number}>
943
+ *
944
+ * // Single element arrays
945
+ * const single = [42];
946
+ * const singleResult = Arr.last(single); // Optional<number> containing 42
947
+ *
948
+ * // Functional composition with arrays of arrays
949
+ * const getLastElements = (arrays: readonly string[][]) =>
950
+ * arrays.map(Arr.last).filter(Optional.isSome);
951
+ *
952
+ * const nestedArrays = [['a', 'b'], ['c'], [], ['d', 'e', 'f']];
953
+ * const lastElements = getLastElements(nestedArrays);
954
+ * // [Optional.Some('b'), Optional.Some('c'), Optional.Some('f')]
955
+ *
956
+ * // Common pattern: get last element or default
957
+ * const data = [10, 20, 30];
958
+ * const lastOrDefault = Optional.unwrapOr(Arr.last(data), 0); // 30
959
+ * const emptyLastOrDefault = Optional.unwrapOr(Arr.last([]), 0); // 0
960
+ *
961
+ * // Type inference examples
962
+ * expectType<typeof emptyResult, Optional.None>('=');
963
+ * expectType<typeof tupleResult, Optional.Some<'last'>>('=');
964
+ * expectType<typeof guaranteedResult, Optional.Some<number>>('=');
965
+ * expectType<typeof maybeResult, Optional<number>>('=');
966
+ * ```
967
+ *
968
+ * @see {@link head} for getting the first element
969
+ * @see {@link at} for accessing elements at specific indices with negative indexing support
970
+ * @see {@link butLast} for getting all elements except the last
971
+ */
972
+ export const last: LastFnOverload;
973
+ type LastFnOverload = {
974
+ /**
975
+ * Get last of empty array.
976
+ */
977
+ (array: readonly []): Optional.None;
978
+ /**
979
+ * Get last of tuple.
980
+ */
981
+ <Ar extends readonly unknown[], L>(array: readonly [...Ar, L]): Optional.Some<L>;
982
+ /**
983
+ * Get last of non-empty array.
984
+ */
985
+ <E>(array: NonEmptyArray<E>): Optional.Some<E>;
986
+ /**
987
+ * Get last of any array.
988
+ */
989
+ <E>(array: readonly E[]): Optional<E>;
990
+ };
991
+ /**
992
+ * Slices an array with automatically clamped start and end indices for safe bounds handling.
993
+ *
994
+ * This function provides a safer alternative to `Array.slice()` by automatically clamping
995
+ * the start and end indices to valid bounds, preventing out-of-bounds access and ensuring
996
+ * consistent behavior regardless of input values.
997
+ *
998
+ * **Clamping Behavior:**
999
+ * - `start` is clamped to `[0, array.length]`
1000
+ * - `end` is clamped to `[clampedStart, array.length]` (ensuring end ≥ start)
1001
+ * - Invalid ranges (start > end after clamping) return empty arrays
1002
+ * - Negative indices are clamped to 0, large indices are clamped to array.length
1003
+ *
1004
+ * **Curried Usage:** This function supports currying - when called with only start and end
1005
+ * indices, it returns a function that can be applied to arrays.
1006
+ *
1007
+ * @template E The type of elements in the array.
1008
+ * @param array The array to slice (when using direct call syntax).
1009
+ * @param start The start index for the slice (inclusive). Will be clamped to valid bounds.
1010
+ * @param end The end index for the slice (exclusive). Will be clamped to valid bounds.
1011
+ * @returns A new immutable array containing the sliced elements. Always returns a valid array,
1012
+ * never throws for out-of-bounds indices.
1013
+ *
1014
+ * @example
1015
+ * ```typescript
1016
+ * const data = [10, 20, 30, 40, 50];
1017
+ *
1018
+ * // Normal slicing
1019
+ * const middle = Arr.sliceClamped(data, 1, 4); // [20, 30, 40]
1020
+ * const beginning = Arr.sliceClamped(data, 0, 2); // [10, 20]
1021
+ * const end = Arr.sliceClamped(data, 3, 5); // [40, 50]
1022
+ *
1023
+ * // Automatic clamping for out-of-bounds indices
1024
+ * const clampedStart = Arr.sliceClamped(data, -10, 3); // [10, 20, 30] (start clamped to 0)
1025
+ * const clampedEnd = Arr.sliceClamped(data, 2, 100); // [30, 40, 50] (end clamped to length)
1026
+ * const bothClamped = Arr.sliceClamped(data, -5, 100); // [10, 20, 30, 40, 50] (entire array)
1027
+ *
1028
+ * // Invalid ranges become empty arrays
1029
+ * const emptyReversed = Arr.sliceClamped(data, 4, 1); // [] (start > end after clamping)
1030
+ * const emptyAtEnd = Arr.sliceClamped(data, 5, 10); // [] (start at end of array)
1031
+ *
1032
+ * // Edge cases
1033
+ * const emptyArray = Arr.sliceClamped([], 0, 5); // [] (empty input)
1034
+ * const singleElement = Arr.sliceClamped([42], 0, 1); // [42]
1035
+ * const fullCopy = Arr.sliceClamped(data, 0, data.length); // [10, 20, 30, 40, 50]
1036
+ *
1037
+ * // Curried usage for functional composition
1038
+ * const takeFirst3 = Arr.sliceClamped(0, 3);
1039
+ * const getMiddle2 = Arr.sliceClamped(1, 3);
1040
+ *
1041
+ * const arrays = [
1042
+ * [1, 2, 3, 4, 5],
1043
+ * [10, 20],
1044
+ * [100, 200, 300, 400, 500, 600]
1045
+ * ];
1046
+ *
1047
+ * const first3Elements = arrays.map(takeFirst3);
1048
+ * // [[1, 2, 3], [10, 20], [100, 200, 300]]
1049
+ *
1050
+ * const middle2Elements = arrays.map(getMiddle2);
1051
+ * // [[2, 3], [20], [200, 300]]
1052
+ *
1053
+ * // Pipe composition
1054
+ * const result = pipe([1, 2, 3, 4, 5, 6])
1055
+ * .map(takeFirst3)
1056
+ * .map(Arr.sum)
1057
+ * .value; // 6 (sum of [1, 2, 3])
1058
+ *
1059
+ * // Comparison with regular Array.slice (which can throw or behave unexpectedly)
1060
+ * try {
1061
+ * // Regular slice with out-of-bounds - works but may be unintuitive
1062
+ * const regularSlice = data.slice(-10, 100); // [10, 20, 30, 40, 50]
1063
+ * // sliceClamped provides same safe behavior explicitly
1064
+ * const clampedSlice = Arr.sliceClamped(data, -10, 100); // [10, 20, 30, 40, 50]
1065
+ * } catch (error) {
1066
+ * // sliceClamped never throws
1067
+ * }
1068
+ * ```
1069
+ *
1070
+ * @see {@link take} for taking the first N elements
1071
+ * @see {@link skip} for skipping the first N elements
1072
+ * @see {@link takeLast} for taking the last N elements
1073
+ */
1074
+ export const sliceClamped: SliceClampedFnOverload;
1075
+ type SliceClampedFnOverload = {
1076
+ <E>(array: readonly E[], start: SizeType.ArgArr, end: SizeType.ArgArr): readonly E[];
1077
+ (start: SizeType.ArgArr, end: SizeType.ArgArr): <E>(array: readonly E[]) => readonly E[];
1078
+ };
1079
+ /**
1080
+ * Returns all elements of an array except the first one.
1081
+ * @template E The type of the array (can be a tuple for more precise typing).
1082
+ * @param array The input array.
1083
+ * @returns A new array containing all elements except the first. The type is inferred as `List.Tail<T>`.
1084
+ * @example
1085
+ * ```ts
1086
+ * Arr.tail([1, 2, 3] as const); // [2, 3]
1087
+ * Arr.tail([1] as const); // []
1088
+ * Arr.tail([]); // []
1089
+ * ```
1090
+ */
1091
+ export const tail: <Ar extends readonly unknown[]>(array: Ar) => List.Tail<Ar>;
1092
+ /**
1093
+ * Returns all elements of an array except the last one.
1094
+ * @template E The type of the array (can be a tuple for more precise typing).
1095
+ * @param array The input array.
1096
+ * @returns A new array containing all elements except the last. The type is inferred as `List.ButLast<T>`.
1097
+ * @example
1098
+ * ```ts
1099
+ * Arr.butLast([1, 2, 3] as const); // [1, 2]
1100
+ * Arr.butLast([1] as const); // []
1101
+ * Arr.butLast([]); // []
1102
+ * ```
1103
+ */
1104
+ export const butLast: <Ar extends readonly unknown[]>(array: Ar) => List.ButLast<Ar>;
1105
+ /**
1106
+ * Takes the first N elements from an array.
1107
+ *
1108
+ * - If the array is a tuple, the return type is inferred as a tuple of the first N elements.
1109
+ * - If the array is a NonEmptyArray and N is a SizeType.ArgArrPositive, returns a NonEmptyArray.
1110
+ * - Otherwise, returns a readonly array of up to N elements.
1111
+ *
1112
+ * @template E The type of the array (can be a tuple for more precise typing).
1113
+ * @template N The number of elements to take, constrained to `SmallUint`.
1114
+ * @param array The input array.
1115
+ * @param num The number of elements to take.
1116
+ * @returns A new array containing the first N elements.
1117
+ * @example
1118
+ * ```ts
1119
+ * // Regular usage
1120
+ * Arr.take([1, 2, 3, 4] as const, 2); // [1, 2]
1121
+ *
1122
+ * // Curried usage for pipe composition
1123
+ * const takeFirst3 = Arr.take(3);
1124
+ * const result = pipe([1, 2, 3, 4, 5]).map(takeFirst3).value;
1125
+ * console.log(result); // [1, 2, 3]
1126
+ * ```
1127
+ */
1128
+ export const take: TakeFnOverload;
1129
+ type TakeFnOverload = {
1130
+ <Ar extends readonly unknown[], N extends SmallUint>(array: Ar, num: N): List.Take<N, Ar>;
1131
+ <N extends SmallUint>(num: N): <Ar extends readonly unknown[]>(array: Ar) => List.Take<N, Ar>;
1132
+ <E>(array: NonEmptyArray<E>, num: SizeType.ArgArrPositive): NonEmptyArray<E>;
1133
+ (num: SizeType.ArgArrPositive): <E>(array: NonEmptyArray<E>) => NonEmptyArray<E>;
1134
+ <E>(array: readonly E[], num: SizeType.ArgArrNonNegative): readonly E[];
1135
+ (num: SizeType.ArgArrNonNegative): <E>(array: readonly E[]) => readonly E[];
1136
+ };
1137
+ /**
1138
+ * Takes the last N elements from an array.
1139
+ *
1140
+ * - If the array is a tuple, the return type is inferred as a tuple of the last N elements.
1141
+ * - If the array is a non-empty array and N is a positive integer, returns a non-empty array.
1142
+ * - Otherwise, returns a readonly array of up to N elements.
1143
+ *
1144
+ * @template E The type of the array (can be a tuple for more precise typing).
1145
+ * @template N The number of elements to take, constrained to `SmallUint`.
1146
+ * @param array The input array.
1147
+ * @param num The number of elements to take.
1148
+ * @returns A new array containing the last N elements.
1149
+ * @example
1150
+ * ```ts
1151
+ * // Regular usage
1152
+ * Arr.takeLast([1, 2, 3, 4] as const, 2); // [3, 4]
1153
+ *
1154
+ * // Curried usage for pipe composition
1155
+ * const takeLast2 = Arr.takeLast(2);
1156
+ * const result = pipe([1, 2, 3, 4, 5]).map(takeLast2).value;
1157
+ * console.log(result); // [4, 5]
1158
+ * ```
1159
+ */
1160
+ export const takeLast: TakeLastFnOverload;
1161
+ type TakeLastFnOverload = {
1162
+ <Ar extends readonly unknown[], N extends SmallUint>(array: Ar, num: N): List.TakeLast<N, Ar>;
1163
+ <N extends SmallUint>(num: N): <Ar extends readonly unknown[]>(array: Ar) => List.TakeLast<N, Ar>;
1164
+ <E>(array: NonEmptyArray<E>, num: SizeType.ArgArrPositive): NonEmptyArray<E>;
1165
+ (num: SizeType.ArgArrPositive): <E>(array: NonEmptyArray<E>) => NonEmptyArray<E>;
1166
+ <E>(array: readonly E[], num: SizeType.ArgArrNonNegative): readonly E[];
1167
+ (num: SizeType.ArgArrNonNegative): <E>(array: readonly E[]) => readonly E[];
1168
+ };
1169
+ /**
1170
+ * Skips the first N elements of an array.
1171
+ *
1172
+ * - If the array is a tuple, the return type is inferred as a tuple with the first N elements removed.
1173
+ * - If the array is a non-empty array and N is a positive integer, returns a readonly array (may be empty).
1174
+ * - Otherwise, returns a readonly array with the first N elements skipped.
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 skip, constrained to `SmallUint`.
1178
+ * @param array The input array.
1179
+ * @param num The number of elements to skip.
1180
+ * @returns A new array containing the elements after skipping the first N.
1181
+ * @example
1182
+ * ```ts
1183
+ * // Regular usage
1184
+ * Arr.skip([1, 2, 3, 4] as const, 2); // [3, 4]
1185
+ *
1186
+ * // Curried usage for pipe composition
1187
+ * const skipFirst2 = Arr.skip(2);
1188
+ * const result = pipe([1, 2, 3, 4, 5]).map(skipFirst2).value;
1189
+ * console.log(result); // [3, 4, 5]
1190
+ * ```
1191
+ */
1192
+ export const skip: SkipFnOverload;
1193
+ type SkipFnOverload = {
1194
+ <Ar extends readonly unknown[], N extends SmallUint>(array: Ar, num: N): List.Skip<N, Ar>;
1195
+ <E>(array: NonEmptyArray<E>, num: SizeType.ArgArrPositive): readonly E[];
1196
+ <E>(array: readonly E[], num: SizeType.ArgArrNonNegative): readonly E[];
1197
+ <N extends SmallUint>(num: N): <Ar extends readonly unknown[]>(array: Ar) => List.Skip<N, Ar>;
1198
+ (num: SizeType.ArgArrPositive): <E>(array: NonEmptyArray<E>) => readonly E[];
1199
+ (num: SizeType.ArgArrNonNegative): <E>(array: readonly E[]) => readonly E[];
1200
+ };
1201
+ /**
1202
+ * Skips the last N elements of an array.
1203
+ *
1204
+ * - If the array is a tuple, the return type is inferred as a tuple with the last N elements removed.
1205
+ * - If the array is a non-empty array and N is a positive integer, returns a readonly array (may be empty).
1206
+ * - Otherwise, returns a readonly array with the last N elements skipped.
1207
+ *
1208
+ * @template E The type of the array (can be a tuple for more precise typing).
1209
+ * @template N The number of elements to skip, constrained to `SmallUint`.
1210
+ * @param array The input array.
1211
+ * @param num The number of elements to skip from the end.
1212
+ * @returns A new array containing the elements after skipping the last N.
1213
+ * @example
1214
+ * ```ts
1215
+ * // Regular usage
1216
+ * Arr.skipLast([1, 2, 3, 4] as const, 2); // [1, 2]
1217
+ *
1218
+ * // Curried usage for pipe composition
1219
+ * const skipLast2 = Arr.skipLast(2);
1220
+ * const result = pipe([1, 2, 3, 4, 5]).map(skipLast2).value;
1221
+ * console.log(result); // [1, 2, 3]
1222
+ * ```
1223
+ */
1224
+ export const skipLast: SkipLastFnOverload;
1225
+ type SkipLastFnOverload = {
1226
+ <Ar extends readonly unknown[], N extends SmallUint>(array: Ar, num: N): List.SkipLast<N, Ar>;
1227
+ <E>(array: readonly E[], num: SizeType.ArgArrNonNegative): readonly E[];
1228
+ <N extends SmallUint>(num: N): <Ar extends readonly unknown[]>(array: Ar) => List.SkipLast<N, Ar>;
1229
+ (num: SizeType.ArgArrNonNegative): <E>(array: readonly E[]) => readonly E[];
1230
+ };
1231
+ /**
1232
+ * Returns a new array with the element at the specified index updated by a function.
1233
+ *
1234
+ * This function provides immutable array updates with type-safe bounds checking. It applies an updater
1235
+ * function to the element at the given index and returns a new array with the transformed value.
1236
+ * The original array is never modified, ensuring immutability.
1237
+ *
1238
+ * **Type Union Behavior:** When the updater function returns a different type `U` than the original
1239
+ * element type `E`, the result type becomes `readonly (E | U)[]` to accommodate both original and
1240
+ * updated element types. This ensures type safety when elements have different types after updating.
1241
+ *
1242
+ * **Bounds Checking:** Unlike native array access which can cause runtime errors, this function
1243
+ * performs safe bounds checking:
1244
+ * - **Valid index:** Creates new array with updated element
1245
+ * - **Invalid index:** Returns the original array unchanged (no errors thrown)
1246
+ * - **Negative index:** Treated as invalid (returns original array)
1247
+ *
1248
+ * **Curried Usage:** Supports currying for functional composition - when called with only index and
1249
+ * updater, returns a reusable function that can be applied to arrays.
1250
+ *
1251
+ * @template E The type of elements in the original array.
1252
+ * @template U The type of the value returned by the updater function.
1253
+ * @param array The input array to update. Can be any readonly array.
1254
+ * @param index The index of the element to update. Must be a non-negative {@link SizeType.ArgArrNonNegative}.
1255
+ * - **Valid range:** `0 <= index < array.length`
1256
+ * - **Out of bounds:** Returns original array unchanged
1257
+ * - **Negative values:** Not allowed by type system (non-negative constraint)
1258
+ * @param updater A function `(prev: E) => U` that transforms the existing element:
1259
+ * - **prev:** The current element at the specified index
1260
+ * - **returns:** The new value to place at that index (can be different type)
1261
+ * @returns A new `readonly (E | U)[]` array where:
1262
+ * - All elements except the target index remain unchanged (type `E`)
1263
+ * - The element at the target index is replaced with the updater result (type `U`)
1264
+ * - Type union `E | U` accommodates both original and updated element types
1265
+ * - If index is out of bounds, returns the original array unchanged
1266
+ *
1267
+ * @example
1268
+ * ```typescript
1269
+ * // Basic usage with same type transformation
1270
+ * const numbers = [1, 2, 3, 4, 5];
1271
+ * const doubled = Arr.toUpdated(numbers, 2, x => x * 2);
1272
+ * // readonly number[] -> [1, 2, 6, 4, 5]
1273
+ *
1274
+ * // Type union when updater returns different type
1275
+ * const mixed = Arr.toUpdated(numbers, 1, x => `value: ${x}`);
1276
+ * // readonly (number | string)[] -> [1, 'value: 2', 3, 4, 5]
1277
+ *
1278
+ * // Complex object updates
1279
+ * const users = [
1280
+ * { id: 1, name: 'Alice', active: true },
1281
+ * { id: 2, name: 'Bob', active: false },
1282
+ * { id: 3, name: 'Charlie', active: true }
1283
+ * ];
1284
+ *
1285
+ * const activatedUser = Arr.toUpdated(users, 1, user => ({
1286
+ * ...user,
1287
+ * active: true,
1288
+ * lastUpdated: new Date()
1289
+ * }));
1290
+ * // Bob is now active with lastUpdated field
1291
+ *
1292
+ * // Bounds checking behavior
1293
+ * const safe1 = Arr.toUpdated([1, 2, 3], 10, x => x * 2); // [1, 2, 3] (index out of bounds)
1294
+ * const safe2 = Arr.toUpdated([1, 2, 3], 0, x => x * 2); // [2, 2, 3] (valid index)
1295
+ * const safe3 = Arr.toUpdated([], 0, x => x); // [] (empty array, index out of bounds)
1296
+ *
1297
+ * // Functional transformations
1298
+ * const products = [
1299
+ * { name: 'laptop', price: 1000 },
1300
+ * { name: 'mouse', price: 25 },
1301
+ * { name: 'keyboard', price: 75 }
1302
+ * ];
1303
+ *
1304
+ * const discounted = Arr.toUpdated(products, 0, product => ({
1305
+ * ...product,
1306
+ * price: Math.round(product.price * 0.8), // 20% discount
1307
+ * onSale: true
1308
+ * }));
1309
+ * // First product now has discounted price and onSale flag
1310
+ *
1311
+ * // Curried usage for reusable updates
1312
+ * const doubleAtIndex2 = Arr.toUpdated(2, (x: number) => x * 2);
1313
+ * const capitalizeAtIndex0 = Arr.toUpdated(0, (s: string) => s.toUpperCase());
1314
+ * const markCompleteAtIndex = (index: number) =>
1315
+ * Arr.toUpdated(index, (task: {done: boolean}) => ({...task, done: true}));
1316
+ *
1317
+ * const numberArrays = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
1318
+ * const allDoubled = numberArrays.map(doubleAtIndex2);
1319
+ * // [[1, 2, 6], [4, 5, 12], [7, 8, 18]]
1320
+ *
1321
+ * const words = [['hello', 'world'], ['foo', 'bar'], ['type', 'script']];
1322
+ * const capitalized = words.map(capitalizeAtIndex0);
1323
+ * // [['HELLO', 'world'], ['FOO', 'bar'], ['TYPE', 'script']]
1324
+ *
1325
+ * // Pipe composition for data processing
1326
+ * const processArray = (arr: readonly number[]) => pipe(arr)
1327
+ * .map(Arr.toUpdated(0, x => x * 10)) // Scale first element
1328
+ * .map(Arr.toUpdated(1, x => typeof x === 'number' ? x + 100 : x)) // Add to second if number
1329
+ * .value;
1330
+ *
1331
+ * console.log(processArray([1, 2, 3])); // [10, 102, 3]
1332
+ *
1333
+ * // Multiple sequential updates
1334
+ * const pipeline = (data: readonly number[]) => pipe(data)
1335
+ * .map(Arr.toUpdated(0, x => x * 2))
1336
+ * .map(Arr.toUpdated(1, x => typeof x === 'number' ? x + 10 : x))
1337
+ * .map(Arr.toUpdated(2, x => typeof x === 'number' ? x.toString() : x))
1338
+ * .value;
1339
+ *
1340
+ * console.log(pipeline([1, 2, 3])); // [2, 12, '3'] - readonly (number | string)[]
1341
+ *
1342
+ * // Error-safe updates in data processing
1343
+ * const safeUpdate = <T, U>(
1344
+ * array: readonly T[],
1345
+ * index: number,
1346
+ * updater: (value: T) => U
1347
+ * ) => {
1348
+ * if (index < 0 || index >= array.length) {
1349
+ * console.warn(`Index ${index} out of bounds for array of length ${array.length}`);
1350
+ * return array;
1351
+ * }
1352
+ * return Arr.toUpdated(array, index as SizeType.ArgArrNonNegative, updater);
1353
+ * };
1354
+ *
1355
+ * // Advanced: State management pattern
1356
+ * type AppState = {
1357
+ * users: Array<{id: number, name: string}>;
1358
+ * currentUserId: number;
1359
+ * };
1360
+ *
1361
+ * const updateUserName = (state: AppState, userId: number, newName: string): AppState => {
1362
+ * const userIndex = state.users.findIndex(u => u.id === userId);
1363
+ * if (userIndex === -1) return state;
1364
+ *
1365
+ * return {
1366
+ * ...state,
1367
+ * users: Arr.toUpdated(state.users, userIndex as SizeType.ArgArrNonNegative, user => ({
1368
+ * ...user,
1369
+ * name: newName
1370
+ * }))
1371
+ * };
1372
+ * };
1373
+ *
1374
+ * // Type inference examples showing union types
1375
+ * expectType<typeof doubled, readonly number[]>('='); // Same type
1376
+ * expectType<typeof mixed, readonly (number | string)[]>('='); // Union type
1377
+ * expectType<typeof doubleAtIndex2, <T extends readonly number[]>(array: T) => readonly (number | number)[]>('=');
1378
+ * expectType<typeof safe1, readonly number[]>('='); // Bounds check preserves type
1379
+ * ```
1380
+ *
1381
+ * @see {@link Array.prototype.with} for the native method with different error handling
1382
+ * @see {@link SizeType.ArgArrNonNegative} for the index type constraint
1383
+ * @see Immutable update patterns for functional programming approaches
1384
+ */
1385
+ export const toUpdated: ToUpdatedFnOverload;
1386
+ type ToUpdatedFnOverload = {
1387
+ <E, U>(array: readonly E[], index: SizeType.ArgArrNonNegative, updater: (prev: E) => U): readonly (E | U)[];
1388
+ <E, U>(index: SizeType.ArgArrNonNegative, updater: (prev: E) => U): (array: readonly E[]) => readonly (E | U)[];
1389
+ };
1390
+ /**
1391
+ * Returns a new array with a new value inserted at the specified index.
1392
+ * Index can be out of bounds (e.g., negative or greater than length), `toSpliced` handles this.
1393
+ * @template E The type of elements in the array.
1394
+ * @param array The input array.
1395
+ * @param index The index at which to insert the new value.
1396
+ * @param newValue The value to insert.
1397
+ * @returns A new array with the value inserted.
1398
+ * @example
1399
+ * ```ts
1400
+ * // Regular usage
1401
+ * Arr.toInserted([1, 2, 3], 1, 10); // [1, 10, 2, 3]
1402
+ *
1403
+ * // Curried usage for pipe composition
1404
+ * const insertAtStart = Arr.toInserted(0, 99);
1405
+ * const result = pipe([1, 2, 3]).map(insertAtStart).value;
1406
+ * console.log(result); // [99, 1, 2, 3]
1407
+ * ```
1408
+ */
1409
+ export const toInserted: ToInsertedFnOverload;
1410
+ type ToInsertedFnOverload = {
1411
+ <E, const V = E>(array: readonly E[], index: SizeType.ArgArrNonNegative, newValue: V): NonEmptyArray<E | V>;
1412
+ <E, const V = E>(index: SizeType.ArgArrNonNegative, newValue: V): (array: readonly E[]) => NonEmptyArray<E | V>;
1413
+ };
1414
+ /**
1415
+ * Returns a new array with the element at the specified index removed.
1416
+ * If index is out of bounds, `toSpliced` handles this (usually by returning a copy).
1417
+ * @template E The type of elements in the array.
1418
+ * @param array The input array.
1419
+ * @param index The index of the element to remove.
1420
+ * @returns A new array with the element removed.
1421
+ * @example
1422
+ * ```ts
1423
+ * // Regular usage
1424
+ * Arr.toRemoved([1, 2, 3], 1); // [1, 3]
1425
+ *
1426
+ * // Curried usage for pipe composition
1427
+ * const removeFirst = Arr.toRemoved(0);
1428
+ * const result = pipe([10, 20, 30]).map(removeFirst).value;
1429
+ * console.log(result); // [20, 30]
1430
+ * ```
1431
+ */
1432
+ export const toRemoved: ToRemovedFnOverload;
1433
+ type ToRemovedFnOverload = {
1434
+ <E>(array: readonly E[], index: SizeType.ArgArrNonNegative): readonly E[];
1435
+ (index: SizeType.ArgArrNonNegative): <E>(array: readonly E[]) => readonly E[];
1436
+ };
1437
+ /**
1438
+ * Returns a new array with a value added to the end.
1439
+ * @template E The type of the input array (can be a tuple).
1440
+ * @template V The type of the value to add.
1441
+ * @param array The input array.
1442
+ * @param newValue The value to add.
1443
+ * @returns A new array with the value added to the end. Type is `readonly [...E, V]`.
1444
+ * @example
1445
+ * ```ts
1446
+ * // Regular usage
1447
+ * Arr.toPushed([1, 2] as const, 3); // [1, 2, 3]
1448
+ *
1449
+ * // Curried usage for pipe composition
1450
+ * const addZero = Arr.toPushed(0);
1451
+ * const result = pipe([1, 2, 3]).map(addZero).value;
1452
+ * console.log(result); // [1, 2, 3, 0]
1453
+ * ```
1454
+ */
1455
+ export const toPushed: ToPushedFnOverload;
1456
+ type ToPushedFnOverload = {
1457
+ <Ar extends readonly unknown[], const V>(array: Ar, newValue: V): readonly [...Ar, V];
1458
+ <const V>(newValue: V): <Ar extends readonly unknown[]>(array: Ar) => readonly [...Ar, V];
1459
+ };
1460
+ /**
1461
+ * Returns a new array with a value added to the beginning.
1462
+ * @template E The type of the input array (can be a tuple).
1463
+ * @template V The type of the value to add.
1464
+ * @param array The input array.
1465
+ * @param newValue The value to add.
1466
+ * @returns A new array with the value added to the beginning. Type is `readonly [V, ...E]`.
1467
+ * @example
1468
+ * ```ts
1469
+ * // Regular usage
1470
+ * Arr.toUnshifted([1, 2] as const, 0); // [0, 1, 2]
1471
+ *
1472
+ * // Curried usage for pipe composition
1473
+ * const prependZero = Arr.toUnshifted(0);
1474
+ * const result = pipe([1, 2, 3]).map(prependZero).value;
1475
+ * console.log(result); // [0, 1, 2, 3]
1476
+ * ```
1477
+ */
1478
+ export const toUnshifted: ToUnshiftedFnOverload;
1479
+ type ToUnshiftedFnOverload = {
1480
+ <Ar extends readonly unknown[], const V>(array: Ar, newValue: V): readonly [V, ...Ar];
1481
+ <const V>(newValue: V): <Ar extends readonly unknown[]>(array: Ar) => readonly [V, ...Ar];
1482
+ };
1483
+ /**
1484
+ * Fills an array with a value (creates a new filled array).
1485
+ * @param array The array.
1486
+ * @param value The value to fill with.
1487
+ * @param start The start index.
1488
+ * @param end The end index.
1489
+ * @returns A new filled array.
1490
+ * @example
1491
+ * ```typescript
1492
+ * // Regular usage
1493
+ * const arr = [1, 2, 3, 4, 5];
1494
+ * const result = Arr.toFilled(arr, 0, 1, 4);
1495
+ * console.log(result); // [1, 0, 0, 0, 5]
1496
+ *
1497
+ * // Curried usage for pipe composition
1498
+ * const fillWithZeros = Arr.toFilled(0, 1, 3);
1499
+ * const result2 = pipe([1, 2, 3, 4]).map(fillWithZeros).value;
1500
+ * console.log(result2); // [1, 0, 0, 4]
1501
+ * ```
1502
+ */
1503
+ export const toFilled: ToFilledFnOverload;
1504
+ type ToFilledFnOverload = {
1505
+ <E>(array: readonly E[], value: E): readonly E[];
1506
+ <E>(value: E): (array: readonly E[]) => readonly E[];
1507
+ };
1508
+ export const toRangeFilled: ToRangeFilledFnOverload;
1509
+ type ToRangeFilledFnOverload = {
1510
+ <E>(array: readonly E[], value: E, fillRange: readonly [start: SizeType.ArgArr, end: SizeType.ArgArr]): readonly E[];
1511
+ <E>(value: E, fillRange: readonly [start: SizeType.ArgArr, end: SizeType.ArgArr]): (array: readonly E[]) => readonly E[];
1512
+ };
1513
+ /**
1514
+ * Safely finds the first element in an array that satisfies a predicate function.
1515
+ *
1516
+ * This function provides type-safe searching with no risk of runtime errors. It returns
1517
+ * the first element that matches the predicate wrapped in an Optional, or Optional.None
1518
+ * if no element is found. The predicate receives the element, its index, and the entire array.
1519
+ *
1520
+ * **Curried Usage:** This function supports currying - when called with only a predicate,
1521
+ * it returns a function that can be applied to arrays, making it ideal for functional composition.
1522
+ *
1523
+ * @template E The type of elements in the array.
1524
+ * @param array The array to search through (when using direct call syntax).
1525
+ * @param predicate A function that tests each element. Called with:
1526
+ * - `value`: The current element being tested
1527
+ * - `index`: The index of the current element (branded as `SizeType.Arr`)
1528
+ * - `arr`: The entire array being searched
1529
+ * @returns An `Optional<E>` containing:
1530
+ * - `Optional.Some<E>` with the first matching element if found
1531
+ * - `Optional.None` if no element satisfies the predicate
1532
+ *
1533
+ * @example
1534
+ * ```typescript
1535
+ * // Basic element finding
1536
+ * const numbers = [1, 2, 3, 4, 5];
1537
+ * const firstEven = Arr.find(numbers, x => x % 2 === 0);
1538
+ * if (Optional.isSome(firstEven)) {
1539
+ * console.log(firstEven.value); // 2 - first even number
1540
+ * }
1541
+ *
1542
+ * // Finding with index information
1543
+ * const findLargeAtEnd = Arr.find(numbers, (value, index) => value > 3 && index > 2);
1544
+ * // Optional.Some(4) - first number > 3 after index 2
1545
+ *
1546
+ * // Finding objects by property
1547
+ * const users = [
1548
+ * { id: 1, name: 'Alice', age: 25 },
1549
+ * { id: 2, name: 'Bob', age: 30 },
1550
+ * { id: 3, name: 'Charlie', age: 35 }
1551
+ * ];
1552
+ *
1553
+ * const adult = Arr.find(users, user => user.age >= 30);
1554
+ * // Optional.Some({ id: 2, name: 'Bob', age: 30 })
1555
+ *
1556
+ * const nonExistent = Arr.find(users, user => user.age > 100);
1557
+ * // Optional.None
1558
+ *
1559
+ * // Empty array handling
1560
+ * const emptyResult = Arr.find([], x => x > 0); // Optional.None
1561
+ *
1562
+ * // Curried usage for functional composition
1563
+ * const findNegative = Arr.find((x: number) => x < 0);
1564
+ * const findLongString = Arr.find((s: string) => s.length > 5);
1565
+ *
1566
+ * const datasets = [
1567
+ * [1, 2, -3, 4],
1568
+ * [5, 6, 7, 8],
1569
+ * [-1, 0, 1]
1570
+ * ];
1571
+ *
1572
+ * const negativeNumbers = datasets.map(findNegative);
1573
+ * // [Optional.Some(-3), Optional.None, Optional.Some(-1)]
1574
+ *
1575
+ * // Pipe composition
1576
+ * const result = pipe(['short', 'medium', 'very long string'])
1577
+ * .map(findLongString)
1578
+ * .map(opt => Optional.unwrapOr(opt, 'default'))
1579
+ * .value; // 'very long string'
1580
+ *
1581
+ * // Complex predicate with all parameters
1582
+ * const findSpecial = (arr: readonly number[]) =>
1583
+ * Arr.find(arr, (value, index, array) => {
1584
+ * return value > 10 && index > 0 && index < array.length - 1;
1585
+ * });
1586
+ *
1587
+ * const hasMiddleSpecial = findSpecial([5, 15, 20, 3]);
1588
+ * // Optional.Some(15) - first value > 10 that's not at start or end
1589
+ *
1590
+ * // Safe unwrapping patterns
1591
+ * const maybeFound = Arr.find(numbers, x => x > 10);
1592
+ * const foundOrDefault = Optional.unwrapOr(maybeFound, 0); // 0 (not found)
1593
+ * const foundOrThrow = Optional.isSome(maybeFound)
1594
+ * ? maybeFound.value
1595
+ * : (() => { throw new Error('Not found'); })();
1596
+ *
1597
+ * // Type inference examples
1598
+ * expectType<typeof firstEven, Optional<number>>('=');
1599
+ * expectType<typeof adult, Optional<{id: number, name: string, age: number}>>('=');
1600
+ * expectType<typeof findNegative, (array: readonly number[]) => Optional<number>>('=');
1601
+ * ```
1602
+ *
1603
+ * @see {@link findIndex} for finding the index instead of the element
1604
+ * @see {@link indexOf} for finding elements by equality
1605
+ * @see {@link Optional} for working with the returned Optional values
1606
+ */
1607
+ export const find: FindFnOverload;
1608
+ type FindFnOverload = {
1609
+ <E>(array: readonly E[], predicate: (value: E, index: SizeType.Arr, arr: readonly E[]) => boolean): Optional<E>;
1610
+ <E>(predicate: (value: E, index: SizeType.Arr, arr: readonly E[]) => boolean): (array: readonly E[]) => Optional<E>;
1611
+ };
1612
+ /**
1613
+ * Safely finds the index of the first element in an array that satisfies a predicate function.
1614
+ *
1615
+ * This function provides type-safe index searching with no risk of runtime errors. It returns
1616
+ * the index of the first element that matches the predicate wrapped in an Optional, or Optional.None
1617
+ * if no element is found. The returned index is branded as `SizeType.Arr` for type safety.
1618
+ *
1619
+ * **Curried Usage:** This function supports currying - when called with only a predicate,
1620
+ * it returns a function that can be applied to arrays, making it ideal for functional composition.
1621
+ *
1622
+ * @template E The type of elements in the array.
1623
+ * @param array The array to search through (when using direct call syntax).
1624
+ * @param predicate A function that tests each element. Called with:
1625
+ * - `value`: The current element being tested
1626
+ * - `index`: The index of the current element (branded as `SizeType.Arr`)
1627
+ * @returns An `Optional<SizeType.Arr>` containing:
1628
+ * - `Optional.Some<SizeType.Arr>` with the index of the first matching element if found
1629
+ * - `Optional.None` if no element satisfies the predicate
1630
+ *
1631
+ * @example
1632
+ * ```typescript
1633
+ * // Basic index finding
1634
+ * const fruits = ['apple', 'banana', 'cherry', 'banana'];
1635
+ * const bananaIndex = Arr.findIndex(fruits, fruit => fruit === 'banana');
1636
+ * if (Optional.isSome(bananaIndex)) {
1637
+ * console.log(bananaIndex.value); // 1 - index of first 'banana'
1638
+ * }
1639
+ *
1640
+ * // Finding with complex conditions
1641
+ * const numbers = [1, 5, 10, 15, 20];
1642
+ * const firstLargeIndex = Arr.findIndex(numbers, (value, index) =>
1643
+ * value > 10 && index > 1
1644
+ * );
1645
+ * // Optional.Some(3) - index of 15 (first value > 10 after index 1)
1646
+ *
1647
+ * // Finding objects by property
1648
+ * const users = [
1649
+ * { id: 1, active: false },
1650
+ * { id: 2, active: true },
1651
+ * { id: 3, active: true }
1652
+ * ];
1653
+ *
1654
+ * const firstActiveIndex = Arr.findIndex(users, user => user.active);
1655
+ * // Optional.Some(1) - index of first active user
1656
+ *
1657
+ * const inactiveAdminIndex = Arr.findIndex(users, user => !user.active && user.id > 5);
1658
+ * // Optional.None - no inactive user with id > 5
1659
+ *
1660
+ * // Empty array handling
1661
+ * const emptyResult = Arr.findIndex([], x => x > 0); // Optional.None
1662
+ *
1663
+ * // Curried usage for functional composition
1664
+ * const findNegativeIndex = Arr.findIndex((x: number) => x < 0);
1665
+ * const findLongStringIndex = Arr.findIndex((s: string) => s.length > 5);
1666
+ *
1667
+ * const datasets = [
1668
+ * [1, 2, -3, 4], // index 2 has negative
1669
+ * [5, 6, 7, 8], // no negative
1670
+ * [-1, 0, 1] // index 0 has negative
1671
+ * ];
1672
+ *
1673
+ * const negativeIndices = datasets.map(findNegativeIndex);
1674
+ * // [Optional.Some(2), Optional.None, Optional.Some(0)]
1675
+ *
1676
+ * // Using found indices for further operations
1677
+ * const data = ['short', 'medium', 'very long string', 'tiny'];
1678
+ * const longStringIndex = Arr.findIndex(data, s => s.length > 8);
1679
+ *
1680
+ * if (Optional.isSome(longStringIndex)) {
1681
+ * const index = longStringIndex.value;
1682
+ * console.log(`Found at position ${index}: ${data[index]}`);
1683
+ * // "Found at position 2: very long string"
1684
+ * }
1685
+ *
1686
+ * // Pipe composition
1687
+ * const result = pipe(['a', 'bb', 'ccc'])
1688
+ * .map(findLongStringIndex)
1689
+ * .map(opt => Optional.unwrapOr(opt, -1))
1690
+ * .value; // 2 (index of 'ccc')
1691
+ *
1692
+ * // Comparing with native findIndex (which returns -1)
1693
+ * const nativeResult = fruits.findIndex(fruit => fruit === 'grape'); // -1
1694
+ * const safeResult = Arr.findIndex(fruits, fruit => fruit === 'grape'); // Optional.None
1695
+ *
1696
+ * // Safe index usage patterns
1697
+ * const maybeIndex = Arr.findIndex(numbers, x => x > 100);
1698
+ * const indexOrDefault = Optional.unwrapOr(maybeIndex, 0); // 0 (not found)
1699
+ *
1700
+ * // Using index for array access
1701
+ * const foundIndex = Arr.findIndex(fruits, f => f.startsWith('c'));
1702
+ * const foundElement = Optional.isSome(foundIndex)
1703
+ * ? fruits[foundIndex.value]
1704
+ * : 'not found';
1705
+ * // 'cherry'
1706
+ *
1707
+ * // Type inference examples
1708
+ * expectType<typeof bananaIndex, Optional<SizeType.Arr>>('=');
1709
+ * expectType<typeof findNegativeIndex, (array: readonly number[]) => Optional<SizeType.Arr>>('=');
1710
+ * ```
1711
+ *
1712
+ * @see {@link find} for finding the element instead of its index
1713
+ * @see {@link indexOf} for finding elements by equality (not predicate)
1714
+ * @see {@link lastIndexOf} for finding the last occurrence
1715
+ * @see {@link Optional} for working with the returned Optional values
1716
+ */
1717
+ export const findIndex: FindIndexFnOverload;
1718
+ type FindIndexFnOverload = {
1719
+ <E>(array: readonly E[], predicate: (value: E, index: SizeType.Arr) => boolean): SizeType.Arr | -1;
1720
+ <E>(predicate: (value: E, index: SizeType.Arr) => boolean): (array: readonly E[]) => SizeType.Arr | -1;
1721
+ };
1722
+ /**
1723
+ * Gets the index of a value in an array.
1724
+ * @param array The array to search.
1725
+ * @param searchElement The element to search for.
1726
+ * @param fromIndex The index to start searching from.
1727
+ * @returns The index if found, -1 otherwise.
1728
+ * @example
1729
+ * ```typescript
1730
+ * // Regular usage
1731
+ * const arr = ['a', 'b', 'c', 'b'];
1732
+ * const result = Arr.indexOf(arr, 'b');
1733
+ * if (Optional.isSome(result)) {
1734
+ * console.log(result.value); // 1 (branded as SizeType.Arr)
1735
+ * }
1736
+ *
1737
+ * // Curried usage for pipe composition
1738
+ * const findB = Arr.indexOf('b');
1739
+ * const result2 = pipe(['a', 'b', 'c']).map(findB).value;
1740
+ * console.log(Optional.unwrapOr(result2, -1)); // 1
1741
+ * ```
1742
+ */
1743
+ export const indexOf: IndexOfFnOverload;
1744
+ type IndexOfFnOverload = {
1745
+ <E>(array: readonly E[], searchElement: E): SizeType.Arr | -1;
1746
+ <E>(searchElement: E): (array: readonly E[]) => SizeType.Arr | -1;
1747
+ };
1748
+ export const indexOfFrom: IndexOfFromFnOverload;
1749
+ type IndexOfFromFnOverload = {
1750
+ <E>(array: readonly E[], searchElement: E, fromIndex: SizeType.ArgArr): SizeType.Arr | -1;
1751
+ <E>(searchElement: E, fromIndex: SizeType.ArgArr): (array: readonly E[]) => SizeType.Arr | -1;
1752
+ };
1753
+ /**
1754
+ * Gets the last index of a value in an array.
1755
+ * @param array The array to search.
1756
+ * @param searchElement The element to search for.
1757
+ * @param fromIndex The index to start searching from (searches backwards).
1758
+ * @returns Optional.Some with the index if found, Optional.None otherwise.
1759
+ * @example
1760
+ * ```typescript
1761
+ * // Regular usage
1762
+ * const arr = ['a', 'b', 'c', 'b'];
1763
+ * const result = Arr.lastIndexOf(arr, 'b');
1764
+ * if (Optional.isSome(result)) {
1765
+ * console.log(result.value); // 3 (branded as SizeType.Arr)
1766
+ * }
1767
+ *
1768
+ * // Curried usage for pipe composition
1769
+ * const findLastB = Arr.lastIndexOf('b');
1770
+ * const result2 = pipe(['a', 'b', 'c', 'b']).map(findLastB).value;
1771
+ * console.log(Optional.unwrapOr(result2, -1)); // 3
1772
+ * ```
1773
+ */
1774
+ export const lastIndexOf: LastIndexOfFnOverload;
1775
+ type LastIndexOfFnOverload = {
1776
+ <E>(array: readonly E[], searchElement: E): SizeType.Arr | -1;
1777
+ <E>(searchElement: E): (array: readonly E[]) => SizeType.Arr | -1;
1778
+ };
1779
+ export const lastIndexOfFrom: LastIndexOfFromFnOverload;
1780
+ type LastIndexOfFromFnOverload = {
1781
+ <E>(array: readonly E[], searchElement: E, fromIndex: SizeType.ArgArr): SizeType.Arr | -1;
1782
+ <E>(searchElement: E, fromIndex: SizeType.ArgArr): (array: readonly E[]) => SizeType.Arr | -1;
1783
+ };
1784
+ /**
1785
+ * Applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value.
1786
+ * This is an alias for `Array.prototype.reduce`.
1787
+ * @template E The type of elements in the array.
1788
+ * @template S The type of the accumulated value.
1789
+ * @param array The input array.
1790
+ * @param callbackfn A function to execute on each element in the array: `(previousValue: S, currentValue: A, currentIndex: SizeType.Arr) => S`.
1791
+ * @param initialValue The initial value of the accumulator.
1792
+ * @returns The single value that results from the reduction.
1793
+ * @example
1794
+ * ```ts
1795
+ * // Regular usage
1796
+ * Arr.foldl([1, 2, 3], (sum, n) => sum + n, 0); // 6
1797
+ *
1798
+ * // Curried usage for pipe composition
1799
+ * const sumWithZero = Arr.foldl((sum: number, n: number) => sum + n, 0);
1800
+ * const result = pipe([1, 2, 3, 4]).map(sumWithZero).value;
1801
+ * console.log(result); // 10
1802
+ * ```
1803
+ */
1804
+ export const foldl: FoldlFnOverload;
1805
+ type FoldlFnOverload = {
1806
+ <E, P>(array: readonly E[], callbackfn: (previousValue: P, currentValue: E, currentIndex: SizeType.Arr) => P, initialValue: P): P;
1807
+ <E, P>(callbackfn: (previousValue: P, currentValue: E, currentIndex: SizeType.Arr) => P, initialValue: P): (array: readonly E[]) => P;
1808
+ };
1809
+ /**
1810
+ * Applies a function against an accumulator and each element in the array (from right to left) to reduce it to a single value.
1811
+ * This is an alias for `Array.prototype.reduceRight`.
1812
+ * @template E The type of elements in the array.
1813
+ * @template S The type of the accumulated value.
1814
+ * @param array The input array.
1815
+ * @param callbackfn A function to execute on each element in the array: `(previousValue: S, currentValue: A, currentIndex: SizeType.Arr) => S`.
1816
+ * @param initialValue The initial value of the accumulator.
1817
+ * @returns The single value that results from the reduction.
1818
+ * @example
1819
+ * ```ts
1820
+ * // Regular usage
1821
+ * Arr.foldr([1, 2, 3], (sum, n) => sum + n, 0); // 6
1822
+ *
1823
+ * // Curried usage for pipe composition
1824
+ * const concatRight = Arr.foldr((acc: string, curr: string) => curr + acc, '');
1825
+ * const result = pipe(['a', 'b', 'c']).map(concatRight).value;
1826
+ * console.log(result); // "abc"
1827
+ * ```
1828
+ */
1829
+ export const foldr: FoldrFnOverload;
1830
+ type FoldrFnOverload = {
1831
+ <E, P>(array: readonly E[], callbackfn: (previousValue: P, currentValue: E, currentIndex: SizeType.Arr) => P, initialValue: P): P;
1832
+ <E, P>(callbackfn: (previousValue: P, currentValue: E, currentIndex: SizeType.Arr) => P, initialValue: P): (array: readonly E[]) => P;
1833
+ };
1834
+ /**
1835
+ * Finds the minimum value in an array.
1836
+ * @template E The type of numbers in the array (must extend `number`).
1837
+ * @param array The input array.
1838
+ * @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`.
1839
+ * @returns The minimum value in the array wrapped in Optional.
1840
+ * @example
1841
+ * ```ts
1842
+ * Arr.min([3, 1, 4, 1, 5] as const); // Optional.some(1)
1843
+ * Arr.min([{v:3}, {v:1}], (a,b) => a.v - b.v) // Optional.some({v:1})
1844
+ * Arr.min([]); // Optional.none
1845
+ * ```
1846
+ */
1847
+ export const min: MinFnOverload;
1848
+ type MinFnOverload = {
1849
+ <E extends number>(array: NonEmptyArray<E>, comparator?: (x: E, y: E) => number): Optional.Some<E>;
1850
+ <E extends number>(array: readonly E[], comparator?: (x: E, y: E) => number): Optional<E>;
1851
+ <E>(array: NonEmptyArray<E>, comparator: (x: E, y: E) => number): Optional.Some<E>;
1852
+ <E>(array: readonly E[], comparator: (x: E, y: E) => number): Optional<E>;
1853
+ };
1854
+ /**
1855
+ * Finds the maximum value in an array.
1856
+ *
1857
+ * - If the array is non-empty, returns the maximum value.
1858
+ * - If the array is empty, returns `Optional.none`.
1859
+ * - You can provide a custom comparator for arbitrary types.
1860
+ *
1861
+ * @template E The type of elements in the array.
1862
+ * @param array The input array.
1863
+ * @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.
1864
+ * @returns The maximum value in the array wrapped in Optional.
1865
+ * @example
1866
+ * ```ts
1867
+ * Arr.max([3, 1, 4, 1, 5] as const); // Optional.some(5)
1868
+ * Arr.max([{v:3}, {v:1}], (a,b) => a.v - b.v) // Optional.some({v:3})
1869
+ * Arr.max([]); // Optional.none
1870
+ * ```
1871
+ */
1872
+ export const max: MaxFnOverload;
1873
+ type MaxFnOverload = {
1874
+ <E extends number>(array: NonEmptyArray<E>, comparator?: (x: E, y: E) => number): Optional.Some<E>;
1875
+ <E extends number>(array: readonly E[], comparator?: (x: E, y: E) => number): Optional<E>;
1876
+ <E>(array: NonEmptyArray<E>, comparator: (x: E, y: E) => number): Optional.Some<E>;
1877
+ <E>(array: readonly E[], comparator: (x: E, y: E) => number): Optional<E>;
1878
+ };
1879
+ /**
1880
+ * Finds the element with the minimum value according to a mapped numeric value.
1881
+ *
1882
+ * - If the array is non-empty, returns the element with the minimum mapped value.
1883
+ * - If the array is empty, returns `Optional.none`.
1884
+ * - You can provide a custom comparator for the mapped values.
1885
+ *
1886
+ * @template E The type of elements in the array.
1887
+ * @template V The type of the value to compare by.
1888
+ * @param array The input array.
1889
+ * @param comparatorValueMapper A function that maps an element to a value for comparison.
1890
+ * @param comparator An optional custom comparator function for the mapped values.
1891
+ * @returns The element with the minimum mapped value wrapped in Optional.
1892
+ * @example
1893
+ * ```ts
1894
+ * const people = [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 20 }] as const;
1895
+ * Arr.minBy(people, p => p.age); // Optional.some({ name: 'Bob', age: 20 })
1896
+ * Arr.minBy([], p => p.age); // Optional.none
1897
+ * ```
1898
+ */
1899
+ export const minBy: MinByFnOverload;
1900
+ type MinByFnOverload = {
1901
+ <E>(array: NonEmptyArray<E>, comparatorValueMapper: (value: E) => number): Optional.Some<E>;
1902
+ <E>(array: readonly E[], comparatorValueMapper: (value: E) => number): Optional<E>;
1903
+ <E, V>(array: NonEmptyArray<E>, comparatorValueMapper: (value: E) => V, comparator: (x: V, y: V) => number): Optional.Some<E>;
1904
+ <E, V>(array: readonly E[], comparatorValueMapper: (value: E) => V, comparator: (x: V, y: V) => number): Optional<E>;
1905
+ };
1906
+ /**
1907
+ * Finds the element with the maximum value according to a mapped numeric value.
1908
+ *
1909
+ * - If the array is non-empty, returns the element with the maximum mapped value.
1910
+ * - If the array is empty, returns `Optional.none`.
1911
+ * - You can provide a custom comparator for the mapped values.
1912
+ *
1913
+ * @template E The type of elements in the array.
1914
+ * @template V The type of the value to compare by.
1915
+ * @param array The input array.
1916
+ * @param comparatorValueMapper A function that maps an element to a value for comparison.
1917
+ * @param comparator An optional custom comparator function for the mapped values.
1918
+ * @returns The element with the maximum mapped value wrapped in Optional.
1919
+ * @example
1920
+ * ```ts
1921
+ * const people = [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 20 }] as const;
1922
+ * Arr.maxBy(people, p => p.age); // Optional.some({ name: 'Alice', age: 30 })
1923
+ * Arr.maxBy([], p => p.age); // Optional.none
1924
+ * ```
1925
+ */
1926
+ export const maxBy: MaxByFnOverload;
1927
+ type MaxByFnOverload = {
1928
+ <E>(array: NonEmptyArray<E>, comparatorValueMapper: (value: E) => number): Optional.Some<E>;
1929
+ <E>(array: readonly E[], comparatorValueMapper: (value: E) => number): Optional<E>;
1930
+ <E, V>(array: NonEmptyArray<E>, comparatorValueMapper: (value: E) => V, comparator: (x: V, y: V) => number): Optional.Some<E>;
1931
+ <E, V>(array: readonly E[], comparatorValueMapper: (value: E) => V, comparator: (x: V, y: V) => number): Optional<E>;
1932
+ };
1933
+ /**
1934
+ * Counts the number of elements in an array that satisfy a predicate.
1935
+ * @template E The type of elements in the array.
1936
+ * @param array The input array.
1937
+ * @param predicate A function `(value: A, index: number) => boolean` to test each element for a condition.
1938
+ * @returns The number of elements that satisfy the predicate.
1939
+ * @example
1940
+ * ```ts
1941
+ * // Regular usage
1942
+ * Arr.count([1, 2, 3, 4], (x) => x > 2); // 2
1943
+ *
1944
+ * // Curried usage for pipe composition
1945
+ * const countEvens = Arr.count((x: number) => x % 2 === 0);
1946
+ * const result = pipe([1, 2, 3, 4, 5, 6]).map(countEvens).value;
1947
+ * console.log(result); // 3
1948
+ * ```
1949
+ */
1950
+ export const count: CountFnOverload;
1951
+ type CountFnOverload = {
1952
+ <E>(array: readonly E[], predicate: (value: E, index: SizeType.Arr) => boolean): SizeType.Arr;
1953
+ <E>(predicate: (value: E, index: SizeType.Arr) => boolean): (array: readonly E[]) => SizeType.Arr;
1954
+ };
1955
+ /**
1956
+ * Groups elements of an array by a key derived from each element and counts the elements in each group.
1957
+ * @template E The type of elements in the array.
1958
+ * @template G The type of the group key (must be a primitive type: `string`, `number`, `boolean`, `symbol`, `bigint`, `null`, or `undefined`).
1959
+ * @param array The input array.
1960
+ * @param grouper A function `(value: A, index: number) => G` that maps an element and its index to a group key.
1961
+ * @returns An `IMap` where keys are group keys and values are the counts of elements in each group.
1962
+ * @example
1963
+ * ```ts
1964
+ * // Regular usage
1965
+ * Arr.countBy([1, 2, 2, 3, 1, 1], (x) => x);
1966
+ * // IMap { 1 => 3, 2 => 2, 3 => 1 }
1967
+ *
1968
+ * // Curried usage for pipe composition
1969
+ * const countByType = Arr.countBy((x: {type: string}) => x.type);
1970
+ * const data = [{type: 'a'}, {type: 'b'}, {type: 'a'}];
1971
+ * const result = pipe(data).map(countByType).value;
1972
+ * // IMap { 'a' => 2, 'b' => 1 }
1973
+ * ```
1974
+ */
1975
+ export const countBy: CountByFnOverload;
1976
+ type CountByFnOverload = {
1977
+ <E, G extends MapSetKeyType>(array: readonly E[], grouper: (value: E, index: SizeType.Arr) => G): IMap<G, SizeType.Arr>;
1978
+ <E, G extends MapSetKeyType>(grouper: (value: E, index: SizeType.Arr) => G): (array: readonly E[]) => IMap<G, SizeType.Arr>;
1979
+ };
1980
+ /**
1981
+ * Calculates the sum of numbers in an array.
1982
+ * @param array The input array of numbers.
1983
+ * @returns The sum of the numbers. Returns 0 for an empty array.
1984
+ * @example
1985
+ * ```ts
1986
+ * Arr.sum([1, 2, 3]); // 6
1987
+ * Arr.sum([]); // 0
1988
+ * Arr.sum([-1, 0, 1]); // 0
1989
+ * ```
1990
+ */
1991
+ export const sum: SumFnOverload;
1992
+ type SumFnOverload = {
1993
+ (array: readonly []): 0;
1994
+ <N extends number>(array: readonly [N]): N;
1995
+ (array: readonly Uint[]): Uint;
1996
+ (array: readonly Int[]): Int;
1997
+ (array: readonly number[]): number;
1998
+ };
1999
+ /**
2000
+ * Joins array elements into a string.
2001
+ * @param array The array to join.
2002
+ * @param separator The separator string.
2003
+ * @returns Result.Ok with the joined string, Result.Err if the operation throws.
2004
+ * @example
2005
+ * ```typescript
2006
+ * // Regular usage
2007
+ * const arr = ['Hello', 'World'];
2008
+ * const result = Arr.join(arr, ' ');
2009
+ * if (Result.isOk(result)) {
2010
+ * console.log(result.value); // "Hello World"
2011
+ * }
2012
+ *
2013
+ * // Curried usage for pipe composition
2014
+ * const joinWithComma = Arr.join(',');
2015
+ * const result2 = pipe(['a', 'b', 'c']).map(joinWithComma).value;
2016
+ * console.log(Result.unwrapOr(result2, '')); // "a,b,c"
2017
+ * ```
2018
+ */
2019
+ export const join: JoinFnOverload;
2020
+ type JoinFnOverload = {
2021
+ <E>(array: readonly E[], separator?: string): Result<string, Error>;
2022
+ (separator?: string): <E>(array: readonly E[]) => Result<string, Error>;
2023
+ };
2024
+ /**
2025
+ * Creates an array of tuples by pairing up corresponding elements from two arrays.
2026
+ * The resulting array has a length equal to the minimum of the two input array lengths.
2027
+ * @template E1 The type of the first array.
2028
+ * @template E2 The type of the second array.
2029
+ * @param array1 The first array.
2030
+ * @param array2 The second array.
2031
+ * @returns An array of tuples where each tuple contains corresponding elements from both arrays.
2032
+ * @example
2033
+ * ```ts
2034
+ * Arr.zip([1, 2, 3] as const, ['a', 'b', 'c'] as const); // [[1, 'a'], [2, 'b'], [3, 'c']]
2035
+ * Arr.zip([1, 2], ['a', 'b', 'c']); // [[1, 'a'], [2, 'b']]
2036
+ * Arr.zip([1, 2, 3], ['a']); // [[1, 'a']]
2037
+ * Arr.zip([], ['a']); // []
2038
+ * ```
2039
+ */
2040
+ export const zip: <Ar1 extends readonly unknown[], Ar2 extends readonly unknown[]>(array1: Ar1, array2: Ar2) => List.Zip<Ar1, Ar2>;
2041
+ /**
2042
+ * Filters an array by excluding elements for which the predicate returns true.
2043
+ * This is the opposite of `Array.prototype.filter`.
2044
+ * @template E The type of elements in the array.
2045
+ * @param array The input array.
2046
+ * @param predicate A function `(a: A, index: number) => boolean` that returns `true` for elements to be excluded.
2047
+ * @returns A new array with elements for which the predicate returned `false`.
2048
+ * @example
2049
+ * ```ts
2050
+ * // Regular usage
2051
+ * Arr.filterNot([1, 2, 3, 4], (x) => x % 2 === 0); // [1, 3] (excludes even numbers)
2052
+ *
2053
+ * // Curried usage for pipe composition
2054
+ * const excludeEvens = Arr.filterNot((x: number) => x % 2 === 0);
2055
+ * const result = pipe([1, 2, 3, 4, 5, 6]).map(excludeEvens).value;
2056
+ * console.log(result); // [1, 3, 5]
2057
+ * ```
2058
+ */
2059
+ export const filterNot: FilterNotFnOverload;
2060
+ type FilterNotFnOverload = {
2061
+ <E>(array: readonly E[], predicate: (a: E, index: SizeType.Arr) => boolean): readonly E[];
2062
+ <E>(predicate: (a: E, index: SizeType.Arr) => boolean): (array: readonly E[]) => readonly E[];
2063
+ };
2064
+ /**
2065
+ * Concatenates two arrays.
2066
+ * @template E1 The type of the first array (can be a tuple).
2067
+ * @template E2 The type of the second array (can be a tuple).
2068
+ * @param array1 The first array.
2069
+ * @param array2 The second array.
2070
+ * @returns A new array that is the concatenation of the two input arrays. Type is `readonly [...E1, ...E2]`.
2071
+ * @example
2072
+ * ```ts
2073
+ * Arr.concat([1, 2] as const, [3, 4] as const); // [1, 2, 3, 4]
2074
+ * Arr.concat([], [1, 2]); // [1, 2]
2075
+ * Arr.concat([1, 2], []); // [1, 2]
2076
+ * ```
2077
+ */
2078
+ export const concat: <Ar1 extends readonly unknown[], Ar2 extends readonly unknown[]>(array1: Ar1, array2: Ar2) => readonly [...Ar1, ...Ar2];
2079
+ /**
2080
+ * Partitions an array into sub-arrays of a specified size.
2081
+ * The last partition may be smaller if the array length is not a multiple of `chunkSize`.
2082
+ * Returns an empty array if chunkSize < 2.
2083
+ * @template N The size of each partition (must be a number type, typically a literal for precise typing).
2084
+ * @template E The type of elements in the array.
2085
+ * @param array The input array.
2086
+ * @param chunkSize The size of each partition.
2087
+ * @returns An array of arrays, where each inner array has up to `chunkSize` elements.
2088
+ * @example
2089
+ * ```ts
2090
+ * // Regular usage
2091
+ * Arr.partition([1, 2, 3, 4, 5, 6], 2); // [[1, 2], [3, 4], [5, 6]]
2092
+ *
2093
+ * // Curried usage for pipe composition
2094
+ * const chunkBy3 = Arr.partition(3);
2095
+ * const result = pipe([1, 2, 3, 4, 5, 6, 7]).map(chunkBy3).value;
2096
+ * console.log(result); // [[1, 2, 3], [4, 5, 6], [7]]
2097
+ * ```
2098
+ */
2099
+ export const partition: PartitionFnOverload;
2100
+ type PartitionFnOverload = {
2101
+ <N extends WithSmallInt<PositiveInt & SizeType.Arr>, E>(array: readonly E[], chunkSize: N): readonly (readonly E[])[];
2102
+ <N extends WithSmallInt<PositiveInt & SizeType.Arr>>(chunkSize: N): <E>(array: readonly E[]) => readonly (readonly E[])[];
2103
+ };
2104
+ /**
2105
+ * Sorts an array by a value derived from its elements, using a numeric mapping.
2106
+ * @template E The type of elements in the array.
2107
+ * @param array The input array.
2108
+ * @param comparatorValueMapper A function `(value: A) => number` that maps an element to a number for comparison.
2109
+ * @param comparator An optional custom comparator function `(x: number, y: number) => number` for the mapped numbers. Defaults to ascending sort (x - y).
2110
+ * @returns A new array sorted by the mapped values.
2111
+ * @example
2112
+ * ```ts
2113
+ * const items = [{ name: 'Eve', score: 70 }, { name: 'Adam', score: 90 }, { name: 'Bob', score: 80 }];
2114
+ * Arr.toSortedBy(items, item => item.score);
2115
+ * // [{ name: 'Eve', score: 70 }, { name: 'Bob', score: 80 }, { name: 'Adam', score: 90 }]
2116
+ * Arr.toSortedBy(items, item => item.score, (a, b) => b - a); // Sort descending
2117
+ * // [{ name: 'Adam', score: 90 }, { name: 'Bob', score: 80 }, { name: 'Eve', score: 70 }]
2118
+ * ```
2119
+ */
2120
+ export const toSortedBy: ToSortedByFnOverload;
2121
+ type ToSortedByFnOverload = {
2122
+ <E>(array: readonly E[], comparatorValueMapper: (value: E) => number, comparator?: (x: number, y: number) => number): readonly E[];
2123
+ <E, const V>(array: readonly E[], comparatorValueMapper: (value: E) => V, comparator: (x: V, y: V) => number): readonly E[];
2124
+ };
2125
+ /**
2126
+ * Returns an array of successively reduced values from an array, starting with an initial value.
2127
+ *
2128
+ * This function creates a \"running tally\" by applying a reducer function to each element and
2129
+ * accumulating the results. Unlike {@link reduce} which returns a single final value, `scan`
2130
+ * returns all intermediate accumulated values, providing visibility into the reduction process.
2131
+ *
2132
+ * **Key Differences from Reduce:**
2133
+ * - {@link reduce}: `[1, 2, 3] -> 6` (final sum only)
2134
+ * - `scan`: `[1, 2, 3] -> [0, 1, 3, 6]` (all intermediate sums including initial value)
2135
+ *
2136
+ * **Guaranteed Non-Empty Return:** The result is always a {@link NonEmptyArray}<S> because it includes
2137
+ * the initial value as the first element, even for empty input arrays. This provides type safety
2138
+ * and eliminates the need for empty array checks.
2139
+ *
2140
+ * **Array Length Relationship:** `result.length === array.length + 1` (includes initial value)
2141
+ *
2142
+ * **Curried Usage:** Supports currying for functional composition - when called with only the reducer
2143
+ * and initial value, returns a reusable function that can be applied to arrays.
2144
+ *
2145
+ * @template E The type of elements in the input array.
2146
+ * @template S The type of the accumulated values and the initial value.
2147
+ * @param array The input array to scan over. Can be empty (result will still contain the initial value).
2148
+ * @param reducer A function `(accumulator: S, currentValue: E, currentIndex: SizeType.Arr) => S` that:
2149
+ * - **accumulator:** The current accumulated value (starts with `init`, then previous results)
2150
+ * - **currentValue:** The current array element being processed
2151
+ * - **currentIndex:** The 0-based index of the current element (typed as {@link SizeType.Arr})
2152
+ * - **returns:** The new accumulated value to include in the result array
2153
+ * @param init The initial accumulated value. Becomes the first element of the result array.
2154
+ * @returns A {@link NonEmptyArray}<S> of accumulated values with length `array.length + 1`:
2155
+ * - `result[0]` is always the `init` value
2156
+ * - `result[i+1]` is the result of applying the reducer to `result[i]` and `array[i]`
2157
+ * - Guaranteed to be non-empty regardless of input array length
2158
+ *
2159
+ * @example
2160
+ * ```typescript
2161
+ * // Basic running sum example
2162
+ * const numbers = [1, 2, 3, 4];
2163
+ * const runningSum = Arr.scan(numbers, (acc, curr) => acc + curr, 0);
2164
+ * // NonEmptyArray<number> -> [0, 1, 3, 6, 10]
2165
+ * // ^ ^ ^ ^ ^
2166
+ * // | | | | └─ 0+1+2+3+4 = 10
2167
+ * // | | | └─ 0+1+2+3 = 6
2168
+ * // | | └─ 0+1+2 = 3
2169
+ * // | └─ 0+1 = 1
2170
+ * // └─ init = 0
2171
+ *
2172
+ * // Difference from reduce
2173
+ * const reduced = numbers.reduce((acc, curr) => acc + curr, 0); // 10 (final only)
2174
+ * const scanned = Arr.scan(numbers, (acc, curr) => acc + curr, 0); // [0, 1, 3, 6, 10] (all steps)
2175
+ *
2176
+ * // Running product
2177
+ * const factorial = Arr.scan([1, 2, 3, 4, 5], (acc, curr) => acc * curr, 1);
2178
+ * // [1, 1, 2, 6, 24, 120] - factorial sequence
2179
+ *
2180
+ * // Running maximum
2181
+ * const temperatures = [20, 25, 18, 30, 22];
2182
+ * const runningMax = Arr.scan(temperatures, (max, temp) => Math.max(max, temp), -Infinity);
2183
+ * // [-Infinity, 20, 25, 25, 30, 30]
2184
+ *
2185
+ * // Building strings incrementally
2186
+ * const words = ['Hello', 'beautiful', 'world'];
2187
+ * const sentences = Arr.scan(words, (sentence, word) => sentence + ' ' + word, '');
2188
+ * // ['', ' Hello', ' Hello beautiful', ' Hello beautiful world']
2189
+ *
2190
+ * // Array accumulation (collecting elements)
2191
+ * const items = ['a', 'b', 'c'];
2192
+ * const growing = Arr.scan(items, (acc, item) => [...acc, item], [] as string[]);
2193
+ * // [[], ['a'], ['a', 'b'], ['a', 'b', 'c']]
2194
+ *
2195
+ * // Financial running balance
2196
+ * const transactions = [100, -20, 50, -30];
2197
+ * const balances = Arr.scan(transactions, (balance, transaction) => balance + transaction, 1000);
2198
+ * // [1000, 1100, 1080, 1130, 1100] - account balance after each transaction
2199
+ *
2200
+ * // Using index information
2201
+ * const letters = ['a', 'b', 'c'];
2202
+ * const indexed = Arr.scan(letters, (acc, letter, index) => acc + `${index}:${letter} `, '');
2203
+ * // ['', '0:a ', '0:a 1:b ', '0:a 1:b 2:c ']
2204
+ *
2205
+ * // Edge cases
2206
+ * const emptyArray: number[] = [];
2207
+ * const emptyResult = Arr.scan(emptyArray, (acc, curr) => acc + curr, 42);
2208
+ * // [42] - NonEmptyArray even for empty input
2209
+ *
2210
+ * const singleElement = Arr.scan([5], (acc, curr) => acc * curr, 2);
2211
+ * // [2, 10] - init value plus one result
2212
+ *
2213
+ * // Complex object accumulation
2214
+ * const sales = [
2215
+ * { product: 'A', amount: 100 },
2216
+ * { product: 'B', amount: 200 },
2217
+ * { product: 'A', amount: 150 }
2218
+ * ];
2219
+ *
2220
+ * const runningSales = Arr.scan(sales, (totals, sale) => ({
2221
+ * ...totals,
2222
+ * [sale.product]: (totals[sale.product] || 0) + sale.amount
2223
+ * }), {} as Record<string, number>);
2224
+ * // [
2225
+ * // {},
2226
+ * // { A: 100 },
2227
+ * // { A: 100, B: 200 },
2228
+ * // { A: 250, B: 200 }
2229
+ * // ]
2230
+ *
2231
+ * // Curried usage for functional composition
2232
+ * const runningSumFn = Arr.scan((acc: number, curr: number) => acc + curr, 0);
2233
+ * const runningProductFn = Arr.scan((acc: number, curr: number) => acc * curr, 1);
2234
+ * const collectingFn = Arr.scan((acc: string[], curr: string) => [...acc, curr], [] as string[]);
2235
+ *
2236
+ * const datasets = [[1, 2, 3], [4, 5], [6, 7, 8, 9]];
2237
+ * const allSums = datasets.map(runningSumFn);
2238
+ * // [
2239
+ * // [0, 1, 3, 6],
2240
+ * // [0, 4, 9],
2241
+ * // [0, 6, 13, 21, 30]
2242
+ * // ]
2243
+ *
2244
+ * // Pipe composition for data analysis
2245
+ * const analysisResult = pipe([10, 20, 30, 40])
2246
+ * .map(runningSumFn)
2247
+ * .map(sums => sums.slice(1)) // Remove initial value to get pure running sums
2248
+ * .map(sums => sums.map((sum, i) => ({ step: i + 1, total: sum })))
2249
+ * .value;
2250
+ * // [{ step: 1, total: 10 }, { step: 2, total: 30 }, { step: 3, total: 60 }, { step: 4, total: 100 }]
2251
+ *
2252
+ * // Advanced: State machine simulation
2253
+ * type State = 'idle' | 'loading' | 'success' | 'error';
2254
+ * type Event = 'start' | 'complete' | 'fail' | 'reset';
2255
+ *
2256
+ * const events: Event[] = ['start', 'complete', 'reset', 'start', 'fail'];
2257
+ * const stateTransition = (state: State, event: Event): State => {
2258
+ * switch (state) {
2259
+ * case 'idle': return event === 'start' ? 'loading' : state;
2260
+ * case 'loading': return event === 'complete' ? 'success' : event === 'fail' ? 'error' : state;
2261
+ * case 'success': return event === 'reset' ? 'idle' : state;
2262
+ * case 'error': return event === 'reset' ? 'idle' : state;
2263
+ * }
2264
+ * };
2265
+ *
2266
+ * const stateHistory = Arr.scan(events, stateTransition, 'idle' as State);
2267
+ * // ['idle', 'loading', 'success', 'idle', 'loading', 'error']
2268
+ *
2269
+ * // Type inference examples
2270
+ * expectType<typeof runningSum, NonEmptyArray<number>>('=');
2271
+ * expectType<typeof emptyResult, NonEmptyArray<number>>('=');
2272
+ * expectType<typeof runningSumFn, <T extends readonly number[]>(array: T) => NonEmptyArray<number>>('=');
2273
+ * expectType<typeof stateHistory, NonEmptyArray<State>>('=');
2274
+ * ```
2275
+ *
2276
+ * @see {@link reduce} for getting only the final accumulated value
2277
+ * @see {@link NonEmptyArray} for understanding the guaranteed non-empty return type
2278
+ * @see {@link SizeType.Arr} for the index parameter type
2279
+ * @see Array.prototype.reduce for the standard reduce function
2280
+ */
2281
+ export const scan: ScanFnOverload;
2282
+ type ScanFnOverload = {
2283
+ <E, S>(array: readonly E[], reducer: (accumulator: S, currentValue: E, currentIndex: SizeType.Arr) => S, init: S): NonEmptyArray<S>;
2284
+ <E, S>(reducer: (accumulator: S, currentValue: E, currentIndex: SizeType.Arr) => S, init: S): (array: readonly E[]) => NonEmptyArray<S>;
2285
+ };
2286
+ /**
2287
+ * Groups elements of an array by a key derived from each element, returning an immutable {@link IMap}.
2288
+ *
2289
+ * This function categorizes array elements into groups based on a computed key, using the efficient
2290
+ * {@link IMap} data structure for the result. The grouper function receives both the element and its
2291
+ * index, enabling flexible grouping strategies.
2292
+ *
2293
+ * **MapSetKeyType Constraint:** The group key type `G` must extend {@link MapSetKeyType}, which includes
2294
+ * primitive types that can be used as Map keys (string, number, boolean, symbol, null, undefined).
2295
+ * This constraint ensures type safety and efficient key-based operations.
2296
+ *
2297
+ * **IMap Return Type:** Returns an {@link IMap}<G, readonly E[]> where:
2298
+ * - Keys are the computed group identifiers of type `G`
2299
+ * - Values are immutable arrays containing all elements that belong to each group
2300
+ * - Preserves insertion order of first occurrence of each group
2301
+ * - Maintains type safety with precise generic types
2302
+ *
2303
+ * **Curried Usage:** Supports currying for functional composition - when called with only the grouper
2304
+ * function, returns a reusable function that can be applied to arrays.
2305
+ *
2306
+ * @template E The type of elements in the input array.
2307
+ * @template G The type of the group key, constrained to {@link MapSetKeyType} (primitives usable as Map keys).
2308
+ * Must be one of: `string | number | boolean | symbol | null | undefined`
2309
+ * @param array The input array to group. Can be empty (returns empty {@link IMap}).
2310
+ * @param grouper A function `(value: E, index: SizeType.Arr) => G` that computes the group key for each element.
2311
+ * - **value:** The current array element
2312
+ * - **index:** The 0-based index of the element (typed as {@link SizeType.Arr})
2313
+ * - **returns:** The group key (must be {@link MapSetKeyType})
2314
+ * @returns An {@link IMap}<G, readonly E[]> where:
2315
+ * - Keys are unique group identifiers computed by the grouper function
2316
+ * - Values are immutable arrays of elements belonging to each group
2317
+ * - Empty groups are not included (only groups with at least one element)
2318
+ * - Insertion order is preserved based on first occurrence of each group key
2319
+ *
2320
+ * @example
2321
+ * ```typescript
2322
+ * // Basic grouping by object property
2323
+ * const products = [
2324
+ * { type: 'fruit', name: 'apple', price: 1.2 },
2325
+ * { type: 'vegetable', name: 'carrot', price: 0.8 },
2326
+ * { type: 'fruit', name: 'banana', price: 0.9 },
2327
+ * { type: 'vegetable', name: 'broccoli', price: 2.1 },
2328
+ * { type: 'fruit', name: 'orange', price: 1.5 }
2329
+ * ];
2330
+ *
2331
+ * const byType = Arr.groupBy(products, item => item.type);
2332
+ * // IMap<string, readonly Product[]> {
2333
+ * // 'fruit' => [
2334
+ * // { type: 'fruit', name: 'apple', price: 1.2 },
2335
+ * // { type: 'fruit', name: 'banana', price: 0.9 },
2336
+ * // { type: 'fruit', name: 'orange', price: 1.5 }
2337
+ * // ],
2338
+ * // 'vegetable' => [
2339
+ * // { type: 'vegetable', name: 'carrot', price: 0.8 },
2340
+ * // { type: 'vegetable', name: 'broccoli', price: 2.1 }
2341
+ * // ]
2342
+ * // }
2343
+ *
2344
+ * // Access grouped results with IMap methods
2345
+ * const fruits = IMap.get(byType, 'fruit'); // Optional<readonly Product[]>
2346
+ * const fruitCount = Optional.map(fruits, arr => arr.length); // Optional<number>
2347
+ * const fruitNames = Optional.map(fruits, arr => arr.map(p => p.name)); // Optional<string[]>
2348
+ *
2349
+ * // Grouping by computed values
2350
+ * const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
2351
+ * const byParity = Arr.groupBy(numbers, n => n % 2 === 0 ? 'even' : 'odd');
2352
+ * // IMap<string, readonly number[]> {
2353
+ * // 'odd' => [1, 3, 5, 7, 9],
2354
+ * // 'even' => [2, 4, 6, 8, 10]
2355
+ * // }
2356
+ *
2357
+ * // Grouping by price ranges using index information
2358
+ * const byPriceRange = Arr.groupBy(products, (product, index) => {
2359
+ * const category = product.price < 1.0 ? 'cheap' :
2360
+ * product.price < 2.0 ? 'moderate' : 'expensive';
2361
+ * return `${category}_${index < 2 ? 'early' : 'late'}`;
2362
+ * });
2363
+ *
2364
+ * // MapSetKeyType constraint examples (valid key types)
2365
+ * const byStringKey = Arr.groupBy([1, 2, 3], n => `group_${n}`); // string keys
2366
+ * const byNumberKey = Arr.groupBy(['a', 'b', 'c'], (_, i) => i); // number keys
2367
+ * const byBooleanKey = Arr.groupBy([1, 2, 3, 4], n => n > 2); // boolean keys
2368
+ * const bySymbolKey = Arr.groupBy([1, 2], n => Symbol(n.toString())); // symbol keys
2369
+ *
2370
+ * // Edge cases
2371
+ * const emptyGroup = Arr.groupBy([], x => x); // IMap<never, readonly never[]> (empty)
2372
+ * const singleGroup = Arr.groupBy([1, 2, 3], () => 'all'); // All elements in one group
2373
+ * const uniqueGroups = Arr.groupBy([1, 2, 3], x => x); // Each element in its own group
2374
+ *
2375
+ * // Curried usage for functional composition
2376
+ * const groupByType = Arr.groupBy((item: { type: string }) => item.type);
2377
+ * const groupByLength = Arr.groupBy((str: string) => str.length);
2378
+ * const groupByFirstChar = Arr.groupBy((str: string) => str.charAt(0).toLowerCase());
2379
+ *
2380
+ * const datasets = [
2381
+ * [{ type: 'A' }, { type: 'B' }, { type: 'A' }],
2382
+ * [{ type: 'C' }, { type: 'A' }],
2383
+ * [{ type: 'B' }, { type: 'B' }, { type: 'C' }]
2384
+ * ];
2385
+ * const allGrouped = datasets.map(groupByType);
2386
+ * // Array of IMap instances, each grouped by type
2387
+ *
2388
+ * // Pipe composition for complex data processing
2389
+ * const words = ['apple', 'banana', 'apricot', 'blueberry', 'avocado', 'blackberry'];
2390
+ * const processedGroups = pipe(words)
2391
+ * .map(groupByFirstChar)
2392
+ * .map(groupMap => IMap.map(groupMap, (wordsInGroup, firstLetter) => ({
2393
+ * letter: firstLetter,
2394
+ * count: wordsInGroup.length,
2395
+ * longest: wordsInGroup.reduce((longest, word) =>
2396
+ * word.length > longest.length ? word : longest
2397
+ * )
2398
+ * })))
2399
+ * .value;
2400
+ * // IMap<string, {letter: string, count: number, longest: string}>
2401
+ *
2402
+ * // Advanced: Grouping with complex transformations
2403
+ * const students = [
2404
+ * { name: 'Alice', grade: 85, subject: 'Math' },
2405
+ * { name: 'Bob', grade: 92, subject: 'Science' },
2406
+ * { name: 'Charlie', grade: 78, subject: 'Math' },
2407
+ * { name: 'Diana', grade: 96, subject: 'Science' }
2408
+ * ];
2409
+ *
2410
+ * const byGradeLevel = Arr.groupBy(students, student => {
2411
+ * if (student.grade >= 90) return 'A';
2412
+ * if (student.grade >= 80) return 'B';
2413
+ * return 'C';
2414
+ * });
2415
+ *
2416
+ * // Working with the grouped results
2417
+ * const aStudents = Optional.unwrapOr(IMap.get(byGradeLevel, 'A'), []);
2418
+ * const averageAGrade = aStudents.length > 0
2419
+ * ? aStudents.reduce((sum, s) => sum + s.grade, 0) / aStudents.length
2420
+ * : 0;
2421
+ *
2422
+ * // Type inference examples
2423
+ * expectType<typeof byType, IMap<string, readonly typeof products[number][]>>('=');
2424
+ * expectType<typeof byParity, IMap<string, readonly number[]>>('=');
2425
+ * expectType<typeof groupByType, <T extends {type: string}>(array: readonly T[]) => IMap<string, readonly T[]>>('=');
2426
+ * expectType<typeof emptyGroup, IMap<never, readonly never[]>>('=');
2427
+ * ```
2428
+ *
2429
+ * @see {@link IMap} for working with the returned immutable map
2430
+ * @see {@link MapSetKeyType} for understanding valid key types
2431
+ * @see {@link IMap.get} for safely accessing grouped results
2432
+ * @see {@link IMap.map} for transforming grouped data
2433
+ * @see {@link Optional} for handling potentially missing groups
2434
+ */
2435
+ export const groupBy: GroupByFnOverload;
2436
+ type GroupByFnOverload = {
2437
+ <E, G extends MapSetKeyType>(array: readonly E[], grouper: (value: E, index: SizeType.Arr) => G): IMap<G, readonly E[]>;
2438
+ <E, G extends MapSetKeyType>(grouper: (value: E, index: SizeType.Arr) => G): (array: readonly E[]) => IMap<G, readonly E[]>;
2439
+ };
2440
+ /**
2441
+ * Creates a new array with unique elements from the input array. Order is preserved from the first occurrence.
2442
+ * Uses `Set` internally for efficient uniqueness checking.
2443
+ * @template P The type of elements in the array.
2444
+ * @param array The input array.
2445
+ * @returns A new array with unique elements from the input array. Returns `[]` for an empty input.
2446
+ * @example
2447
+ * ```ts
2448
+ * Arr.uniq([1, 2, 2, 3, 1, 4]); // [1, 2, 3, 4]
2449
+ * Arr.uniq(['a', 'b', 'a']); // ['a', 'b']
2450
+ * ```
2451
+ */
2452
+ export const uniq: <P extends Primitive>(array: readonly P[]) => readonly P[];
2453
+ /**
2454
+ * Creates a new array with unique elements from the input array, based on the values returned by `mapFn`.
2455
+ *
2456
+ * - If the input is a non-empty array, returns a non-empty array.
2457
+ * - Otherwise, returns a readonly array.
2458
+ *
2459
+ * @template E The type of elements in the array.
2460
+ * @template P The type of the mapped value (used for uniqueness comparison).
2461
+ * @param array The input array.
2462
+ * @param mapFn A function `(value: A) => P` to map elements to values for uniqueness comparison.
2463
+ * @returns A new array with unique elements based on the mapped values.
2464
+ * @example
2465
+ * ```ts
2466
+ * const users = [
2467
+ * { id: 1, name: 'Alice' },
2468
+ * { id: 2, name: 'Bob' },
2469
+ * { id: 1, name: 'Alicia' }, // Duplicate id
2470
+ * ];
2471
+ * Arr.uniqBy(users, user => user.id); // [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
2472
+ * ```
2473
+ */
2474
+ export const uniqBy: UniqByFnOverload;
2475
+ type UniqByFnOverload = {
2476
+ <E, P extends Primitive>(array: NonEmptyArray<E>, mapFn: (value: E) => P): NonEmptyArray<E>;
2477
+ <E, P extends Primitive>(array: readonly E[], mapFn: (value: E) => P): readonly E[];
2478
+ };
2479
+ /**
2480
+ * Checks if two arrays are equal by performing a shallow comparison of their elements.
2481
+ * @template E The type of elements in the arrays.
2482
+ * @param array1 The first array.
2483
+ * @param array2 The second array.
2484
+ * @param equality An optional function `(a: T, b: T) => boolean` to compare elements. Defaults to `Object.is`.
2485
+ * @returns `true` if the arrays have the same length and all corresponding elements are equal according to the `equality` function, `false` otherwise.
2486
+ * @example
2487
+ * ```ts
2488
+ * Arr.eq([1, 2, 3], [1, 2, 3]); // true
2489
+ * Arr.eq([1, 2, 3], [1, 2, 4]); // false
2490
+ * Arr.eq([1, 2], [1, 2, 3]); // false
2491
+ * Arr.eq([{a:1}], [{a:1}]); // false (different object references)
2492
+ * Arr.eq([{a:1}], [{a:1}], (o1, o2) => o1.a === o2.a); // true
2493
+ * ```
2494
+ */
2495
+ export const eq: <E>(array1: readonly E[], array2: readonly E[], equality?: (a: E, b: E) => boolean) => boolean;
2496
+ /**
2497
+ * Alias for `eq`.
2498
+ */
2499
+ export const equal: <E>(array1: readonly E[], array2: readonly E[], equality?: (a: E, b: E) => boolean) => boolean;
2500
+ /**
2501
+ * Checks if the first array (`array1`) is a subset of the second array (`array2`).
2502
+ * An array `A` is a subset of `B` if all elements of `A` are also present in `B`.
2503
+ * Elements must be primitive types for `includes` to work reliably for comparison.
2504
+ * @template E1 The type of elements in the first array (subset candidate), must be a primitive type.
2505
+ * @template E2 The type of elements in the second array (superset candidate), must be a primitive type.
2506
+ * @param array1 The first array.
2507
+ * @param array2 The second array.
2508
+ * @returns `true` if `array1` is a subset of `array2`, `false` otherwise.
2509
+ * @remarks `array1` ⊂ `array2`
2510
+ * @example
2511
+ * ```ts
2512
+ * Arr.isSubset([1, 2], [1, 2, 3]); // true
2513
+ * Arr.isSubset([1, 2, 3], [1, 2]); // false
2514
+ * Arr.isSubset([], [1, 2, 3]); // true
2515
+ * Arr.isSubset([1, 5], [1, 2, 3]); // false
2516
+ * ```
2517
+ */
2518
+ export const isSubset: <E1 extends Primitive, E2 extends Primitive = E1>(array1: readonly E1[], array2: readonly E2[]) => boolean;
2519
+ /**
2520
+ * Checks if the first array (`array1`) is a superset of the second array (`array2`).
2521
+ * An array `A` is a superset of `B` if all elements of `B` are also present in `A`.
2522
+ * Elements must be primitive types.
2523
+ * @template E1 The type of elements in the first array (superset candidate), must be a primitive type.
2524
+ * @template E2 The type of elements in the second array (subset candidate), must be a primitive type.
2525
+ * @param array1 The first array.
2526
+ * @param array2 The second array.
2527
+ * @returns `true` if `array1` is a superset of `array2`, `false` otherwise.
2528
+ * @remarks `array1` ⊃ `array2`
2529
+ * @example
2530
+ * ```ts
2531
+ * Arr.isSuperset([1, 2, 3], [1, 2]); // true
2532
+ * Arr.isSuperset([1, 2], [1, 2, 3]); // false
2533
+ * Arr.isSuperset([1, 2, 3], []); // true
2534
+ * ```
2535
+ */
2536
+ export const isSuperset: <E1 extends Primitive, E2 extends Primitive = E1>(array1: readonly E1[], array2: readonly E2[]) => boolean;
2537
+ /**
2538
+ * Returns the intersection of two arrays of primitive types.
2539
+ * The intersection contains elements that are present in both arrays. Order is based on `array1`.
2540
+ * @template E1 The type of elements in the first array (must be a primitive type).
2541
+ * @template E2 The type of elements in the second array (must be a primitive type).
2542
+ * @param array1 The first array.
2543
+ * @param array2 The second array.
2544
+ * @returns A new array containing elements that are in both `array1` and `array2`.
2545
+ * @example
2546
+ * ```ts
2547
+ * Arr.setIntersection([1, 2, 3], [2, 3, 4]); // [2, 3]
2548
+ * Arr.setIntersection(['a', 'b'], ['b', 'c']); // ['b']
2549
+ * Arr.setIntersection([1, 2], [3, 4]); // []
2550
+ * ```
2551
+ */
2552
+ export const setIntersection: <E1 extends Primitive, E2 extends Primitive = E1>(array1: readonly E1[], array2: readonly E2[]) => readonly (E1 & E2)[];
2553
+ /**
2554
+ * Returns the set difference of two arrays (`array1` - `array2`).
2555
+ * The difference contains elements that are in `array1` but not in `array2`. Order is based on `array1`.
2556
+ * Elements must be primitive types.
2557
+ * @template E The type of elements in the arrays (must be a primitive type).
2558
+ * @param array1 The first array.
2559
+ * @param array2 The second array.
2560
+ * @returns A new array containing elements from `array1` that are not in `array2`.
2561
+ * @example
2562
+ * ```ts
2563
+ * Arr.setDifference([1, 2, 3], [2, 3, 4]); // [1]
2564
+ * Arr.setDifference([1, 2, 3], [1, 2, 3]); // []
2565
+ * Arr.setDifference([1, 2], [3, 4]); // [1, 2]
2566
+ * ```
2567
+ */
2568
+ export const setDifference: <E extends Primitive>(array1: readonly E[], array2: readonly E[]) => readonly E[];
2569
+ /**
2570
+ * Returns the set difference of two sorted arrays of numbers (`sortedList1` - `sortedList2`).
2571
+ * This operation is more efficient for sorted arrays than the generic `setDifference`.
2572
+ * The resulting array is also sorted.
2573
+ * @template E The type of numbers in the arrays (must extend `number`).
2574
+ * @param sortedList1 The first sorted array of numbers.
2575
+ * @param sortedList2 The second sorted array of numbers.
2576
+ * @returns A new sorted array containing numbers from `sortedList1` that are not in `sortedList2`.
2577
+ * @example
2578
+ * ```ts
2579
+ * Arr.sortedNumSetDifference([1, 2, 3, 5], [2, 4, 5]); // [1, 3]
2580
+ * Arr.sortedNumSetDifference([1, 2, 3], [1, 2, 3]); // []
2581
+ * Arr.sortedNumSetDifference([1, 2], [3, 4]); // [1, 2]
2582
+ * ```
2583
+ */
2584
+ export const sortedNumSetDifference: <E extends number>(sortedList1: readonly E[], sortedList2: readonly E[]) => readonly E[];
2585
+ /**
2586
+ * Alias for `head`. Returns the first element of an array.
2587
+ * @see {@link head}
2588
+ */
2589
+ export const first: HeadFnOverload;
2590
+ /**
2591
+ * Alias for `tail`. Returns all elements of an array except the first one.
2592
+ * @see {@link tail}
2593
+ */
2594
+ export const rest: <Ar extends readonly unknown[]>(array: Ar) => List.Tail<Ar>;
2595
+ /**
2596
+ * Alias for `skip`. Skips the first N elements of an array.
2597
+ * @see {@link skip}
2598
+ */
2599
+ export const drop: SkipFnOverload;
2600
+ /**
2601
+ * 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.
2602
+ * @see {@link foldl}
2603
+ */
2604
+ export const reduce: FoldlFnOverload;
2605
+ /**
2606
+ * 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.
2607
+ * @see {@link foldr}
2608
+ */
2609
+ export const reduceRight: FoldrFnOverload;
2610
+ /**
2611
+ * Alias for `partition`. Splits an array into chunks of a specified size.
2612
+ * @see {@link partition}
2613
+ */
2614
+ export const chunk: PartitionFnOverload;
2615
+ export {};
2616
+ }
2617
+ //# sourceMappingURL=array-utils.d.mts.map