ts-data-forge 6.13.1 → 7.0.1

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 (257) hide show
  1. package/README.md +2 -2
  2. package/dist/array/impl/array-utils-creation.d.mts.map +1 -1
  3. package/dist/array/impl/array-utils-creation.mjs +1 -1
  4. package/dist/array/impl/array-utils-creation.mjs.map +1 -1
  5. package/dist/array/impl/array-utils-iterators.mjs +7 -1
  6. package/dist/array/impl/array-utils-iterators.mjs.map +1 -1
  7. package/dist/array/impl/array-utils-modification.mjs +6 -0
  8. package/dist/array/impl/array-utils-modification.mjs.map +1 -1
  9. package/dist/array/impl/array-utils-reducing-value.d.mts +1 -1
  10. package/dist/array/impl/array-utils-reducing-value.d.mts.map +1 -1
  11. package/dist/array/impl/array-utils-reducing-value.mjs +6 -1
  12. package/dist/array/impl/array-utils-reducing-value.mjs.map +1 -1
  13. package/dist/array/impl/array-utils-search.d.mts +0 -2
  14. package/dist/array/impl/array-utils-search.d.mts.map +1 -1
  15. package/dist/array/impl/array-utils-search.mjs +6 -0
  16. package/dist/array/impl/array-utils-search.mjs.map +1 -1
  17. package/dist/array/impl/array-utils-set-op.d.mts.map +1 -1
  18. package/dist/array/impl/array-utils-set-op.mjs +0 -1
  19. package/dist/array/impl/array-utils-set-op.mjs.map +1 -1
  20. package/dist/array/impl/array-utils-slice-clamped.mjs +6 -0
  21. package/dist/array/impl/array-utils-slice-clamped.mjs.map +1 -1
  22. package/dist/array/impl/array-utils-slicing.mjs +6 -0
  23. package/dist/array/impl/array-utils-slicing.mjs.map +1 -1
  24. package/dist/array/impl/array-utils-transformation.d.mts +1 -1
  25. package/dist/array/impl/array-utils-transformation.d.mts.map +1 -1
  26. package/dist/array/impl/array-utils-transformation.mjs +8 -4
  27. package/dist/array/impl/array-utils-transformation.mjs.map +1 -1
  28. package/dist/array/impl/array-utils-validation.d.mts.map +1 -1
  29. package/dist/array/impl/array-utils-validation.mjs +9 -9
  30. package/dist/array/impl/array-utils-validation.mjs.map +1 -1
  31. package/dist/collections/imap-mapped.d.mts +622 -3
  32. package/dist/collections/imap-mapped.d.mts.map +1 -1
  33. package/dist/collections/imap-mapped.mjs +117 -18
  34. package/dist/collections/imap-mapped.mjs.map +1 -1
  35. package/dist/collections/imap.d.mts +3 -3
  36. package/dist/collections/imap.d.mts.map +1 -1
  37. package/dist/collections/imap.mjs +12 -5
  38. package/dist/collections/imap.mjs.map +1 -1
  39. package/dist/collections/iset-mapped.d.mts +4 -4
  40. package/dist/collections/iset-mapped.d.mts.map +1 -1
  41. package/dist/collections/iset-mapped.mjs +14 -4
  42. package/dist/collections/iset-mapped.mjs.map +1 -1
  43. package/dist/collections/iset.d.mts +2 -2
  44. package/dist/collections/iset.d.mts.map +1 -1
  45. package/dist/collections/iset.mjs +11 -2
  46. package/dist/collections/iset.mjs.map +1 -1
  47. package/dist/collections/queue.mjs +26 -20
  48. package/dist/collections/queue.mjs.map +1 -1
  49. package/dist/collections/stack.mjs +23 -17
  50. package/dist/collections/stack.mjs.map +1 -1
  51. package/dist/entry-point.mjs +6 -0
  52. package/dist/entry-point.mjs.map +1 -1
  53. package/dist/functional/optional/impl/optional-flat-map.d.mts +2 -2
  54. package/dist/functional/pipe.d.mts.map +1 -1
  55. package/dist/functional/pipe.mjs.map +1 -1
  56. package/dist/functional/result/impl/result-flat-map.d.mts +2 -2
  57. package/dist/functional/ternary-result/impl/ternary-result-flat-map.d.mts +5 -3
  58. package/dist/functional/ternary-result/impl/ternary-result-flat-map.d.mts.map +1 -1
  59. package/dist/functional/ternary-result/impl/ternary-result-flat-map.mjs.map +1 -1
  60. package/dist/guard/has-key.d.mts.map +1 -1
  61. package/dist/guard/has-key.mjs +1 -3
  62. package/dist/guard/has-key.mjs.map +1 -1
  63. package/dist/guard/is-non-null-object.d.mts.map +1 -1
  64. package/dist/guard/is-non-null-object.mjs +1 -3
  65. package/dist/guard/is-non-null-object.mjs.map +1 -1
  66. package/dist/guard/key-is-in.d.mts.map +1 -1
  67. package/dist/guard/key-is-in.mjs +1 -3
  68. package/dist/guard/key-is-in.mjs.map +1 -1
  69. package/dist/index.mjs +6 -0
  70. package/dist/index.mjs.map +1 -1
  71. package/dist/iterator/range.mjs +6 -0
  72. package/dist/iterator/range.mjs.map +1 -1
  73. package/dist/json/json.mjs +11 -7
  74. package/dist/json/json.mjs.map +1 -1
  75. package/dist/number/branded-types/finite-number.d.mts +1 -1
  76. package/dist/number/branded-types/index.d.mts +6 -0
  77. package/dist/number/branded-types/index.d.mts.map +1 -1
  78. package/dist/number/branded-types/index.mjs +6 -0
  79. package/dist/number/branded-types/index.mjs.map +1 -1
  80. package/dist/number/branded-types/int.d.mts +1 -2
  81. package/dist/number/branded-types/int.d.mts.map +1 -1
  82. package/dist/number/branded-types/int16.d.mts +2 -3
  83. package/dist/number/branded-types/int16.d.mts.map +1 -1
  84. package/dist/number/branded-types/int32.d.mts +2 -3
  85. package/dist/number/branded-types/int32.d.mts.map +1 -1
  86. package/dist/number/branded-types/negative-finite-number.d.mts +143 -0
  87. package/dist/number/branded-types/negative-finite-number.d.mts.map +1 -0
  88. package/dist/number/branded-types/negative-finite-number.mjs +156 -0
  89. package/dist/number/branded-types/negative-finite-number.mjs.map +1 -0
  90. package/dist/number/branded-types/negative-int.d.mts +120 -0
  91. package/dist/number/branded-types/negative-int.d.mts.map +1 -0
  92. package/dist/number/branded-types/negative-int.mjs +125 -0
  93. package/dist/number/branded-types/negative-int.mjs.map +1 -0
  94. package/dist/number/branded-types/negative-safe-int.d.mts +132 -0
  95. package/dist/number/branded-types/negative-safe-int.d.mts.map +1 -0
  96. package/dist/number/branded-types/negative-safe-int.mjs +136 -0
  97. package/dist/number/branded-types/negative-safe-int.mjs.map +1 -0
  98. package/dist/number/branded-types/non-negative-finite-number.d.mts +1 -1
  99. package/dist/number/branded-types/non-negative-int16.d.mts +1 -1
  100. package/dist/number/branded-types/non-negative-int32.d.mts +1 -1
  101. package/dist/number/branded-types/non-positive-finite-number.d.mts +130 -0
  102. package/dist/number/branded-types/non-positive-finite-number.d.mts.map +1 -0
  103. package/dist/number/branded-types/non-positive-finite-number.mjs +134 -0
  104. package/dist/number/branded-types/non-positive-finite-number.mjs.map +1 -0
  105. package/dist/number/branded-types/non-positive-int.d.mts +224 -0
  106. package/dist/number/branded-types/non-positive-int.d.mts.map +1 -0
  107. package/dist/number/branded-types/non-positive-int.mjs +222 -0
  108. package/dist/number/branded-types/non-positive-int.mjs.map +1 -0
  109. package/dist/number/branded-types/non-positive-safe-int.d.mts +119 -0
  110. package/dist/number/branded-types/non-positive-safe-int.d.mts.map +1 -0
  111. package/dist/number/branded-types/non-positive-safe-int.mjs +116 -0
  112. package/dist/number/branded-types/non-positive-safe-int.mjs.map +1 -0
  113. package/dist/number/branded-types/non-zero-finite-number.d.mts +5 -17
  114. package/dist/number/branded-types/non-zero-finite-number.d.mts.map +1 -1
  115. package/dist/number/branded-types/non-zero-finite-number.mjs +5 -17
  116. package/dist/number/branded-types/non-zero-finite-number.mjs.map +1 -1
  117. package/dist/number/branded-types/non-zero-int.d.mts +5 -33
  118. package/dist/number/branded-types/non-zero-int.d.mts.map +1 -1
  119. package/dist/number/branded-types/non-zero-int.mjs +5 -25
  120. package/dist/number/branded-types/non-zero-int.mjs.map +1 -1
  121. package/dist/number/branded-types/non-zero-int16.d.mts +6 -43
  122. package/dist/number/branded-types/non-zero-int16.d.mts.map +1 -1
  123. package/dist/number/branded-types/non-zero-int16.mjs +5 -25
  124. package/dist/number/branded-types/non-zero-int16.mjs.map +1 -1
  125. package/dist/number/branded-types/non-zero-int32.d.mts +6 -39
  126. package/dist/number/branded-types/non-zero-int32.d.mts.map +1 -1
  127. package/dist/number/branded-types/non-zero-int32.mjs +5 -25
  128. package/dist/number/branded-types/non-zero-int32.mjs.map +1 -1
  129. package/dist/number/branded-types/non-zero-safe-int.d.mts +5 -37
  130. package/dist/number/branded-types/non-zero-safe-int.d.mts.map +1 -1
  131. package/dist/number/branded-types/non-zero-safe-int.mjs +7 -30
  132. package/dist/number/branded-types/non-zero-safe-int.mjs.map +1 -1
  133. package/dist/number/branded-types/non-zero-uint16.d.mts +6 -33
  134. package/dist/number/branded-types/non-zero-uint16.d.mts.map +1 -1
  135. package/dist/number/branded-types/non-zero-uint16.mjs +5 -17
  136. package/dist/number/branded-types/non-zero-uint16.mjs.map +1 -1
  137. package/dist/number/branded-types/non-zero-uint32.d.mts +6 -31
  138. package/dist/number/branded-types/non-zero-uint32.d.mts.map +1 -1
  139. package/dist/number/branded-types/non-zero-uint32.mjs +5 -17
  140. package/dist/number/branded-types/non-zero-uint32.mjs.map +1 -1
  141. package/dist/number/branded-types/positive-finite-number.d.mts +4 -2
  142. package/dist/number/branded-types/positive-finite-number.d.mts.map +1 -1
  143. package/dist/number/branded-types/positive-int.d.mts +4 -2
  144. package/dist/number/branded-types/positive-int.d.mts.map +1 -1
  145. package/dist/number/branded-types/positive-int16.d.mts +4 -2
  146. package/dist/number/branded-types/positive-int16.d.mts.map +1 -1
  147. package/dist/number/branded-types/positive-int32.d.mts +4 -2
  148. package/dist/number/branded-types/positive-int32.d.mts.map +1 -1
  149. package/dist/number/branded-types/positive-safe-int.d.mts +4 -2
  150. package/dist/number/branded-types/positive-safe-int.d.mts.map +1 -1
  151. package/dist/number/branded-types/positive-safe-int.mjs +1 -1
  152. package/dist/number/branded-types/positive-uint16.d.mts +4 -2
  153. package/dist/number/branded-types/positive-uint16.d.mts.map +1 -1
  154. package/dist/number/branded-types/positive-uint32.d.mts +4 -2
  155. package/dist/number/branded-types/positive-uint32.d.mts.map +1 -1
  156. package/dist/number/branded-types/safe-int.d.mts +1 -2
  157. package/dist/number/branded-types/safe-int.d.mts.map +1 -1
  158. package/dist/number/branded-types/safe-int.mjs +2 -2
  159. package/dist/number/branded-types/safe-uint.d.mts +1 -1
  160. package/dist/number/branded-types/safe-uint.mjs +1 -1
  161. package/dist/number/branded-types/uint.d.mts +1 -1
  162. package/dist/number/branded-types/uint16.d.mts +1 -1
  163. package/dist/number/branded-types/uint32.d.mts +1 -1
  164. package/dist/number/index.d.mts +1 -0
  165. package/dist/number/index.d.mts.map +1 -1
  166. package/dist/number/index.mjs +6 -0
  167. package/dist/number/index.mjs.map +1 -1
  168. package/dist/number/num-arithmetic-types.d.mts +74 -0
  169. package/dist/number/num-arithmetic-types.d.mts.map +1 -0
  170. package/dist/number/num-arithmetic-types.mjs +2 -0
  171. package/dist/number/num-arithmetic-types.mjs.map +1 -0
  172. package/dist/number/num.d.mts +53 -9
  173. package/dist/number/num.d.mts.map +1 -1
  174. package/dist/number/num.mjs +67 -15
  175. package/dist/number/num.mjs.map +1 -1
  176. package/dist/number/refined-number-utils.d.mts +12 -9
  177. package/dist/number/refined-number-utils.d.mts.map +1 -1
  178. package/dist/number/refined-number-utils.mjs.map +1 -1
  179. package/dist/object/object.mjs +7 -1
  180. package/dist/object/object.mjs.map +1 -1
  181. package/dist/others/fast-deep-equal.d.mts.map +1 -1
  182. package/dist/others/fast-deep-equal.mjs +0 -1
  183. package/dist/others/fast-deep-equal.mjs.map +1 -1
  184. package/dist/others/unknown-to-string.mjs +2 -2
  185. package/dist/others/unknown-to-string.mjs.map +1 -1
  186. package/package.json +6 -6
  187. package/src/array/impl/array-utils-creation.mts +1 -1
  188. package/src/array/impl/array-utils-iterators.mts +1 -1
  189. package/src/array/impl/array-utils-reducing-value.mts +1 -2
  190. package/src/array/impl/array-utils-search.mts +0 -2
  191. package/src/array/impl/array-utils-set-op.mts +0 -1
  192. package/src/array/impl/array-utils-transformation.mts +8 -6
  193. package/src/array/impl/array-utils-validation.mts +1 -5
  194. package/src/collections/imap-mapped.mts +696 -34
  195. package/src/collections/imap-mapped.test.mts +61 -13
  196. package/src/collections/imap.mts +20 -9
  197. package/src/collections/imap.test.mts +9 -8
  198. package/src/collections/iset-mapped.mts +18 -10
  199. package/src/collections/iset-mapped.test.mts +6 -1
  200. package/src/collections/iset.mts +11 -4
  201. package/src/collections/iset.test.mts +6 -8
  202. package/src/collections/queue.mts +32 -32
  203. package/src/collections/stack.mts +26 -26
  204. package/src/functional/optional/impl/optional-flat-map.mts +2 -2
  205. package/src/functional/optional.test.mts +6 -4
  206. package/src/functional/pipe.mts +0 -1
  207. package/src/functional/pipe.test.mts +2 -1
  208. package/src/functional/result/impl/result-flat-map.mts +2 -2
  209. package/src/functional/result.test.mts +3 -2
  210. package/src/functional/ternary-result/impl/ternary-result-flat-map.mts +5 -3
  211. package/src/functional/ternary-result.test.mts +8 -3
  212. package/src/guard/has-key.mts +1 -3
  213. package/src/guard/is-non-null-object.mts +0 -1
  214. package/src/guard/key-is-in.mts +1 -3
  215. package/src/json/json.mts +5 -8
  216. package/src/json/json.test.mts +2 -2
  217. package/src/number/branded-types/index.mts +6 -0
  218. package/src/number/branded-types/negative-finite-number.mts +210 -0
  219. package/src/number/branded-types/negative-finite-number.test.mts +172 -0
  220. package/src/number/branded-types/negative-int.mts +160 -0
  221. package/src/number/branded-types/negative-int.test.mts +146 -0
  222. package/src/number/branded-types/negative-safe-int.mts +173 -0
  223. package/src/number/branded-types/negative-safe-int.test.mts +120 -0
  224. package/src/number/branded-types/non-positive-finite-number.mts +191 -0
  225. package/src/number/branded-types/non-positive-finite-number.test.mts +286 -0
  226. package/src/number/branded-types/non-positive-int.mts +251 -0
  227. package/src/number/branded-types/non-positive-int.test.mts +197 -0
  228. package/src/number/branded-types/non-positive-safe-int.mts +147 -0
  229. package/src/number/branded-types/non-positive-safe-int.test.mts +223 -0
  230. package/src/number/branded-types/non-zero-finite-number.mts +14 -22
  231. package/src/number/branded-types/non-zero-finite-number.test.mts +0 -12
  232. package/src/number/branded-types/non-zero-int.mts +10 -32
  233. package/src/number/branded-types/non-zero-int.test.mts +0 -20
  234. package/src/number/branded-types/non-zero-int16.mts +8 -32
  235. package/src/number/branded-types/non-zero-int16.test.mts +0 -30
  236. package/src/number/branded-types/non-zero-int32.mts +8 -32
  237. package/src/number/branded-types/non-zero-int32.test.mts +0 -30
  238. package/src/number/branded-types/non-zero-safe-int.mts +10 -37
  239. package/src/number/branded-types/non-zero-safe-int.test.mts +0 -32
  240. package/src/number/branded-types/non-zero-uint16.mts +8 -22
  241. package/src/number/branded-types/non-zero-uint16.test.mts +0 -16
  242. package/src/number/branded-types/non-zero-uint32.mts +8 -22
  243. package/src/number/branded-types/non-zero-uint32.test.mts +0 -16
  244. package/src/number/branded-types/positive-safe-int.mts +1 -1
  245. package/src/number/branded-types/safe-int.mts +2 -2
  246. package/src/number/branded-types/safe-uint.mts +1 -1
  247. package/src/number/index.mts +1 -0
  248. package/src/number/num-arithmetic-types.mts +265 -0
  249. package/src/number/num-arithmetic-types.test.mts +130 -0
  250. package/src/number/num-arithmetic.test.mts +102 -0
  251. package/src/number/num.mts +99 -18
  252. package/src/number/num.test.mts +2 -2
  253. package/src/number/refined-number-utils.mts +19 -9
  254. package/src/object/object.mts +2 -2
  255. package/src/others/fast-deep-equal.mts +0 -2
  256. package/src/others/map-nullable.test.mts +4 -3
  257. package/src/others/unknown-to-string.mts +2 -2
