ts-data-forge 14.10.1 → 14.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (437) hide show
  1. package/README.md +34 -1
  2. package/dist/array/impl/array-utils-reducing-value.d.mts.map +1 -1
  3. package/dist/array/impl/array-utils-reducing-value.mjs +4 -3
  4. package/dist/array/impl/array-utils-reducing-value.mjs.map +1 -1
  5. package/dist/array/impl/array-utils-slice-clamped.mjs +1 -1
  6. package/dist/array/impl/array-utils-slice-clamped.mjs.map +1 -1
  7. package/dist/array/impl/array-utils-slicing.d.mts.map +1 -1
  8. package/dist/array/impl/array-utils-slicing.mjs +10 -3
  9. package/dist/array/impl/array-utils-slicing.mjs.map +1 -1
  10. package/dist/array/impl/array-utils-transformation.d.mts.map +1 -1
  11. package/dist/array/impl/array-utils-transformation.mjs +3 -3
  12. package/dist/array/impl/array-utils-transformation.mjs.map +1 -1
  13. package/dist/array/impl/array-utils-validation.d.mts.map +1 -1
  14. package/dist/array/impl/array-utils-validation.mjs +2 -1
  15. package/dist/array/impl/array-utils-validation.mjs.map +1 -1
  16. package/dist/built-in-tag.d.mts +22 -0
  17. package/dist/built-in-tag.d.mts.map +1 -0
  18. package/dist/built-in-tag.mjs +34 -0
  19. package/dist/built-in-tag.mjs.map +1 -0
  20. package/dist/collections/imap-mapped.mjs +6 -3
  21. package/dist/collections/imap-mapped.mjs.map +1 -1
  22. package/dist/collections/imap.mjs +6 -3
  23. package/dist/collections/imap.mjs.map +1 -1
  24. package/dist/collections/stack.mjs +3 -3
  25. package/dist/collections/stack.mjs.map +1 -1
  26. package/dist/iterator/range.d.mts +1 -1
  27. package/dist/iterator/range.d.mts.map +1 -1
  28. package/dist/iterator/range.mjs +5 -2
  29. package/dist/iterator/range.mjs.map +1 -1
  30. package/dist/json/json.d.mts.map +1 -1
  31. package/dist/json/json.mjs +13 -47
  32. package/dist/json/json.mjs.map +1 -1
  33. package/dist/number/branded-types/finite-number.d.mts +4 -9
  34. package/dist/number/branded-types/finite-number.d.mts.map +1 -1
  35. package/dist/number/branded-types/finite-number.mjs +9 -9
  36. package/dist/number/branded-types/finite-number.mjs.map +1 -1
  37. package/dist/number/branded-types/int.d.mts +3 -9
  38. package/dist/number/branded-types/int.d.mts.map +1 -1
  39. package/dist/number/branded-types/int.mjs +9 -10
  40. package/dist/number/branded-types/int.mjs.map +1 -1
  41. package/dist/number/branded-types/int16.d.mts +3 -18
  42. package/dist/number/branded-types/int16.d.mts.map +1 -1
  43. package/dist/number/branded-types/int16.mjs +9 -10
  44. package/dist/number/branded-types/int16.mjs.map +1 -1
  45. package/dist/number/branded-types/int32.d.mts +3 -14
  46. package/dist/number/branded-types/int32.d.mts.map +1 -1
  47. package/dist/number/branded-types/int32.mjs +9 -10
  48. package/dist/number/branded-types/int32.mjs.map +1 -1
  49. package/dist/number/branded-types/negative-finite-number.d.mts +4 -16
  50. package/dist/number/branded-types/negative-finite-number.d.mts.map +1 -1
  51. package/dist/number/branded-types/negative-finite-number.mjs +9 -10
  52. package/dist/number/branded-types/negative-finite-number.mjs.map +1 -1
  53. package/dist/number/branded-types/negative-int.d.mts +3 -16
  54. package/dist/number/branded-types/negative-int.d.mts.map +1 -1
  55. package/dist/number/branded-types/negative-int.mjs +9 -11
  56. package/dist/number/branded-types/negative-int.mjs.map +1 -1
  57. package/dist/number/branded-types/negative-safe-int.d.mts +3 -17
  58. package/dist/number/branded-types/negative-safe-int.d.mts.map +1 -1
  59. package/dist/number/branded-types/negative-safe-int.mjs +9 -11
  60. package/dist/number/branded-types/negative-safe-int.mjs.map +1 -1
  61. package/dist/number/branded-types/non-negative-finite-number.d.mts +4 -14
  62. package/dist/number/branded-types/non-negative-finite-number.d.mts.map +1 -1
  63. package/dist/number/branded-types/non-negative-finite-number.mjs +9 -9
  64. package/dist/number/branded-types/non-negative-finite-number.mjs.map +1 -1
  65. package/dist/number/branded-types/non-negative-int16.d.mts +3 -19
  66. package/dist/number/branded-types/non-negative-int16.d.mts.map +1 -1
  67. package/dist/number/branded-types/non-negative-int16.mjs +9 -10
  68. package/dist/number/branded-types/non-negative-int16.mjs.map +1 -1
  69. package/dist/number/branded-types/non-negative-int32.d.mts +3 -17
  70. package/dist/number/branded-types/non-negative-int32.d.mts.map +1 -1
  71. package/dist/number/branded-types/non-negative-int32.mjs +9 -10
  72. package/dist/number/branded-types/non-negative-int32.mjs.map +1 -1
  73. package/dist/number/branded-types/non-positive-finite-number.d.mts +4 -14
  74. package/dist/number/branded-types/non-positive-finite-number.d.mts.map +1 -1
  75. package/dist/number/branded-types/non-positive-finite-number.mjs +9 -9
  76. package/dist/number/branded-types/non-positive-finite-number.mjs.map +1 -1
  77. package/dist/number/branded-types/non-positive-int.d.mts +3 -14
  78. package/dist/number/branded-types/non-positive-int.d.mts.map +1 -1
  79. package/dist/number/branded-types/non-positive-int.mjs +9 -10
  80. package/dist/number/branded-types/non-positive-int.mjs.map +1 -1
  81. package/dist/number/branded-types/non-positive-safe-int.d.mts +3 -15
  82. package/dist/number/branded-types/non-positive-safe-int.d.mts.map +1 -1
  83. package/dist/number/branded-types/non-positive-safe-int.mjs +9 -10
  84. package/dist/number/branded-types/non-positive-safe-int.mjs.map +1 -1
  85. package/dist/number/branded-types/non-zero-finite-number.d.mts +4 -10
  86. package/dist/number/branded-types/non-zero-finite-number.d.mts.map +1 -1
  87. package/dist/number/branded-types/non-zero-finite-number.mjs +9 -10
  88. package/dist/number/branded-types/non-zero-finite-number.mjs.map +1 -1
  89. package/dist/number/branded-types/non-zero-int.d.mts +3 -10
  90. package/dist/number/branded-types/non-zero-int.d.mts.map +1 -1
  91. package/dist/number/branded-types/non-zero-int.mjs +9 -11
  92. package/dist/number/branded-types/non-zero-int.mjs.map +1 -1
  93. package/dist/number/branded-types/non-zero-int16.d.mts +3 -19
  94. package/dist/number/branded-types/non-zero-int16.d.mts.map +1 -1
  95. package/dist/number/branded-types/non-zero-int16.mjs +12 -11
  96. package/dist/number/branded-types/non-zero-int16.mjs.map +1 -1
  97. package/dist/number/branded-types/non-zero-int32.d.mts +3 -15
  98. package/dist/number/branded-types/non-zero-int32.d.mts.map +1 -1
  99. package/dist/number/branded-types/non-zero-int32.mjs +12 -11
  100. package/dist/number/branded-types/non-zero-int32.mjs.map +1 -1
  101. package/dist/number/branded-types/non-zero-safe-int.d.mts +6 -14
  102. package/dist/number/branded-types/non-zero-safe-int.d.mts.map +1 -1
  103. package/dist/number/branded-types/non-zero-safe-int.mjs +9 -13
  104. package/dist/number/branded-types/non-zero-safe-int.mjs.map +1 -1
  105. package/dist/number/branded-types/non-zero-uint16.d.mts +3 -20
  106. package/dist/number/branded-types/non-zero-uint16.d.mts.map +1 -1
  107. package/dist/number/branded-types/non-zero-uint16.mjs +9 -11
  108. package/dist/number/branded-types/non-zero-uint16.mjs.map +1 -1
  109. package/dist/number/branded-types/non-zero-uint32.d.mts +3 -18
  110. package/dist/number/branded-types/non-zero-uint32.d.mts.map +1 -1
  111. package/dist/number/branded-types/non-zero-uint32.mjs +9 -11
  112. package/dist/number/branded-types/non-zero-uint32.mjs.map +1 -1
  113. package/dist/number/branded-types/positive-finite-number.d.mts +4 -16
  114. package/dist/number/branded-types/positive-finite-number.d.mts.map +1 -1
  115. package/dist/number/branded-types/positive-finite-number.mjs +9 -9
  116. package/dist/number/branded-types/positive-finite-number.mjs.map +1 -1
  117. package/dist/number/branded-types/positive-int.d.mts +3 -16
  118. package/dist/number/branded-types/positive-int.d.mts.map +1 -1
  119. package/dist/number/branded-types/positive-int.mjs +9 -10
  120. package/dist/number/branded-types/positive-int.mjs.map +1 -1
  121. package/dist/number/branded-types/positive-int16.d.mts +3 -21
  122. package/dist/number/branded-types/positive-int16.d.mts.map +1 -1
  123. package/dist/number/branded-types/positive-int16.mjs +9 -10
  124. package/dist/number/branded-types/positive-int16.mjs.map +1 -1
  125. package/dist/number/branded-types/positive-int32.d.mts +3 -19
  126. package/dist/number/branded-types/positive-int32.d.mts.map +1 -1
  127. package/dist/number/branded-types/positive-int32.mjs +9 -10
  128. package/dist/number/branded-types/positive-int32.mjs.map +1 -1
  129. package/dist/number/branded-types/positive-safe-int.d.mts +5 -19
  130. package/dist/number/branded-types/positive-safe-int.d.mts.map +1 -1
  131. package/dist/number/branded-types/positive-safe-int.mjs +9 -11
  132. package/dist/number/branded-types/positive-safe-int.mjs.map +1 -1
  133. package/dist/number/branded-types/positive-uint16.d.mts +3 -20
  134. package/dist/number/branded-types/positive-uint16.d.mts.map +1 -1
  135. package/dist/number/branded-types/positive-uint16.mjs +9 -10
  136. package/dist/number/branded-types/positive-uint16.mjs.map +1 -1
  137. package/dist/number/branded-types/positive-uint32.d.mts +3 -18
  138. package/dist/number/branded-types/positive-uint32.d.mts.map +1 -1
  139. package/dist/number/branded-types/positive-uint32.mjs +9 -10
  140. package/dist/number/branded-types/positive-uint32.mjs.map +1 -1
  141. package/dist/number/branded-types/safe-int.d.mts +5 -12
  142. package/dist/number/branded-types/safe-int.d.mts.map +1 -1
  143. package/dist/number/branded-types/safe-int.mjs +9 -12
  144. package/dist/number/branded-types/safe-int.mjs.map +1 -1
  145. package/dist/number/branded-types/safe-uint.d.mts +3 -15
  146. package/dist/number/branded-types/safe-uint.d.mts.map +1 -1
  147. package/dist/number/branded-types/safe-uint.mjs +9 -11
  148. package/dist/number/branded-types/safe-uint.mjs.map +1 -1
  149. package/dist/number/branded-types/uint.d.mts +3 -14
  150. package/dist/number/branded-types/uint.d.mts.map +1 -1
  151. package/dist/number/branded-types/uint.mjs +9 -10
  152. package/dist/number/branded-types/uint.mjs.map +1 -1
  153. package/dist/number/branded-types/uint16.d.mts +3 -18
  154. package/dist/number/branded-types/uint16.d.mts.map +1 -1
  155. package/dist/number/branded-types/uint16.mjs +9 -10
  156. package/dist/number/branded-types/uint16.mjs.map +1 -1
  157. package/dist/number/branded-types/uint32.d.mts +3 -16
  158. package/dist/number/branded-types/uint32.d.mts.map +1 -1
  159. package/dist/number/branded-types/uint32.mjs +9 -10
  160. package/dist/number/branded-types/uint32.mjs.map +1 -1
  161. package/dist/number/enum/int8.d.mts +13 -15
  162. package/dist/number/enum/int8.d.mts.map +1 -1
  163. package/dist/number/enum/int8.mjs +20 -25
  164. package/dist/number/enum/int8.mjs.map +1 -1
  165. package/dist/number/enum/uint8.d.mts +12 -14
  166. package/dist/number/enum/uint8.d.mts.map +1 -1
  167. package/dist/number/enum/uint8.mjs +18 -23
  168. package/dist/number/enum/uint8.mjs.map +1 -1
  169. package/dist/number/index.d.mts +1 -1
  170. package/dist/number/index.d.mts.map +1 -1
  171. package/dist/number/index.mjs +1 -1
  172. package/dist/number/index.mjs.map +1 -1
  173. package/dist/number/num/impl/index.d.mts +2 -0
  174. package/dist/number/num/impl/index.d.mts.map +1 -0
  175. package/dist/number/num/impl/index.mjs +2 -0
  176. package/dist/number/num/impl/index.mjs.map +1 -0
  177. package/dist/number/num/impl/num.d.mts +531 -0
  178. package/dist/number/num/impl/num.d.mts.map +1 -0
  179. package/dist/number/num/impl/num.mjs +542 -0
  180. package/dist/number/num/impl/num.mjs.map +1 -0
  181. package/dist/number/num/index.d.mts +17 -0
  182. package/dist/number/num/index.d.mts.map +1 -0
  183. package/dist/number/num/index.mjs +17 -0
  184. package/dist/number/num/index.mjs.map +1 -0
  185. package/dist/number/operators/finite-number.d.mts +16 -0
  186. package/dist/number/operators/finite-number.d.mts.map +1 -0
  187. package/dist/number/operators/finite-number.mjs +7 -0
  188. package/dist/number/operators/finite-number.mjs.map +1 -0
  189. package/dist/number/operators/int.d.mts +16 -0
  190. package/dist/number/operators/int.d.mts.map +1 -0
  191. package/dist/number/operators/int.mjs +8 -0
  192. package/dist/number/operators/int.mjs.map +1 -0
  193. package/dist/number/operators/int16.d.mts +25 -0
  194. package/dist/number/operators/int16.d.mts.map +1 -0
  195. package/dist/number/operators/int16.mjs +8 -0
  196. package/dist/number/operators/int16.mjs.map +1 -0
  197. package/dist/number/operators/int32.d.mts +21 -0
  198. package/dist/number/operators/int32.d.mts.map +1 -0
  199. package/dist/number/operators/int32.mjs +8 -0
  200. package/dist/number/operators/int32.mjs.map +1 -0
  201. package/dist/number/operators/int8.d.mts +24 -0
  202. package/dist/number/operators/int8.d.mts.map +1 -0
  203. package/dist/number/operators/int8.mjs +8 -0
  204. package/dist/number/operators/int8.mjs.map +1 -0
  205. package/dist/number/operators/negative-finite-number.d.mts +11 -0
  206. package/dist/number/operators/negative-finite-number.d.mts.map +1 -0
  207. package/dist/number/operators/negative-finite-number.mjs +8 -0
  208. package/dist/number/operators/negative-finite-number.mjs.map +1 -0
  209. package/dist/number/operators/negative-int.d.mts +10 -0
  210. package/dist/number/operators/negative-int.d.mts.map +1 -0
  211. package/dist/number/operators/negative-int.mjs +9 -0
  212. package/dist/number/operators/negative-int.mjs.map +1 -0
  213. package/dist/number/operators/negative-safe-int.d.mts +10 -0
  214. package/dist/number/operators/negative-safe-int.d.mts.map +1 -0
  215. package/dist/number/operators/negative-safe-int.mjs +9 -0
  216. package/dist/number/operators/negative-safe-int.mjs.map +1 -0
  217. package/dist/number/operators/non-negative-finite-number.d.mts +22 -0
  218. package/dist/number/operators/non-negative-finite-number.d.mts.map +1 -0
  219. package/dist/number/operators/non-negative-finite-number.mjs +7 -0
  220. package/dist/number/operators/non-negative-finite-number.mjs.map +1 -0
  221. package/dist/number/operators/non-negative-int16.d.mts +27 -0
  222. package/dist/number/operators/non-negative-int16.d.mts.map +1 -0
  223. package/dist/number/operators/non-negative-int16.mjs +8 -0
  224. package/dist/number/operators/non-negative-int16.mjs.map +1 -0
  225. package/dist/number/operators/non-negative-int32.d.mts +25 -0
  226. package/dist/number/operators/non-negative-int32.d.mts.map +1 -0
  227. package/dist/number/operators/non-negative-int32.mjs +8 -0
  228. package/dist/number/operators/non-negative-int32.mjs.map +1 -0
  229. package/dist/number/operators/non-positive-finite-number.d.mts +11 -0
  230. package/dist/number/operators/non-positive-finite-number.d.mts.map +1 -0
  231. package/dist/number/operators/non-positive-finite-number.mjs +7 -0
  232. package/dist/number/operators/non-positive-finite-number.mjs.map +1 -0
  233. package/dist/number/operators/non-positive-int.d.mts +10 -0
  234. package/dist/number/operators/non-positive-int.d.mts.map +1 -0
  235. package/dist/number/operators/non-positive-int.mjs +8 -0
  236. package/dist/number/operators/non-positive-int.mjs.map +1 -0
  237. package/dist/number/operators/non-positive-safe-int.d.mts +10 -0
  238. package/dist/number/operators/non-positive-safe-int.d.mts.map +1 -0
  239. package/dist/number/operators/non-positive-safe-int.mjs +8 -0
  240. package/dist/number/operators/non-positive-safe-int.mjs.map +1 -0
  241. package/dist/number/operators/non-zero-finite-number.d.mts +16 -0
  242. package/dist/number/operators/non-zero-finite-number.d.mts.map +1 -0
  243. package/dist/number/operators/non-zero-finite-number.mjs +8 -0
  244. package/dist/number/operators/non-zero-finite-number.mjs.map +1 -0
  245. package/dist/number/operators/non-zero-int.d.mts +10 -0
  246. package/dist/number/operators/non-zero-int.d.mts.map +1 -0
  247. package/dist/number/operators/non-zero-int.mjs +9 -0
  248. package/dist/number/operators/non-zero-int.mjs.map +1 -0
  249. package/dist/number/operators/non-zero-int16.d.mts +10 -0
  250. package/dist/number/operators/non-zero-int16.d.mts.map +1 -0
  251. package/dist/number/operators/non-zero-int16.mjs +9 -0
  252. package/dist/number/operators/non-zero-int16.mjs.map +1 -0
  253. package/dist/number/operators/non-zero-int32.d.mts +10 -0
  254. package/dist/number/operators/non-zero-int32.d.mts.map +1 -0
  255. package/dist/number/operators/non-zero-int32.mjs +9 -0
  256. package/dist/number/operators/non-zero-int32.mjs.map +1 -0
  257. package/dist/number/operators/non-zero-safe-int.d.mts +10 -0
  258. package/dist/number/operators/non-zero-safe-int.d.mts.map +1 -0
  259. package/dist/number/operators/non-zero-safe-int.mjs +11 -0
  260. package/dist/number/operators/non-zero-safe-int.mjs.map +1 -0
  261. package/dist/number/operators/non-zero-uint16.d.mts +2 -0
  262. package/dist/number/operators/non-zero-uint16.d.mts.map +1 -0
  263. package/dist/number/operators/non-zero-uint16.mjs +9 -0
  264. package/dist/number/operators/non-zero-uint16.mjs.map +1 -0
  265. package/dist/number/operators/non-zero-uint32.d.mts +2 -0
  266. package/dist/number/operators/non-zero-uint32.d.mts.map +1 -0
  267. package/dist/number/operators/non-zero-uint32.mjs +9 -0
  268. package/dist/number/operators/non-zero-uint32.mjs.map +1 -0
  269. package/dist/number/operators/positive-finite-number.d.mts +23 -0
  270. package/dist/number/operators/positive-finite-number.d.mts.map +1 -0
  271. package/dist/number/operators/positive-finite-number.mjs +7 -0
  272. package/dist/number/operators/positive-finite-number.mjs.map +1 -0
  273. package/dist/number/operators/positive-int.d.mts +23 -0
  274. package/dist/number/operators/positive-int.d.mts.map +1 -0
  275. package/dist/number/operators/positive-int.mjs +8 -0
  276. package/dist/number/operators/positive-int.mjs.map +1 -0
  277. package/dist/number/operators/positive-int16.d.mts +28 -0
  278. package/dist/number/operators/positive-int16.d.mts.map +1 -0
  279. package/dist/number/operators/positive-int16.mjs +8 -0
  280. package/dist/number/operators/positive-int16.mjs.map +1 -0
  281. package/dist/number/operators/positive-int32.d.mts +26 -0
  282. package/dist/number/operators/positive-int32.d.mts.map +1 -0
  283. package/dist/number/operators/positive-int32.mjs +8 -0
  284. package/dist/number/operators/positive-int32.mjs.map +1 -0
  285. package/dist/number/operators/positive-safe-int.d.mts +24 -0
  286. package/dist/number/operators/positive-safe-int.d.mts.map +1 -0
  287. package/dist/number/operators/positive-safe-int.mjs +9 -0
  288. package/dist/number/operators/positive-safe-int.mjs.map +1 -0
  289. package/dist/number/operators/positive-uint16.d.mts +27 -0
  290. package/dist/number/operators/positive-uint16.d.mts.map +1 -0
  291. package/dist/number/operators/positive-uint16.mjs +8 -0
  292. package/dist/number/operators/positive-uint16.mjs.map +1 -0
  293. package/dist/number/operators/positive-uint32.d.mts +25 -0
  294. package/dist/number/operators/positive-uint32.d.mts.map +1 -0
  295. package/dist/number/operators/positive-uint32.mjs +8 -0
  296. package/dist/number/operators/positive-uint32.mjs.map +1 -0
  297. package/dist/number/operators/safe-int.d.mts +17 -0
  298. package/dist/number/operators/safe-int.d.mts.map +1 -0
  299. package/dist/number/operators/safe-int.mjs +10 -0
  300. package/dist/number/operators/safe-int.mjs.map +1 -0
  301. package/dist/number/operators/safe-uint.d.mts +22 -0
  302. package/dist/number/operators/safe-uint.d.mts.map +1 -0
  303. package/dist/number/operators/safe-uint.mjs +9 -0
  304. package/dist/number/operators/safe-uint.mjs.map +1 -0
  305. package/dist/number/operators/uint.d.mts +14 -0
  306. package/dist/number/operators/uint.d.mts.map +1 -0
  307. package/dist/number/operators/uint.mjs +8 -0
  308. package/dist/number/operators/uint.mjs.map +1 -0
  309. package/dist/number/operators/uint16.d.mts +25 -0
  310. package/dist/number/operators/uint16.d.mts.map +1 -0
  311. package/dist/number/operators/uint16.mjs +8 -0
  312. package/dist/number/operators/uint16.mjs.map +1 -0
  313. package/dist/number/operators/uint32.d.mts +23 -0
  314. package/dist/number/operators/uint32.d.mts.map +1 -0
  315. package/dist/number/operators/uint32.mjs +8 -0
  316. package/dist/number/operators/uint32.mjs.map +1 -0
  317. package/dist/number/operators/uint8.d.mts +24 -0
  318. package/dist/number/operators/uint8.d.mts.map +1 -0
  319. package/dist/number/operators/uint8.mjs +8 -0
  320. package/dist/number/operators/uint8.mjs.map +1 -0
  321. package/dist/number/refined-number-utils.d.mts +2 -2
  322. package/dist/number/refined-number-utils.d.mts.map +1 -1
  323. package/dist/number/refined-number-utils.mjs +1 -1
  324. package/dist/number/refined-number-utils.mjs.map +1 -1
  325. package/dist/object/object.d.mts +8 -0
  326. package/dist/object/object.d.mts.map +1 -1
  327. package/dist/object/object.mjs +17 -5
  328. package/dist/object/object.mjs.map +1 -1
  329. package/dist/others/fast-deep-equal.mjs +1 -1
  330. package/dist/others/fast-deep-equal.mjs.map +1 -1
  331. package/dist/others/replace-equal-deep.mjs +10 -3
  332. package/dist/others/replace-equal-deep.mjs.map +1 -1
  333. package/package.json +22 -9
  334. package/src/array/impl/array-utils-reducing-value.mts +4 -3
  335. package/src/array/impl/array-utils-shape-invariants.test.mts +1 -1
  336. package/src/array/impl/array-utils-slice-clamped.mts +1 -1
  337. package/src/array/impl/array-utils-slicing.mts +12 -3
  338. package/src/array/impl/array-utils-transformation.mts +7 -3
  339. package/src/array/impl/array-utils-transformation.test.mts +52 -3
  340. package/src/array/impl/array-utils-validation.mts +2 -1
  341. package/src/built-in-tag.mts +59 -0
  342. package/src/built-in-tag.test.mts +215 -0
  343. package/src/collections/imap-mapped.mts +6 -4
  344. package/src/collections/imap-mapped.test.mts +27 -0
  345. package/src/collections/imap.mts +6 -4
  346. package/src/collections/imap.test.mts +13 -0
  347. package/src/collections/stack.mts +3 -3
  348. package/src/iterator/range.mts +10 -2
  349. package/src/iterator/range.test.mts +7 -0
  350. package/src/json/json.mts +17 -57
  351. package/src/json/json.test.mts +32 -0
  352. package/src/number/branded-types/finite-number.mts +23 -25
  353. package/src/number/branded-types/int.mts +20 -26
  354. package/src/number/branded-types/int16.mts +21 -26
  355. package/src/number/branded-types/int32.mts +21 -26
  356. package/src/number/branded-types/negative-finite-number.mts +25 -26
  357. package/src/number/branded-types/negative-int.mts +20 -27
  358. package/src/number/branded-types/negative-safe-int.mts +23 -28
  359. package/src/number/branded-types/non-negative-finite-number.mts +24 -25
  360. package/src/number/branded-types/non-negative-int16.mts +23 -26
  361. package/src/number/branded-types/non-negative-int32.mts +23 -26
  362. package/src/number/branded-types/non-positive-finite-number.mts +24 -25
  363. package/src/number/branded-types/non-positive-int.mts +20 -26
  364. package/src/number/branded-types/non-positive-safe-int.mts +21 -26
  365. package/src/number/branded-types/non-zero-finite-number.mts +23 -25
  366. package/src/number/branded-types/non-zero-int.mts +19 -25
  367. package/src/number/branded-types/non-zero-int16.mts +27 -28
  368. package/src/number/branded-types/non-zero-int32.mts +27 -28
  369. package/src/number/branded-types/non-zero-safe-int.mts +25 -35
  370. package/src/number/branded-types/non-zero-uint16.mts +24 -28
  371. package/src/number/branded-types/non-zero-uint32.mts +24 -28
  372. package/src/number/branded-types/positive-finite-number.mts +25 -25
  373. package/src/number/branded-types/positive-int.mts +21 -26
  374. package/src/number/branded-types/positive-int16.mts +23 -26
  375. package/src/number/branded-types/positive-int32.mts +23 -26
  376. package/src/number/branded-types/positive-safe-int.mts +24 -31
  377. package/src/number/branded-types/positive-uint16.mts +23 -26
  378. package/src/number/branded-types/positive-uint32.mts +23 -26
  379. package/src/number/branded-types/safe-int.mts +22 -29
  380. package/src/number/branded-types/safe-uint.mts +21 -27
  381. package/src/number/branded-types/uint.mts +21 -26
  382. package/src/number/branded-types/uint16.mts +21 -26
  383. package/src/number/branded-types/uint32.mts +21 -26
  384. package/src/number/enum/int8.mts +40 -52
  385. package/src/number/enum/uint8.mts +40 -48
  386. package/src/number/index.mts +1 -1
  387. package/src/number/num/impl/index.mts +1 -0
  388. package/src/number/num/impl/num.mts +715 -0
  389. package/src/number/{num.test.mts → num/impl/num.test.mts} +17 -5
  390. package/src/number/num/index.mts +16 -0
  391. package/src/number/num-arithmetic.test.mts +1 -1
  392. package/src/number/operators/finite-number.mts +20 -0
  393. package/src/number/operators/int.mts +20 -0
  394. package/src/number/operators/int16.mts +33 -0
  395. package/src/number/operators/int32.mts +33 -0
  396. package/src/number/operators/int8.mts +18 -0
  397. package/src/number/operators/negative-finite-number.mts +22 -0
  398. package/src/number/operators/negative-int.mts +22 -0
  399. package/src/number/operators/negative-safe-int.mts +32 -0
  400. package/src/number/operators/non-negative-finite-number.mts +32 -0
  401. package/src/number/operators/non-negative-int16.mts +33 -0
  402. package/src/number/operators/non-negative-int32.mts +33 -0
  403. package/src/number/operators/non-positive-finite-number.mts +21 -0
  404. package/src/number/operators/non-positive-int.mts +21 -0
  405. package/src/number/operators/non-positive-safe-int.mts +31 -0
  406. package/src/number/operators/non-zero-finite-number.mts +21 -0
  407. package/src/number/operators/non-zero-int.mts +22 -0
  408. package/src/number/operators/non-zero-int16.mts +32 -0
  409. package/src/number/operators/non-zero-int32.mts +32 -0
  410. package/src/number/operators/non-zero-safe-int.mts +34 -0
  411. package/src/number/operators/non-zero-uint16.mts +32 -0
  412. package/src/number/operators/non-zero-uint32.mts +32 -0
  413. package/src/number/operators/positive-finite-number.mts +32 -0
  414. package/src/number/operators/positive-int.mts +32 -0
  415. package/src/number/operators/positive-int16.mts +33 -0
  416. package/src/number/operators/positive-int32.mts +33 -0
  417. package/src/number/operators/positive-safe-int.mts +34 -0
  418. package/src/number/operators/positive-uint16.mts +33 -0
  419. package/src/number/operators/positive-uint32.mts +33 -0
  420. package/src/number/operators/safe-int.mts +35 -0
  421. package/src/number/operators/safe-uint.mts +33 -0
  422. package/src/number/operators/uint.mts +31 -0
  423. package/src/number/operators/uint16.mts +32 -0
  424. package/src/number/operators/uint32.mts +32 -0
  425. package/src/number/operators/uint8.mts +16 -0
  426. package/src/number/refined-number-utils.mts +4 -4
  427. package/src/object/object.mts +33 -5
  428. package/src/object/object.test.mts +55 -0
  429. package/src/others/fast-deep-equal.mts +1 -1
  430. package/src/others/replace-equal-deep.mts +11 -4
  431. package/src/others/replace-equal-deep.test.mts +26 -0
  432. package/dist/number/num.d.mts +0 -546
  433. package/dist/number/num.d.mts.map +0 -1
  434. package/dist/number/num.mjs +0 -559
  435. package/dist/number/num.mjs.map +0 -1
  436. package/src/guard/is-error.test.mts +0 -145
  437. package/src/number/num.mts +0 -731
