ts-data-forge 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +534 -0
  3. package/package.json +101 -0
  4. package/src/array/array-utils-creation.test.mts +443 -0
  5. package/src/array/array-utils-modification.test.mts +197 -0
  6. package/src/array/array-utils-overload-type-error.test.mts +149 -0
  7. package/src/array/array-utils-reducing-value.test.mts +425 -0
  8. package/src/array/array-utils-search.test.mts +169 -0
  9. package/src/array/array-utils-set-op.test.mts +335 -0
  10. package/src/array/array-utils-slice-clamped.test.mts +113 -0
  11. package/src/array/array-utils-slicing.test.mts +316 -0
  12. package/src/array/array-utils-transformation.test.mts +790 -0
  13. package/src/array/array-utils-validation.test.mts +492 -0
  14. package/src/array/array-utils.mts +4000 -0
  15. package/src/array/array.test.mts +146 -0
  16. package/src/array/index.mts +2 -0
  17. package/src/array/tuple-utils.mts +519 -0
  18. package/src/array/tuple-utils.test.mts +518 -0
  19. package/src/collections/imap-mapped.mts +801 -0
  20. package/src/collections/imap-mapped.test.mts +860 -0
  21. package/src/collections/imap.mts +651 -0
  22. package/src/collections/imap.test.mts +932 -0
  23. package/src/collections/index.mts +6 -0
  24. package/src/collections/iset-mapped.mts +889 -0
  25. package/src/collections/iset-mapped.test.mts +1187 -0
  26. package/src/collections/iset.mts +682 -0
  27. package/src/collections/iset.test.mts +1084 -0
  28. package/src/collections/queue.mts +390 -0
  29. package/src/collections/queue.test.mts +282 -0
  30. package/src/collections/stack.mts +423 -0
  31. package/src/collections/stack.test.mts +225 -0
  32. package/src/expect-type.mts +206 -0
  33. package/src/functional/index.mts +4 -0
  34. package/src/functional/match.mts +300 -0
  35. package/src/functional/match.test.mts +177 -0
  36. package/src/functional/optional.mts +733 -0
  37. package/src/functional/optional.test.mts +619 -0
  38. package/src/functional/pipe.mts +212 -0
  39. package/src/functional/pipe.test.mts +85 -0
  40. package/src/functional/result.mts +1134 -0
  41. package/src/functional/result.test.mts +777 -0
  42. package/src/globals.d.mts +38 -0
  43. package/src/guard/has-key.mts +119 -0
  44. package/src/guard/has-key.test.mts +219 -0
  45. package/src/guard/index.mts +7 -0
  46. package/src/guard/is-non-empty-string.mts +108 -0
  47. package/src/guard/is-non-empty-string.test.mts +91 -0
  48. package/src/guard/is-non-null-object.mts +106 -0
  49. package/src/guard/is-non-null-object.test.mts +90 -0
  50. package/src/guard/is-primitive.mts +165 -0
  51. package/src/guard/is-primitive.test.mts +102 -0
  52. package/src/guard/is-record.mts +153 -0
  53. package/src/guard/is-record.test.mts +112 -0
  54. package/src/guard/is-type.mts +450 -0
  55. package/src/guard/is-type.test.mts +496 -0
  56. package/src/guard/key-is-in.mts +163 -0
  57. package/src/guard/key-is-in.test.mts +19 -0
  58. package/src/index.mts +10 -0
  59. package/src/iterator/index.mts +1 -0
  60. package/src/iterator/range.mts +120 -0
  61. package/src/iterator/range.test.mts +33 -0
  62. package/src/json/index.mts +1 -0
  63. package/src/json/json.mts +711 -0
  64. package/src/json/json.test.mts +628 -0
  65. package/src/number/branded-types/finite-number.mts +354 -0
  66. package/src/number/branded-types/finite-number.test.mts +135 -0
  67. package/src/number/branded-types/index.mts +26 -0
  68. package/src/number/branded-types/int.mts +278 -0
  69. package/src/number/branded-types/int.test.mts +140 -0
  70. package/src/number/branded-types/int16.mts +192 -0
  71. package/src/number/branded-types/int16.test.mts +170 -0
  72. package/src/number/branded-types/int32.mts +193 -0
  73. package/src/number/branded-types/int32.test.mts +170 -0
  74. package/src/number/branded-types/non-negative-finite-number.mts +223 -0
  75. package/src/number/branded-types/non-negative-finite-number.test.mts +188 -0
  76. package/src/number/branded-types/non-negative-int16.mts +187 -0
  77. package/src/number/branded-types/non-negative-int16.test.mts +201 -0
  78. package/src/number/branded-types/non-negative-int32.mts +187 -0
  79. package/src/number/branded-types/non-negative-int32.test.mts +204 -0
  80. package/src/number/branded-types/non-zero-finite-number.mts +229 -0
  81. package/src/number/branded-types/non-zero-finite-number.test.mts +198 -0
  82. package/src/number/branded-types/non-zero-int.mts +167 -0
  83. package/src/number/branded-types/non-zero-int.test.mts +177 -0
  84. package/src/number/branded-types/non-zero-int16.mts +196 -0
  85. package/src/number/branded-types/non-zero-int16.test.mts +195 -0
  86. package/src/number/branded-types/non-zero-int32.mts +196 -0
  87. package/src/number/branded-types/non-zero-int32.test.mts +197 -0
  88. package/src/number/branded-types/non-zero-safe-int.mts +196 -0
  89. package/src/number/branded-types/non-zero-safe-int.test.mts +232 -0
  90. package/src/number/branded-types/non-zero-uint16.mts +189 -0
  91. package/src/number/branded-types/non-zero-uint16.test.mts +199 -0
  92. package/src/number/branded-types/non-zero-uint32.mts +189 -0
  93. package/src/number/branded-types/non-zero-uint32.test.mts +199 -0
  94. package/src/number/branded-types/positive-finite-number.mts +241 -0
  95. package/src/number/branded-types/positive-finite-number.test.mts +204 -0
  96. package/src/number/branded-types/positive-int.mts +304 -0
  97. package/src/number/branded-types/positive-int.test.mts +176 -0
  98. package/src/number/branded-types/positive-int16.mts +188 -0
  99. package/src/number/branded-types/positive-int16.test.mts +197 -0
  100. package/src/number/branded-types/positive-int32.mts +188 -0
  101. package/src/number/branded-types/positive-int32.test.mts +197 -0
  102. package/src/number/branded-types/positive-safe-int.mts +187 -0
  103. package/src/number/branded-types/positive-safe-int.test.mts +210 -0
  104. package/src/number/branded-types/positive-uint16.mts +188 -0
  105. package/src/number/branded-types/positive-uint16.test.mts +203 -0
  106. package/src/number/branded-types/positive-uint32.mts +188 -0
  107. package/src/number/branded-types/positive-uint32.test.mts +203 -0
  108. package/src/number/branded-types/safe-int.mts +291 -0
  109. package/src/number/branded-types/safe-int.test.mts +170 -0
  110. package/src/number/branded-types/safe-uint.mts +187 -0
  111. package/src/number/branded-types/safe-uint.test.mts +176 -0
  112. package/src/number/branded-types/uint.mts +179 -0
  113. package/src/number/branded-types/uint.test.mts +158 -0
  114. package/src/number/branded-types/uint16.mts +186 -0
  115. package/src/number/branded-types/uint16.test.mts +170 -0
  116. package/src/number/branded-types/uint32.mts +218 -0
  117. package/src/number/branded-types/uint32.test.mts +170 -0
  118. package/src/number/enum/index.mts +2 -0
  119. package/src/number/enum/int8.mts +344 -0
  120. package/src/number/enum/int8.test.mts +180 -0
  121. package/src/number/enum/uint8.mts +293 -0
  122. package/src/number/enum/uint8.test.mts +164 -0
  123. package/src/number/index.mts +4 -0
  124. package/src/number/num.mts +604 -0
  125. package/src/number/num.test.mts +242 -0
  126. package/src/number/refined-number-utils.mts +566 -0
  127. package/src/object/index.mts +1 -0
  128. package/src/object/object.mts +447 -0
  129. package/src/object/object.test.mts +124 -0
  130. package/src/others/cast-mutable.mts +113 -0
  131. package/src/others/cast-readonly.mts +192 -0
  132. package/src/others/cast-readonly.test.mts +89 -0
  133. package/src/others/if-then.mts +98 -0
  134. package/src/others/if-then.test.mts +75 -0
  135. package/src/others/index.mts +7 -0
  136. package/src/others/map-nullable.mts +172 -0
  137. package/src/others/map-nullable.test.mts +297 -0
  138. package/src/others/memoize-function.mts +196 -0
  139. package/src/others/memoize-function.test.mts +168 -0
  140. package/src/others/tuple.mts +160 -0
  141. package/src/others/tuple.test.mts +11 -0
  142. package/src/others/unknown-to-string.mts +215 -0
  143. package/src/others/unknown-to-string.test.mts +114 -0