@@ -12,9 +12,9 @@ import { type UnwrapErr, type UnwrapOk } from './types.mjs';
12
12
  *
13
13
  * ```ts
14
14
  * const parseNumber = (input: string): Result<number, string> => {
15
- * const num = Number.parseInt(input, 10);
15
+ * const num = Num.safeParseInt(input);
16
16
  *
17
- * return Number.isNaN(num) ? Result.err('not a number') : Result.ok(num);
17
+ * return Result.mapErr(num, () => 'not a number');
18
18
  * };
19
19
  *
20
20
  * const parsed = Result.flatMap(Result.ok('42'), parseNumber);
@@ -1,4 +1,5 @@
1
1
  import { expectType } from '../expect-type.mjs';
2
+ import { Num } from '../number/index.mjs';
2
3
  import { type Err, type Ok } from '../types.mjs';
3
4
  import { Optional } from './optional/index.mjs';
4
5
  import { pipe } from './pipe.mjs';
@@ -467,7 +468,7 @@ describe('Result test', () => {
467
468
 
468
469
  test('should support chaining multiple flatMaps', () => {
469
470
  const parseNumber = (s: string): Result<number, string> => {
470
- const n = Number(s);
471
+ const n = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
471
472
 
472
473
  return Number.isNaN(n) ? Result.err('Not a number') : Result.ok(n);
473
474
  };
@@ -518,7 +519,7 @@ describe('Result test', () => {
518
519
 
519
520
  test('should work with pipe when curried', () => {
520
521
  const parseNumber = (s: string): Result<number, string> => {
521
- const n = Number(s);
522
+ const n = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
522
523
 
523
524
  return Number.isNaN(n) ? Result.err('Not a number') : Result.ok(n);
524
525
  };
@@ -15,9 +15,11 @@ import { type UnwrapErr, type UnwrapOk, type UnwrapWarn } from './types.mjs';
15
15
  *
16
16
  * ```ts