@@ -12,6 +12,7 @@ import { SafeUint } from '../../number/index.mjs';
12
12
  import { asMinLengthArray } from './array-utils-length-bounded-array-cast.mjs';
13
13
  import {
14
14
  cartesianProduct,
15
+ chunk,
15
16
  concat,
16
17
  filter,
17
18
  filterNot,
@@ -759,13 +760,61 @@ describe('Arr transformations', () => {
759
760
  ]);
760
761
  });
761
762
 
762
- test('should work with chunk size < 2 (returns empty)', () => {
763
+ test('returns singleton chunks for size one', () => {
763
764
  const numbers = [1, 2, 3] as const;
764
765
 
765
766
  const result = partition(numbers, 1);
766
767
 
767
- // According to docs, returns empty array if chunkSize < 2
768
- assert.deepStrictEqual(result, []);
768
+ expectType<typeof result, readonly BoundedLengthArray<1, 1, 1 | 2 | 3>[]>(
769
+ '~=',
770
+ );
771
+
772
+ assert.deepStrictEqual<readonly (readonly number[])[]>(result, [
773
+ [1],
774
+ [2],
775
+ [3],
776
+ ]);
777
+ });
778
+
779
+ test('preserves singleton chunks through the alias and curried overloads', () => {
780
+ const numbers = [1, 2, 3] as const;
781
+
782
+ const expected = [[1], [2], [3]] as const;
783
+
784
+ assert.deepStrictEqual<readonly (readonly number[])[]>(
785
+ partition(1)(numbers),
786
+ expected,
787
+ );
788
+
789
+ assert.deepStrictEqual<readonly (readonly number[])[]>(
790
+ chunk(numbers, 1),
791
+ expected,
792
+ );
793
+
794
+ assert.deepStrictEqual<readonly (readonly number[])[]>(
795
+ chunk(1)(numbers),
796
+ expected,
797
+ );
798
+ });
799
+
800
+ test('size one produces no chunk for an empty array', () => {
801
+ assert.deepStrictEqual(partition([], 1), []);
802
+
803
+ assert.deepStrictEqual(partition(1)([]), []);
804
+
805
+ assert.deepStrictEqual(chunk([], 1), []);
806
+
807
+ assert.deepStrictEqual(chunk(1)([]), []);
808
+ });
809
+
810
+ test('a size below one, which the types reject, produces no chunk', () => {
811
+ const numbers = [1, 2, 3] as const;
812
+
813
+ // @ts-expect-error - a chunk size of 0 is not a positive integer
814
+ assert.deepStrictEqual(partition(numbers, 0), []);
815
+
816
+ // @ts-expect-error - a negative chunk size is not a positive integer
817
+ assert.deepStrictEqual(partition(-1)(numbers), []);
769
818
  });
770
819
 
771
820
  test('should work with chunk size larger than array', () => {
@@ -5,7 +5,8 @@ import type {
5
5
  IsUnknown,
6
6
  UnknownBrand,
7
7
  } from 'ts-type-forge';
8
- import { asUint32, Num } from '../../number/index.mjs';
8
+ import { asUint32 } from '../../number/index.mjs';
9
+ import * as Num from '../../number/num/impl/index.mjs';
9
10
  import type { ArrayIndex, SizeType } from '../../types.mjs';
10
11
 
11
12
  /**
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Type guards for the built-in objects this package special-cases, read from
3
+ * the `Object.prototype.toString` tag as `@sindresorhus/is` reads it, so that
4
+ * each answers as it did when this package depended on that one: an object from
5
+ * another realm is recognized, which `instanceof` misses, and an error-like
6
+ * plain object is not. ts-std-forge keeps the same guards for itself; neither
7
+ * package exports them.
8
+ *
9
+ * They replace that dependency because `@sindresorhus/is` keeps most of itself
10
+ * in a bundle that imports any one of its guards.
11
+ *
12
+ * Not part of the package's API: `gen:index:src` leaves this file out of the
13
+ * barrel.
14
+ */
15
+
16
+ export const isError = (value: unknown): value is Error =>
17
+ tagOf(value) === 'Error';
18
+
19
+ export const isRegExp = (value: unknown): value is RegExp =>
20
+ tagOf(value) === 'RegExp';
21
+
22
+ export const isMap = (value: unknown): value is ReadonlyMap<unknown, unknown> =>
23
+ tagOf(value) === 'Map';
24
+
25
+ export const isSet = (value: unknown): value is ReadonlySet<unknown> =>
26
+ tagOf(value) === 'Set';
27
+
28
+ export const isTypedArray = (value: unknown): value is TypedArray =>
29
+ typedArrayTags.has(tagOf(value));
30
+
31
+ type TypedArray =
32
+ | Int8Array
33
+ | Uint8Array
34
+ | Uint8ClampedArray
35
+ | Int16Array
36
+ | Uint16Array
37
+ | Int32Array
38
+ | Uint32Array
39
+ | Float32Array
40
+ | Float64Array
41
+ | BigInt64Array
42
+ | BigUint64Array;
43
+
44
+ const typedArrayTags: ReadonlySet<string> = new Set<string>([
45
+ 'Int8Array',
46
+ 'Uint8Array',
47
+ 'Uint8ClampedArray',
48
+ 'Int16Array',
49
+ 'Uint16Array',
50
+ 'Int32Array',
51
+ 'Uint32Array',
52
+ 'Float32Array',
53
+ 'Float64Array',
54
+ 'BigInt64Array',
55
+ 'BigUint64Array',
56
+ ]);
57
+
58
+ const tagOf = (value: unknown): string =>
59
+ Object.prototype.toString.call(value).slice(8, -1);
@@ -0,0 +1,215 @@
1
+ /* eslint-disable functional/no-class-inheritance */
2
+ /* eslint-disable unicorn/error-message */
3
+ import {
4
+ isError,
5
+ isMap,
6
+ isRegExp,
7
+ isSet,
8
+ isTypedArray,
9
+ } from './built-in-tag.mjs';
10
+ import { expectType } from './expect-type.mjs';
11
+
12
+ describe(isError, () => {
13
+ test('should return true for native Error instances', () => {
14
+ assert.isTrue(isError(new Error()));
15
+
16
+ assert.isTrue(isError(new Error('test message')));
17
+ });
18
+
19
+ test('should return true for native Error subclasses', () => {
20
+ assert.isTrue(isError(new TypeError()));
21
+
22
+ assert.isTrue(isError(new RangeError()));
23
+
24
+ assert.isTrue(isError(new ReferenceError()));
25
+
26
+ assert.isTrue(isError(new SyntaxError()));
27
+
28
+ assert.isTrue(isError(new EvalError()));
29
+
30
+ assert.isTrue(isError(new URIError()));
31
+ });
32
+
33
+ test('should return true for custom Error subclasses', () => {
34
+ class CustomError extends Error {
35
+ constructor(message?: string) {
36
+ super(message);
37
+
38
+ this.name = 'CustomError';
39
+ }
40
+ }
41
+
42
+ assert.isTrue(isError(new CustomError()));
43
+
44
+ assert.isTrue(isError(new CustomError('custom error message')));
45
+ });
46
+
47
+ test('should return true for Error subclass with additional properties', () => {
48
+ class ExtendedError extends Error {
49
+ readonly code: number;
50
+
51
+ constructor(message: string, code: number) {
52
+ super(message);
53
+
54
+ this.name = 'ExtendedError';
55
+
56
+ this.code = code;
57
+ }
58
+ }
59
+
60
+ assert.isTrue(isError(new ExtendedError('error with code', 404)));
61
+ });
62
+
63
+ test('should return true for deeply nested Error subclass', () => {
64
+ class BaseCustomError extends Error {
65
+ constructor(message?: string) {
66
+ super(message);
67
+
68
+ this.name = 'BaseCustomError';
69
+ }
70
+ }
71
+
72
+ class DerivedCustomError extends BaseCustomError {
73
+ constructor(message?: string) {
74
+ super(message);
75
+
76
+ this.name = 'DerivedCustomError';
77
+ }
78
+ }
79
+
80
+ assert.isTrue(isError(new DerivedCustomError()));
81
+ });
82
+
83
+ test('should return false for Error-like objects', () => {
84
+ const errorLikeObject = {
85
+ name: 'Error',
86
+ message: 'This is not a real error',
87
+ stack: 'fake stack trace',
88
+ } as const;
89
+
90
+ assert.isFalse(isError(errorLikeObject));
91
+ });
92
+
93
+ test('should return false for non-Error values', () => {
94
+ assert.isFalse(isError(null));
95
+
96
+ assert.isFalse(isError(undefined));
97
+
98
+ assert.isFalse(isError(0));
99
+
100
+ assert.isFalse(isError(''));
101
+
102
+ assert.isFalse(isError('Error'));
103
+
104
+ assert.isFalse(isError(true));
105
+
106
+ assert.isFalse(isError({}));
107
+
108
+ assert.isFalse(isError([]));
109
+
110
+ assert.isFalse(isError(() => {}));
111
+ });
112
+
113
+ test('should act as a type guard', () => {
114
+ const value: Error | string = new Error('test');
115
+
116
+ if (!isError(value)) {
117
+ return;
118
+ }
119
+
120
+ expectType<typeof value, Error>('=');
121
+
122
+ expect(value.message).toBe('test');
123
+ });
124
+
125
+ test('should work with AggregateError', () => {
126
+ const aggregateError = new AggregateError(
127
+ [new Error('error 1'), new Error('error 2')],
128
+ 'Multiple errors occurred',
129
+ );
130
+
131
+ assert.isTrue(isError(aggregateError));
132
+ });
133
+
134
+ test('should return false for errors created with Object.create', () => {
135
+ // Built and then re-pointed rather than `Object.create(Error.prototype)`,
136
+ // which the strict standard library types as `unknown` — correctly, since
137
+ // it knows nothing about the resulting shape. The object under test is the
138
+ // same: Error.prototype in its chain, never constructed as an Error.
139
+ const mut_protoError = { message: 'proto error', name: 'ProtoError' };
140
+
141
+ Object.setPrototypeOf(mut_protoError, Error.prototype);
142
+
143
+ const protoError = mut_protoError;
144
+
145
+ assert.isFalse(isError(protoError));
146
+ });
147
+ });
148
+
149
+ describe(isMap, () => {
150
+ test('should return true for a Map only', () => {
151
+ assert.isTrue(isMap(new Map<number, number>([[1, 2]])));
152
+
153
+ assert.isFalse(isMap(new WeakMap<object, unknown>()));
154
+
155
+ assert.isFalse(isMap(new Set<unknown>()));
156
+
157
+ assert.isFalse(isMap({ size: 0 }));
158
+ });
159
+ });
160
+
161
+ describe(isSet, () => {
162
+ test('should return true for a Set only', () => {
163
+ assert.isTrue(isSet(new Set<number>([1])));
164
+
165
+ assert.isFalse(isSet(new WeakSet<object>()));
166
+
167
+ assert.isFalse(isSet(new Map<unknown, unknown>()));
168
+
169
+ assert.isFalse(isSet([1]));
170
+ });
171
+ });
172
+
173
+ describe(isRegExp, () => {
174
+ test('should return true for a RegExp only', () => {
175
+ assert.isTrue(isRegExp(/a/u));
176
+
177
+ assert.isFalse(isRegExp('/a/u'));
178
+
179
+ assert.isFalse(isRegExp({ source: 'a', flags: 'u' }));
180
+ });
181
+ });
182
+
183
+ describe(isTypedArray, () => {
184
+ test('should return true for every typed array', () => {
185
+ assert.isTrue(isTypedArray(new Int8Array(1)));
186
+
187
+ assert.isTrue(isTypedArray(new Uint8Array(1)));
188
+
189
+ assert.isTrue(isTypedArray(new Uint8ClampedArray(1)));
190
+
191
+ assert.isTrue(isTypedArray(new Int16Array(1)));
192
+
193
+ assert.isTrue(isTypedArray(new Uint16Array(1)));
194
+
195
+ assert.isTrue(isTypedArray(new Int32Array(1)));
196
+
197
+ assert.isTrue(isTypedArray(new Uint32Array(1)));
198
+
199
+ assert.isTrue(isTypedArray(new Float32Array(1)));
200
+
201
+ assert.isTrue(isTypedArray(new Float64Array(1)));
202
+
203
+ assert.isTrue(isTypedArray(new BigInt64Array(1)));
204
+
205
+ assert.isTrue(isTypedArray(new BigUint64Array(1)));
206
+ });
207
+
208
+ test('should return false for other binary views and arrays', () => {
209
+ assert.isFalse(isTypedArray(new DataView(new ArrayBuffer(1))));
210
+
211
+ assert.isFalse(isTypedArray(new ArrayBuffer(1)));
212
+
213
+ assert.isFalse(isTypedArray([1, 2]));
214
+ });
215
+ });
@@ -1161,9 +1161,9 @@ class IMapMappedClass<K, V, KM extends MapSetKeyType>
1161
1161
  break;
1162
1162
 
1163
1163
  case 'update': {
1164
- const curr = mut_result.get(key);
1165
-
1166
- if (curr === undefined || !mut_result.has(key)) {
1164
+ // Presence is `has` alone, as in `update`: a stored value may itself
1165
+ // be `undefined`.
1166
+ if (!mut_result.has(key)) {
1167
1167
  if (this.#showNotFoundMessage) {
1168
1168
  console.warn(
1169
1169
  `IMapMapped.withMutations::update: key not found: ${unknownToString(key)}`,
@@ -1173,7 +1173,9 @@ class IMapMappedClass<K, V, KM extends MapSetKeyType>
1173
1173
  break;
1174
1174
  }
1175
1175
 
1176
- mut_result.set(key, action.updater(curr));
1176
+ // `has` held, so `get` returns the stored `V`, `undefined` included.
1177
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
1178
+ mut_result.set(key, action.updater(mut_result.get(key) as V));
1177
1179
 
1178
1180
  break;
1179
1181
  }
@@ -705,6 +705,33 @@ describe('IMapMapped.withMutations', () => {
705
705
  expect(Optional.unwrap(updated.get({ id: 2, type: 'admin' }))).toBe('Bob');
706
706
  });
707
707
 
708
+ test('update calls the updater for a key whose value is undefined, as update() does', () => {
709
+ const map = IMapMapped.create<TestKey, string | undefined, string>(
710
+ [[{ id: 1, type: 'user' }, undefined]],
711
+ testKeyToString,
712
+ stringToTestKey,
713
+ );
714
+
715
+ const updater = (x: string | undefined): string | undefined =>
716
+ x ?? 'filled';
717
+
718
+ const batched = map.withMutations([
719
+ { type: 'update', key: { id: 1, type: 'user' }, updater },
720
+ ]);
721
+
722
+ expect(Optional.unwrap(batched.get({ id: 1, type: 'user' }))).toBe(
723
+ 'filled',
724
+ );
725
+
726
+ expect(
727
+ Optional.unwrap(
728
+ map
729
+ .update({ id: 1, type: 'user' }, updater)
730
+ .get({ id: 1, type: 'user' }),
731
+ ),
732
+ ).toBe('filled');
733
+ });
734
+
708
735
  test('should handle empty mutations array', () => {
709
736
  const map = IMapMapped.create(
710
737
  [[{ id: 1, type: 'user' }, 'Alice']],
@@ -880,9 +880,9 @@ class IMapClass<K extends MapSetKeyType, V>
880
880
  case 'update': {
881
881
  const { key } = action;
882
882
 
883
- const curr = mut_result.get(key);
884
-
885
- if (curr === undefined || !mut_result.has(key)) {
883
+ // Presence is `has` alone, as in `update`: a stored value may itself
884
+ // be `undefined`.
885
+ if (!mut_result.has(key)) {
886
886
  if (this.#showNotFoundMessage) {
887
887
  const keyStr = unknownToString(key);
888
888
 
@@ -892,7 +892,9 @@ class IMapClass<K extends MapSetKeyType, V>
892
892
  break;
893
893
  }
894
894
 
895
- mut_result.set(key, action.updater(curr));
895
+ // `has` held, so `get` returns the stored `V`, `undefined` included.
896
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
897
+ mut_result.set(key, action.updater(mut_result.get(key) as V));
896
898
 
897
899
  break;
898
900
  }
@@ -754,6 +754,19 @@ describe('IMap.withMutations', () => {
754
754
  assert.isTrue(Optional.isNone(updated.get('nonexistent')));
755
755
  });
756
756
 
757
+ test('update calls the updater for a key whose value is undefined, as update() does', () => {
758
+ const map = IMap.create<string, number | undefined>([['a', undefined]]);
759
+
760
+ const updater = (x: number | undefined): number | undefined =>
761
+ x === undefined ? 1 : x + 1;
762
+
763
+ const batched = map.withMutations([{ type: 'update', key: 'a', updater }]);
764
+
765
+ expect(Optional.unwrap(batched.get('a'))).toBe(1);
766
+
767
+ expect(Optional.unwrap(map.update('a', updater).get('a'))).toBe(1);
768
+ });
769
+
757
770
  test('should handle mixed operations', () => {
758
771
  const map = IMap.create([['a', 1]]);
759
772
 
@@ -1,6 +1,6 @@
1
1
  import { Optional } from '../functional/index.mjs';
2
2
  import { range } from '../iterator/index.mjs';
3
- import { asUint32, Uint32 } from '../number/index.mjs';
3
+ import { asUint32, type Uint32 } from '../number/index.mjs';
4
4
  import type { SizeType } from '../types.mjs';
5
5
 
6
6
  /**
@@ -285,7 +285,7 @@ class StackClass<T> implements Stack<T> {
285
285
  return Optional.none;
286
286
  }
287
287
 
288
- this.#mut_size = Uint32.sub(this.#mut_size, 1);
288
+ this.#mut_size = asUint32(this.#mut_size - 1);
289
289
 
290
290
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
291
291
  const element = this.#mut_buffer[this.#mut_size]!;
@@ -320,7 +320,7 @@ class StackClass<T> implements Stack<T> {
320
320
 
321
321
  this.#mut_buffer[this.#mut_size] = value;
322
322
 
323
- this.#mut_size = Uint32.add(this.#mut_size, 1);
323
+ this.#mut_size = asUint32(this.#mut_size + 1);
324
324
  }
325
325
  }
326
326
 
@@ -1,5 +1,6 @@
1
1
  import type { NonZeroSafeInt, SafeUint, WithSmallInt } from 'ts-type-forge';
2
- import { SafeInt, asSafeInt } from '../number/index.mjs';
2
+ import { asSafeInt, type SafeInt } from '../number/index.mjs';
3
+ import * as Num from '../number/num/impl/index.mjs';
3
4
 
4
5
  /**
5
6
  * Generates a sequence of numbers within a specified range using a generator
@@ -109,7 +110,14 @@ export function* range(
109
110
  for (
110
111
  let mut_i: SafeInt = asSafeInt(start);
111
112
  step > 0 ? mut_i < end : mut_i > end;
112
- mut_i = SafeInt.add(mut_i, asSafeInt(step))
113
+ // Saturates as `SafeInt.add` does, without the `SafeInt` object.
114
+ mut_i = asSafeInt(
115
+ Num.clamp(
116
+ mut_i + asSafeInt(step),
117
+ Number.MIN_SAFE_INTEGER,
118
+ Number.MAX_SAFE_INTEGER,
119
+ ),
120
+ )
113
121
  ) {
114
122
  yield mut_i;
115
123
  }
@@ -78,4 +78,11 @@ describe(range, () => {
78
78
 
79
79
  assert.deepStrictEqual(xs, [0, -1]);
80
80
  });
81
+
82
+ // The step is checked before it is added, as `SafeInt.add` used to have it
83
+ // checked, so an unchecked caller gets an error rather than an endless loop.
84
+ test('a step that is not a safe integer throws', () => {
85
+ // @ts-expect-error -- the type forbids it; an unchecked caller can still pass it
86
+ assert.throws(() => Array.from(range(0, 10, Number.POSITIVE_INFINITY)));
87
+ });
81
88
  });
package/src/json/json.mts CHANGED
@@ -3,8 +3,7 @@ import type {
3
3
  UintRangeInclusive,
4
4
  UnknownRecord,
5
5
  } from 'ts-type-forge';
6
- import { Arr } from '../array/index.mjs';
7
- import { pipe, Result } from '../functional/index.mjs';
6
+ import { Result } from '../functional/index.mjs';
8
7
  import { isRecord } from '../guard/index.mjs';
9
8
  import { castMutable, unknownToString } from '../others/index.mjs';
10
9
 
@@ -323,63 +322,24 @@ export namespace Json {
323
322
  value: UnknownRecord,
324
323
  space?: UintRangeInclusive<1, 10> | string,
325
324
  ): Result<string | undefined, string> => {
326
- const allKeys = pipe(keysDeep(value))
327
- .map(Arr.uniq)
328
- .map((ks) => ks.toSorted()).value;
325
+ // The keys are collected by a first pass with a function replacer, which
326
+ // `JSON.stringify` calls at every nesting level with the value after
327
+ // `toJSON`, so the allowlist of the second pass misses none of them. The
328
+ // allowlist also fixes the order, sorting integer-like keys as strings.
329
+ const mut_keys = new Set<string>();
329
330
 
330
- return stringifySelected(value, allKeys, space);
331
- };
332
- }
333
-
334
- /**
335
- * @param obj - The record to extract keys from. Must be a plain object.
336
- * @param mut_keys - A mutable array to accumulate the collected keys. This
337
- * array will be modified in-place by the function for performance reasons.
338
- * @internal
339
- * Recursively collects all property keys from a nested object structure.
340
- *
341
- * This helper function traverses an object and its nested objects and arrays,
342
- * collecting all string keys found at any level of nesting. The function mutates
343
- * the provided keys array for performance reasons.
344
- */
345
- const keysDeepImpl = (
346
- obj: UnknownRecord,
347
- // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
348
- mut_keys: string[],
349
- ): void => {
350
- for (const [k, v] of Object.entries(obj)) {
351
- mut_keys.push(k);
352
-
353
- if (isRecord(v)) {
354
- keysDeepImpl(v, mut_keys);
355
- }
356
-
357
- if (Array.isArray(v)) {
358
- for (const li of v) {
359
- if (isRecord(li)) {
360
- keysDeepImpl(li, mut_keys);
331
+ const collected = stringify(value, (_key, v) => {
332
+ if (isRecord(v)) {
333
+ for (const k of Object.keys(v)) {
334
+ mut_keys.add(k);
361
335
  }
362
336
  }
363
- }
364
- }
365
- };
366
337
 
367
- /**
368
- * @param obj - The record to extract keys from. Must be a plain object.
369
- * @returns A readonly array of all string keys found in the object and its
370
- * nested objects/arrays. May contain duplicates if the same key appears at
371
- * multiple levels.
372
- * @internal
373
- * Extracts all property keys from a nested object structure into a flat array.
374
- *
375
- * This function serves as a safe wrapper around `keysDeepImpl`, creating a new
376
- * mutable array and passing it to the recursive implementation. The result
377
- * contains all keys found at any level of nesting within the input object.
378
- */
379
- const keysDeep = (obj: UnknownRecord): readonly string[] => {
380
- const mut_keys: string[] = [];
338
+ return v;
339
+ });
381
340
 
382
- keysDeepImpl(obj, mut_keys);
383
-
384
- return mut_keys;
385
- };
341
+ return Result.isErr(collected)
342
+ ? collected
343
+ : stringifySelected(value, Array.from(mut_keys).toSorted(), space);
344
+ };
345
+ }
@@ -709,6 +709,38 @@ describe('stringifySortedKey', () => {
709
709
  }
710
710
  });
711
711
 
712
+ test('keeps the properties of an object nested in an array of arrays', () => {
713
+ const result = Json.stringifySortedKey({ a: [[{ c: 1, b: 2 }]] });
714
+
715
+ assert.isTrue(Result.isOk(result));
716
+
717
+ expect(result.value).toBe('{"a":[[{"b":2,"c":1}]]}');
718
+
719
+ const other = Json.stringifySortedKey({ a: [[{ c: 1, b: 3 }]] });
720
+
721
+ assert.isTrue(Result.isOk(other));
722
+
723
+ expect(other.value).not.toBe(result.value);
724
+ });
725
+
726
+ test('keeps the properties of what toJSON returns', () => {
727
+ const result = Json.stringifySortedKey({
728
+ x: { toJSON: () => ({ z: 1, y: 2 }) },
729
+ });
730
+
731
+ assert.isTrue(Result.isOk(result));
732
+
733
+ expect(result.value).toBe('{"x":{"y":2,"z":1}}');
734
+ });
735
+
736
+ test('sorts integer-like keys as strings', () => {
737
+ const result = Json.stringifySortedKey({ 2: 'b', 10: 'a', x: 'c' });
738
+
739
+ assert.isTrue(Result.isOk(result));
740
+
741
+ expect(result.value).toBe('{"10":"a","2":"b","x":"c"}');
742
+ });
743
+
712
744
  test('should handle empty object', () => {
713
745
  const result = Json.stringifySortedKey({});
714
746