@@ -0,0 +1,242 @@
1
+ import { expectType } from '../expect-type.mjs';
2
+ import { pipe } from '../functional/index.mjs';
3
+ import { Num } from './num.mjs';
4
+
5
+ const testClamp = (
6
+ [a, b]: readonly [number, number],
7
+ target: number,
8
+ expected: number,
9
+ ): void => {
10
+ test(`clamp ${target} to [${a}, ${b}]`, () => {
11
+ expect(Num.clamp(a, b)(target)).toBe(expected);
12
+ });
13
+ };
14
+
15
+ describe('Num', () => {
16
+ describe('clamp', () => {
17
+ testClamp([0, 2], 2.3, 2);
18
+ testClamp([0, 2], -0.5, 0);
19
+ testClamp([0, 2], 1.5, 1.5);
20
+ testClamp([0, 2], Number.NaN, 0);
21
+
22
+ test('should support regular usage with three parameters', () => {
23
+ expectTypeOf(Num.clamp(15, 0, 10)).toEqualTypeOf<number>();
24
+ expect(Num.clamp(15, 0, 10)).toBe(10);
25
+ expect(Num.clamp(-5, 0, 10)).toBe(0);
26
+ expect(Num.clamp(5, 0, 10)).toBe(5);
27
+ expect(Num.clamp(Number.NaN, 0, 10)).toBe(0);
28
+ });
29
+
30
+ test('should work with pipe when curried', () => {
31
+ const clampTo0_10 = Num.clamp(0, 10);
32
+
33
+ const result1 = pipe(15).map(clampTo0_10).value;
34
+ expect(result1).toBe(10);
35
+
36
+ const result2 = pipe(-5).map(clampTo0_10).value;
37
+ expect(result2).toBe(0);
38
+
39
+ const result3 = pipe(7.5).map(clampTo0_10).value;
40
+ expect(result3).toBe(7.5);
41
+ });
42
+
43
+ test('should handle edge cases in curried form', () => {
44
+ const clampTo5_15 = Num.clamp(5, 15);
45
+
46
+ expectType<typeof clampTo5_15, (target: number) => number>('=');
47
+
48
+ // Invalid (non-finite) values return the lower bound
49
+ expect(clampTo5_15(Number.POSITIVE_INFINITY)).toBe(5);
50
+ expect(clampTo5_15(Number.NEGATIVE_INFINITY)).toBe(5);
51
+ expect(clampTo5_15(Number.NaN)).toBe(5);
52
+ });
53
+
54
+ test('should work with negative ranges', () => {
55
+ expect(Num.clamp(-15, -10, -5)).toBe(-10);
56
+ expect(Num.clamp(-7, -10, -5)).toBe(-7);
57
+ expect(Num.clamp(0, -10, -5)).toBe(-5);
58
+
59
+ const clampNegative = Num.clamp(-10, -5);
60
+ expect(clampNegative(-15)).toBe(-10);
61
+ expect(clampNegative(-7)).toBe(-7);
62
+ expect(clampNegative(0)).toBe(-5);
63
+ });
64
+ });
65
+
66
+ describe('isUintInRangeInclusive', () => {
67
+ test('truthy case', () => {
68
+ const f = Num.isUintInRangeInclusive(0, 4);
69
+ const x: number = 2;
70
+ if (f(x)) {
71
+ expectType<typeof x, 0 | 1 | 2 | 3 | 4>('=');
72
+ } else {
73
+ expectType<typeof x, number>('=');
74
+ }
75
+ expect(f(x)).toBe(true);
76
+ });
77
+
78
+ test('falsy case', () => {
79
+ const f = Num.isUintInRangeInclusive(0, 4);
80
+ const x: number = 100;
81
+ if (f(x)) {
82
+ expectType<typeof x, 0 | 1 | 2 | 3 | 4>('=');
83
+ } else {
84
+ expectType<typeof x, number>('=');
85
+ }
86
+ expect(f(x)).toBe(false);
87
+ });
88
+ });
89
+
90
+ describe('from', () => {
91
+ test('converts string to number', () => {
92
+ expect(Num.from('123')).toBe(123);
93
+ expect(Num.from('123.45')).toBe(123.45);
94
+ expect(Num.from('-42')).toBe(-42);
95
+ });
96
+
97
+ test('handles edge cases', () => {
98
+ expect(Num.from('')).toBe(0);
99
+ expect(Num.from('abc')).toBeNaN();
100
+ expect(Num.from(true)).toBe(1);
101
+ expect(Num.from(false)).toBe(0);
102
+ });
103
+ });
104
+
105
+ describe('isInRange', () => {
106
+ test('checks range (lower inclusive, upper exclusive)', () => {
107
+ const inRange = Num.isInRange(0, 10);
108
+ expect(inRange(5)).toBe(true);
109
+ expect(inRange(0)).toBe(true); // inclusive lower bound
110
+ expect(inRange(10)).toBe(false); // exclusive upper bound
111
+ expect(inRange(-1)).toBe(false);
112
+ expect(inRange(15)).toBe(false);
113
+ });
114
+ });
115
+
116
+ describe('isInRangeInclusive', () => {
117
+ test('checks range (inclusive)', () => {
118
+ const inRange = Num.isInRangeInclusive(0, 10);
119
+ expect(inRange(5)).toBe(true);
120
+ expect(inRange(0)).toBe(true); // inclusive
121
+ expect(inRange(10)).toBe(true); // inclusive
122
+ expect(inRange(-1)).toBe(false);
123
+ expect(inRange(15)).toBe(false);
124
+ });
125
+ });
126
+
127
+ describe('isUintInRange', () => {
128
+ test('checks uint range (lower inclusive, upper exclusive)', () => {
129
+ const inRange = Num.isUintInRange(0, 5);
130
+ expect(inRange(2)).toBe(true);
131
+ expect(inRange(0)).toBe(true); // inclusive lower bound
132
+ expect(inRange(5)).toBe(false); // exclusive upper bound
133
+ expect(inRange(-1)).toBe(false);
134
+ });
135
+ });
136
+
137
+ describe('isNonZero', () => {
138
+ test('type guard for non-zero numbers', () => {
139
+ const x: number = 5;
140
+ if (Num.isNonZero(x)) {
141
+ expectType<typeof x, NonZeroNumber>('=');
142
+ }
143
+ expect(Num.isNonZero(5)).toBe(true);
144
+ expect(Num.isNonZero(-3)).toBe(true);
145
+ expect(Num.isNonZero(0)).toBe(false);
146
+ });
147
+ });
148
+
149
+ describe('isNonNegative', () => {
150
+ test('type guard for non-negative numbers', () => {
151
+ expect(Num.isNonNegative(5)).toBe(true);
152
+ expect(Num.isNonNegative(0)).toBe(true);
153
+ expect(Num.isNonNegative(-1)).toBe(false);
154
+ });
155
+ });
156
+
157
+ describe('isPositive', () => {
158
+ test('type guard for positive numbers', () => {
159
+ expect(Num.isPositive(5)).toBe(true);
160
+ expect(Num.isPositive(0.1)).toBe(true);
161
+ expect(Num.isPositive(0)).toBe(false);
162
+ expect(Num.isPositive(-1)).toBe(false);
163
+ });
164
+ });
165
+
166
+ describe('div', () => {
167
+ test('basic division', () => {
168
+ expect(Num.div(10, 2)).toBe(5);
169
+ expect(Num.div(7, 3)).toBe(7 / 3);
170
+ expect(Num.div(-10, 2)).toBe(-5);
171
+ });
172
+ });
173
+
174
+ describe('divInt', () => {
175
+ test('integer division (floor)', () => {
176
+ expect(Num.divInt(10, 3)).toBe(3);
177
+ expect(Num.divInt(7, 2)).toBe(3);
178
+ expect(Num.divInt(-7, 2)).toBe(-4); // floor division
179
+ expect(Num.divInt(10.7, 3.2)).toBe(3); // floors both operands
180
+ });
181
+ });
182
+
183
+ describe('roundAt', () => {
184
+ test('rounds to specified decimal places', () => {
185
+ expect(Num.roundAt(3.14159, 2)).toBe(3.14);
186
+ expect(Num.roundAt(3.14159, 3)).toBe(3.142);
187
+ expect(Num.roundAt(2.555, 2)).toBe(2.56);
188
+ expect(Num.roundAt(123.456, 1)).toBe(123.5);
189
+ });
190
+ });
191
+
192
+ describe('roundToInt', () => {
193
+ test('rounds to nearest integer', () => {
194
+ expect(Num.roundToInt(3.4)).toBe(3);
195
+ expect(Num.roundToInt(3.6)).toBe(4);
196
+ expect(Num.roundToInt(2.5)).toBe(3);
197
+ expect(Num.roundToInt(-2.3)).toBe(-1); // bitwise behavior: -2.3 + 0.5 = -1.8, then floor with bitwise OR
198
+ expect(Num.roundToInt(-2.7)).toBe(-2); // bitwise behavior: -2.7 + 0.5 = -2.2, then floor with bitwise OR
199
+ });
200
+ });
201
+
202
+ describe('round', () => {
203
+ test('creates rounding function with specified precision', () => {
204
+ const round2 = Num.round(2);
205
+ expect(round2(3.14159)).toBe(3.14);
206
+ expect(round2(2.556)).toBe(2.56);
207
+
208
+ const round1 = Num.round(1);
209
+ expect(round1(3.14159)).toBe(3.1);
210
+ expect(round1(2.56)).toBe(2.6);
211
+
212
+ const round3 = Num.round(3);
213
+ expect(round3(3.1416)).toBe(3.142);
214
+ expect(round3(2.7182)).toBe(2.718);
215
+ });
216
+ });
217
+
218
+ describe('mapNaN2Undefined', () => {
219
+ test('maps NaN to undefined', () => {
220
+ expect(Num.mapNaN2Undefined(5)).toBe(5);
221
+ expect(Num.mapNaN2Undefined(0)).toBe(0);
222
+ expect(Num.mapNaN2Undefined(-3.14)).toBe(-3.14);
223
+ expect(Num.mapNaN2Undefined(Number.NaN)).toBeUndefined();
224
+ });
225
+ });
226
+
227
+ describe('increment', () => {
228
+ test('increments SmallUint values', () => {
229
+ expect(Num.increment(0)).toBe(1);
230
+ expect(Num.increment(5)).toBe(6);
231
+ expect(Num.increment(38)).toBe(39);
232
+ });
233
+ });
234
+
235
+ describe('decrement', () => {
236
+ test('decrements PositiveSmallInt values', () => {
237
+ expect(Num.decrement(1)).toBe(0);
238
+ expect(Num.decrement(5)).toBe(4);
239
+ expect(Num.decrement(39)).toBe(38);
240
+ });
241
+ });
242
+ });