17
17
  * const parse = (value: string): TernaryResult<number, string, string> =>
18
- * Number.isNaN(Number(value))
19
- * ? TernaryResult.err('NaN')
20
- * : TernaryResult.ok(Number(value));
18
+ * pipe(Num.safeParseFloat(value)).map((result) =>
19
+ * Result.isErr(result)
20
+ * ? TernaryResult.err('NaN')
21
+ * : TernaryResult.ok(result.value),
22
+ * ).value;
21
23
  *
22
24
  * const doubled = TernaryResult.flatMap(TernaryResult.ok('3'), (text) =>
23
25
  * TernaryResult.map(parse(text), (num) => num * 2),
@@ -1,5 +1,8 @@
1
1
  import { expectType } from '../expect-type.mjs';
2
+ import { Num } from '../number/index.mjs';
2
3
  import { Optional } from './optional/index.mjs';
4
+ import { pipe } from './pipe.mjs';
5
+ import { Result } from './result/index.mjs';
3
6
  import { TernaryResult } from './ternary-result/index.mjs';
4
7
 
5
8
  describe('TernaryResult test', () => {
@@ -69,9 +72,11 @@ describe('TernaryResult test', () => {
69
72
 
70
73
  test('flatMap propagates Warn and Err while keeping warnings', () => {
71
74
  const parse = (value: string): TernaryResult<number, string, never> =>
72
- Number.isNaN(Number(value))
73
- ? TernaryResult.err('NaN')
74
- : TernaryResult.ok(Number(value));
75
+ pipe(Num.safeParseFloat(value)).map((result) =>
76
+ Result.isErr(result)
77
+ ? TernaryResult.err('NaN')
78
+ : TernaryResult.ok(result.value),
79
+ ).value;
75
80
 
76
81
  const warn = TernaryResult.warn('3', 'slow');
77
82
 
@@ -47,9 +47,7 @@ export const hasKey = <
47
47
  >(
48
48
  obj: R,
49
49
  key: K,
50
- ): obj is HasKeyReturnType<R, K> =>
51
- // eslint-disable-next-line ts-data-forge/prefer-is-record-and-has-key
52
- Object.hasOwn(obj, key);
50
+ ): obj is HasKeyReturnType<R, K> => Object.hasOwn(obj, key);
53
51
 
54
52
  /**
55
53
  * @internal
@@ -33,5 +33,4 @@
33
33
  */
34
34
  // eslint-disable-next-line @typescript-eslint/no-restricted-types
35
35
  export const isNonNullObject = (u: unknown): u is object =>
36
- // eslint-disable-next-line ts-data-forge/prefer-is-non-null-object
37
36
  typeof u === 'object' && u !== null;
@@ -46,6 +46,4 @@ export const keyIsIn = <
46
46
  >(
47
47
  key: K,
48
48
  obj: R,
49
- ): key is K & keyof typeof obj =>
50
- // eslint-disable-next-line ts-data-forge/prefer-is-record-and-has-key
51
- Object.hasOwn(obj, key);
49
+ ): key is K & keyof typeof obj => Object.hasOwn(obj, key);
package/src/json/json.mts CHANGED
@@ -350,18 +350,15 @@ const keysDeepImpl = (
350
350
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
351
351
  mut_keys: string[],
352
352
  ): void => {
353
- for (const k of Object.keys(obj)) {
353
+ for (const [k, v] of Object.entries(obj)) {
354
354
  mut_keys.push(k);
355
355
 
356
- const o = obj[k];
357
-
358
- if (isRecord(o)) {
359
- keysDeepImpl(o, mut_keys);
356
+ if (isRecord(v)) {
357
+ keysDeepImpl(v, mut_keys);
360
358
  }
361
359
 
362
- // eslint-disable-next-line ts-data-forge/prefer-arr-is-array
363
- if (Array.isArray(o)) {
364
- for (const li of o) {
360
+ if (Array.isArray(v)) {
361
+ for (const li of v) {
365
362
  if (isRecord(li)) {
366
363
  keysDeepImpl(li, mut_keys);
367
364
  }
@@ -1,6 +1,7 @@
1
1
  import { Arr } from '../array/index.mjs';
2
2
  import { Result } from '../functional/index.mjs';
3
3
  import { hasKey, isRecord, isString } from '../guard/index.mjs';
4
+ import { Num } from '../number/index.mjs';
4
5
  import { Json } from './json.mjs';
5
6
 
6
7
  describe('parse', () => {
@@ -154,7 +155,7 @@ describe('parse', () => {
154
155
  test('should handle reviver returning different types', () => {
155
156
  const transformReviver = (key: string, value: unknown): unknown => {
156
157
  if (key === 'number' && typeof value === 'string') {
157
- return Number.parseInt(value, 10);
158
+ return Result.unwrapOkOr(Num.safeParseInt(value), Number.NaN);
158
159
  }
159
160
 
160
161
  return value;
@@ -465,7 +466,6 @@ describe('stringifySelected', () => {
465
466
 
466
467
  // Note: stringifySelected works with JSON.stringify's replacer parameter
467
468
  // which may not work as expected with arrays
468
- // eslint-disable-next-line ts-data-forge/prefer-arr-is-array
469
469
  assert.isTrue(Array.isArray(parsed));
470
470
 
471
471
  expect(parsed).toHaveLength(3);
@@ -2,9 +2,15 @@ export * from './finite-number.mjs';
2
2
  export * from './int.mjs';
3
3
  export * from './int16.mjs';
4
4
  export * from './int32.mjs';
5
+ export * from './negative-finite-number.mjs';
6
+ export * from './negative-int.mjs';
7
+ export * from './negative-safe-int.mjs';
5
8
  export * from './non-negative-finite-number.mjs';
6
9
  export * from './non-negative-int16.mjs';
7
10
  export * from './non-negative-int32.mjs';
11
+ export * from './non-positive-finite-number.mjs';
12
+ export * from './non-positive-int.mjs';
13
+ export * from './non-positive-safe-int.mjs';
8
14
  export * from './non-zero-finite-number.mjs';
9
15
  export * from './non-zero-int.mjs';
10
16
  export * from './non-zero-int16.mjs';
@@ -0,0 +1,210 @@
1
+ import { type NegativeFiniteNumber as TtfImported_NegativeFiniteNumber } from 'ts-type-forge';
2
+ import { TsDataForgeInternals } from '../refined-number-utils.mjs';
3
+ import { PositiveFiniteNumber } from './positive-finite-number.mjs';
4
+
5
+ export type NegativeFiniteNumber = TtfImported_NegativeFiniteNumber;
6
+
7
+ type ElementType = NegativeFiniteNumber;
8
+
9
+ const typeNameInMessage = 'a negative finite number';
10
+
11
+ const {
12
+ MAX_VALUE,
13
+ add,
14
+ castType,
15
+ clamp,
16
+ is,
17
+ max: max_,
18
+ min: min_,
19
+ pow,
20
+ random,
21
+ sub,
22
+ } = TsDataForgeInternals.RefinedNumberUtils.operatorsForFloat<
23
+ ElementType,
24
+ number,
25
+ number
26
+ >({
27
+ nonZero: true,
28
+ MIN_VALUE: -Number.MAX_VALUE,
29
+ MAX_VALUE: -Number.MIN_VALUE,
30
+ typeNameInMessage,
31
+ } as const);
32
+
33
+ /**
34
+ * Returns the absolute value of a negative finite number.
35
+ *
36
+ * The absolute value of a negative finite number is always a positive finite
37
+ * number, so the result is typed as a {@link PositiveFiniteNumber}.
38
+ *
39
+ * @param x - The negative finite number.
40
+ * @returns `|x|` as a PositiveFiniteNumber.
41
+ */
42
+ const abs = (x: ElementType): PositiveFiniteNumber =>
43
+ PositiveFiniteNumber.clamp(Math.abs(x));
44
+
45
+ const floor = (
46
+ x: ElementType,
47
+ ): TsDataForgeInternals.RefinedNumberUtils.ToInt<ElementType> =>
48
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
49
+ Math.floor(x) as TsDataForgeInternals.RefinedNumberUtils.ToInt<ElementType>;
50
+
51
+ const ceil = (
52
+ x: ElementType,
53
+ ): TsDataForgeInternals.RefinedNumberUtils.RemoveNonZeroBrandKey<
54
+ TsDataForgeInternals.RefinedNumberUtils.ToInt<ElementType>
55
+ > =>
56
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
57
+ Math.ceil(x) as TsDataForgeInternals.RefinedNumberUtils.RemoveNonZeroBrandKey<
58
+ TsDataForgeInternals.RefinedNumberUtils.ToInt<ElementType>
59
+ >;
60
+
61
+ const round = (
62
+ x: ElementType,
63
+ ): TsDataForgeInternals.RefinedNumberUtils.RemoveNonZeroBrandKey<
64
+ TsDataForgeInternals.RefinedNumberUtils.ToInt<ElementType>
65
+ > =>
66
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
67
+ Math.round(
68
+ x,
69
+ ) as TsDataForgeInternals.RefinedNumberUtils.RemoveNonZeroBrandKey<
70
+ TsDataForgeInternals.RefinedNumberUtils.ToInt<ElementType>
71
+ >;
72
+
73
+ /**
74
+ * Checks if a number is a NegativeFiniteNumber (a finite number `< 0`).
75
+ *
76
+ * @param value The value to check.
77
+ * @returns `true` if the value is a NegativeFiniteNumber, `false` otherwise.
78
+ */
79
+ export const isNegativeFiniteNumber = is;
80
+
81
+ /**
82
+ * Casts a number to a NegativeFiniteNumber type.
83
+ *
84
+ * @param value The value to cast.
85
+ * @returns The value as a NegativeFiniteNumber type.
86
+ * @throws {TypeError} If the value is not a negative finite number.
87
+ */
88
+ export const asNegativeFiniteNumber = castType;
89
+
90
+ /**
91
+ * Namespace providing type-safe arithmetic operations for negative finite
92
+ * numbers.
93
+ *
94
+ * All operations keep results finite (excluding NaN and Infinity). Operations
95
+ * that stay within the negative finite numbers clamp their results to the valid
96
+ * range, while operations whose result leaves the set (`mul`, `div`, `abs`) are
97
+ * typed to reflect the actual sign of the result.
98
+ */
99
+ export const NegativeFiniteNumber = {
100
+ /**
101
+ * Type guard to check if a value is a NegativeFiniteNumber.
102
+ *
103
+ * @param value The value to check.
104
+ * @returns `true` if the value is a negative finite number, `false`
105
+ * otherwise.
106
+ */
107
+ is,
108
+
109
+ /**
110
+ * The maximum value for a negative finite number.
111
+ *
112
+ * @readonly
113
+ */
114
+ MAX_VALUE,
115
+
116
+ /**
117
+ * Returns the absolute value of a negative finite number.
118
+ *
119
+ * @param a The negative finite number.
120
+ * @returns The absolute value as a PositiveFiniteNumber.
121
+ */
122
+ abs,
123
+
124
+ /**
125
+ * Returns the smaller of two NegativeFiniteNumber values.
126
+ *
127
+ * @param a The first NegativeFiniteNumber.
128
+ * @param b The second NegativeFiniteNumber.
129
+ * @returns The minimum value as a NegativeFiniteNumber.
130
+ */
131
+ min: min_,
132
+
133
+ /**
134
+ * Returns the larger of two NegativeFiniteNumber values.
135
+ *
136
+ * @param a The first NegativeFiniteNumber.
137
+ * @param b The second NegativeFiniteNumber.
138
+ * @returns The maximum value as a NegativeFiniteNumber.
139
+ */
140
+ max: max_,
141
+
142
+ /**
143
+ * Clamps a number to the negative finite range.
144
+ *
145
+ * @param value The number to clamp.
146
+ * @returns The value clamped to `(-∞, 0)` as a NegativeFiniteNumber.
147
+ */
148
+ clamp,
149
+
150
+ /**
151
+ * Rounds down a NegativeFiniteNumber to the nearest integer.
152
+ *
153
+ * @param x The NegativeFiniteNumber to round down.
154
+ * @returns The floor value as a NegativeInt (always `<= -1`).
155
+ */
156
+ floor,
157
+
158
+ /**
159
+ * Rounds up a NegativeFiniteNumber to the nearest integer.
160
+ *
161
+ * @param x The NegativeFiniteNumber to round up.
162
+ * @returns The ceiling value as a NonPositiveInt (can be 0).
163
+ */
164
+ ceil,
165
+
166
+ /**
167
+ * Rounds a NegativeFiniteNumber to the nearest integer.
168
+ *
169
+ * @param x The NegativeFiniteNumber to round.
170
+ * @returns The rounded value as a NonPositiveInt (can be 0 if x > -0.5).
171
+ */
172
+ round,
173
+
174
+ /**
175
+ * Generates a random NegativeFiniteNumber value.
176
+ *
177
+ * @returns A random negative finite number.
178
+ */
179
+ random,
180
+
181
+ /**
182
+ * Raises a NegativeFiniteNumber to the power of another NegativeFiniteNumber.
183
+ *
184
+ * @param a The base NegativeFiniteNumber.
185
+ * @param b The exponent NegativeFiniteNumber.
186
+ * @returns `a ** b` clamped to `(-∞, 0)` as a NegativeFiniteNumber.
187
+ */
188
+ pow,
189
+
190
+ /**
191
+ * Adds two NegativeFiniteNumber values.
192
+ *
193
+ * @param a The first NegativeFiniteNumber.
194
+ * @param b The second NegativeFiniteNumber.
195
+ * @returns `a + b` as a NegativeFiniteNumber.
196
+ */
197
+ add,
198
+
199
+ /**
200
+ * Subtracts one NegativeFiniteNumber from another.
201
+ *
202
+ * The mathematical result can be positive, so it is clamped to the negative
203
+ * finite range (maximum `-Number.MIN_VALUE`).
204
+ *
205
+ * @param a The minuend NegativeFiniteNumber.
206
+ * @param b The subtrahend NegativeFiniteNumber.
207
+ * @returns `a - b` clamped to `(-∞, 0)` as a NegativeFiniteNumber.
208
+ */
209
+ sub,
210
+ } as const;
@@ -0,0 +1,172 @@
1
+ import {
2
+ type NegativeInt,
3
+ type NonPositiveInt,
4
+ type PositiveFiniteNumber,
5
+ } from 'ts-type-forge';
6
+ import { expectType } from '../../expect-type.mjs';
7
+ import { range } from '../../iterator/index.mjs';
8
+ import {
9
+ asNegativeFiniteNumber,
10
+ isNegativeFiniteNumber,
11
+ NegativeFiniteNumber,
12
+ } from './negative-finite-number.mjs';
13
+
14
+ describe('NegativeFiniteNumber test', () => {
15
+ describe(asNegativeFiniteNumber, () => {
16
+ test('accepts valid negative finite numbers', () => {
17
+ expect(() => asNegativeFiniteNumber(-1)).not.toThrow();
18
+
19
+ expect(() => asNegativeFiniteNumber(-1.5)).not.toThrow();
20
+
21
+ expect(() => asNegativeFiniteNumber(-1e308)).not.toThrow();
22
+ });
23
+
24
+ test('rejects zero and positive numbers', () => {
25
+ expect(() => asNegativeFiniteNumber(0)).toThrow(TypeError);
26
+
27
+ expect(() => asNegativeFiniteNumber(1.5)).toThrow(TypeError);
28
+ });
29
+
30
+ test('rejects non-finite values', () => {
31
+ expect(() => asNegativeFiniteNumber(Number.NaN)).toThrow(TypeError);
32
+
33
+ expect(() => asNegativeFiniteNumber(Number.NEGATIVE_INFINITY)).toThrow(
34
+ TypeError,
35
+ );
36
+ });
37
+ });
38
+
39
+ describe(isNegativeFiniteNumber, () => {
40
+ test('correctly identifies negative finite numbers', () => {
41
+ assert.isTrue(isNegativeFiniteNumber(-1));
42
+
43
+ assert.isTrue(isNegativeFiniteNumber(-1.5));
44
+
45
+ assert.isFalse(isNegativeFiniteNumber(0));
46
+
47
+ assert.isFalse(isNegativeFiniteNumber(1));
48
+
49
+ assert.isFalse(isNegativeFiniteNumber(Number.NEGATIVE_INFINITY));
50
+ });
51
+ });
52
+
53
+ describe('NegativeFiniteNumber.is', () => {
54
+ test('works as a type guard', () => {
55
+ const value: number = -42.5;
56
+
57
+ if (NegativeFiniteNumber.is(value)) {
58
+ expectType<typeof value, typeof value & NegativeFiniteNumber>('=');
59
+ }
60
+ });
61
+ });
62
+
63
+ describe('NegativeFiniteNumber.abs', () => {
64
+ test('returns the absolute value as a positive finite number', () => {
65
+ expect(
66
+ NegativeFiniteNumber.abs(asNegativeFiniteNumber(-5.5)),
67
+ ).toBeCloseTo(5.5, 5);
68
+ });
69
+
70
+ test('result type is PositiveFiniteNumber', () => {
71
+ expectType<
72
+ ReturnType<typeof NegativeFiniteNumber.abs>,
73
+ PositiveFiniteNumber
74
+ >('=');
75
+ });
76
+ });
77
+
78
+ describe('NegativeFiniteNumber.min / max', () => {
79
+ test('returns the expected extremum', () => {
80
+ expect(
81
+ NegativeFiniteNumber.min(
82
+ asNegativeFiniteNumber(-5.5),
83
+ asNegativeFiniteNumber(-10.5),
84
+ ),
85
+ ).toBeCloseTo(-10.5, 5);
86
+
87
+ expect(
88
+ NegativeFiniteNumber.max(
89
+ asNegativeFiniteNumber(-5.5),
90
+ asNegativeFiniteNumber(-10.5),
91
+ ),
92
+ ).toBeCloseTo(-5.5, 5);
93
+ });
94
+ });
95
+
96
+ describe('NegativeFiniteNumber.clamp', () => {
97
+ test('clamps non-negative values into range', () => {
98
+ expect(NegativeFiniteNumber.clamp(-5.5)).toBeCloseTo(-5.5, 5);
99
+
100
+ expect(NegativeFiniteNumber.clamp(0)).toBeLessThan(0);
101
+
102
+ expect(NegativeFiniteNumber.clamp(5)).toBeLessThan(0);
103
+ });
104
+ });
105
+
106
+ describe('NegativeFiniteNumber.floor / ceil / round', () => {
107
+ test('rounds toward integers', () => {
108
+ expect(NegativeFiniteNumber.floor(asNegativeFiniteNumber(-2.3))).toBe(-3);
109
+
110
+ expect(NegativeFiniteNumber.ceil(asNegativeFiniteNumber(-2.3))).toBe(-2);
111
+
112
+ expect(
113
+ NegativeFiniteNumber.ceil(asNegativeFiniteNumber(-0.5)),
114
+ ).toBeCloseTo(0);
115
+
116
+ expect(
117
+ NegativeFiniteNumber.round(asNegativeFiniteNumber(-0.4)),
118
+ ).toBeCloseTo(0);
119
+ });
120
+
121
+ test('floor result type is NegativeInt', () => {
122
+ expectType<ReturnType<typeof NegativeFiniteNumber.floor>, NegativeInt>(
123
+ '=',
124
+ );
125
+ });
126
+
127
+ test('ceil/round result type is NonPositiveInt', () => {
128
+ expectType<ReturnType<typeof NegativeFiniteNumber.ceil>, NonPositiveInt>(
129
+ '=',
130
+ );
131
+
132
+ expectType<ReturnType<typeof NegativeFiniteNumber.round>, NonPositiveInt>(
133
+ '=',
134
+ );
135
+ });
136
+ });
137
+
138
+ describe('NegativeFiniteNumber.add / sub', () => {
139
+ test('adds and subtracts within range', () => {
140
+ expect(
141
+ NegativeFiniteNumber.add(
142
+ asNegativeFiniteNumber(-5.5),
143
+ asNegativeFiniteNumber(-3.5),
144
+ ),
145
+ ).toBeCloseTo(-9, 5);
146
+
147
+ expect(
148
+ NegativeFiniteNumber.sub(
149
+ asNegativeFiniteNumber(-10.5),
150
+ asNegativeFiniteNumber(-3.5),
151
+ ),
152
+ ).toBeCloseTo(-7, 5);
153
+
154
+ expect(
155
+ NegativeFiniteNumber.sub(
156
+ asNegativeFiniteNumber(-3.5),
157
+ asNegativeFiniteNumber(-10.5),
158
+ ),
159
+ ).toBeLessThan(0);
160
+ });
161
+ });
162
+
163
+ describe('NegativeFiniteNumber.random', () => {
164
+ test('generates values within range', () => {
165
+ for (const _ of range(100)) {
166
+ const value = NegativeFiniteNumber.random();
167
+
168
+ assert.isTrue(isNegativeFiniteNumber(value));
169
+ }
170
+ });
171
+ });
172
+ });