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,443 @@
1
+ import { expectType } from '../expect-type.mjs';
2
+ import { asNonZeroSafeInt, asUint32 } from '../number/index.mjs';
3
+ import { Arr } from './array-utils.mjs';
4
+
5
+ describe('Arr creations', () => {
6
+ describe('zeros', () => {
7
+ test('fixed length', () => {
8
+ const result = Arr.zeros(3);
9
+ expectType<typeof result, readonly [0, 0, 0]>('=');
10
+ expect(result).toStrictEqual([0, 0, 0]);
11
+ });
12
+
13
+ test('fixed length (empty)', () => {
14
+ const result = Arr.zeros(0);
15
+ expectType<typeof result, readonly []>('=');
16
+ expect(result).toStrictEqual([]);
17
+ });
18
+
19
+ test('unknown length', () => {
20
+ const n: number = 3;
21
+ const result = Arr.zeros(asUint32(n));
22
+ expectType<typeof result, readonly 0[]>('=');
23
+ expect(result).toStrictEqual([0, 0, 0]);
24
+ });
25
+
26
+ test('should create array with zero length', () => {
27
+ const result = Arr.zeros(0);
28
+ expect(result).toStrictEqual([]);
29
+ expect(result.length).toBe(0);
30
+ });
31
+
32
+ test('should create large arrays', () => {
33
+ const result = Arr.zeros(asUint32(1000));
34
+ expect(result).toHaveLength(1000);
35
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
36
+ expect(result.every((x) => x === 0)).toBe(true);
37
+ });
38
+
39
+ test('should work with curried version', () => {
40
+ const createTenZeros = Arr.zeros(10);
41
+ expect(createTenZeros).toStrictEqual([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
42
+ });
43
+ });
44
+
45
+ describe('seq', () => {
46
+ test('fixed length', () => {
47
+ const result = Arr.seq(5);
48
+ expectType<typeof result, readonly [0, 1, 2, 3, 4]>('=');
49
+ expect(result).toStrictEqual([0, 1, 2, 3, 4]);
50
+ });
51
+
52
+ test('fixed length (empty)', () => {
53
+ const result = Arr.seq(0);
54
+ expectType<typeof result, readonly []>('=');
55
+ expect(result).toStrictEqual([]);
56
+ });
57
+
58
+ test('unknown length', () => {
59
+ const n: number = 3;
60
+ const result = Arr.seq(asUint32(n));
61
+ expectType<typeof result, readonly SizeType.Arr[]>('=');
62
+ expect(result).toStrictEqual([0, 1, 2]);
63
+ });
64
+
65
+ test('should create sequence with zero length', () => {
66
+ const result = Arr.seq(0);
67
+ expect(result).toStrictEqual([]);
68
+ });
69
+
70
+ test('should create sequence with large length', () => {
71
+ const result = Arr.seq(asUint32(100));
72
+ expect(result).toHaveLength(100);
73
+ expect(result[0]).toBe(0);
74
+ expect(result[99]).toBe(99);
75
+ });
76
+
77
+ test('should work with curried version', () => {
78
+ const createFiveSeq = Arr.seq(5);
79
+ expect(createFiveSeq).toStrictEqual([0, 1, 2, 3, 4]);
80
+ });
81
+ });
82
+
83
+ describe('create', () => {
84
+ test('fixed length with primitive value', () => {
85
+ const result = Arr.create(3, 'a');
86
+ expectType<typeof result, readonly ['a', 'a', 'a']>('=');
87
+ expect(result).toStrictEqual(['a', 'a', 'a']);
88
+ });
89
+
90
+ test('fixed length with null', () => {
91
+ const result = Arr.create(2, null);
92
+ expectType<typeof result, readonly [null, null]>('=');
93
+ expect(result).toStrictEqual([null, null]);
94
+ });
95
+
96
+ test('fixed length with object (shallow copy)', () => {
97
+ const obj = { id: 1 };
98
+ const result = Arr.create(2, obj);
99
+ expectType<typeof result, readonly [{ id: number }, { id: number }]>(
100
+ '~=',
101
+ );
102
+ expect(result).toStrictEqual([obj, obj]);
103
+ expect(result[0]).toBe(obj);
104
+ expect(result[1]).toBe(obj);
105
+ });
106
+
107
+ test('fixed length (empty)', () => {
108
+ const result = Arr.create(0, 123);
109
+ expectType<typeof result, readonly []>('=');
110
+ expect(result).toStrictEqual([]);
111
+ });
112
+
113
+ test('unknown length', () => {
114
+ const n: number = 2;
115
+ const result = Arr.create(asUint32(n), true);
116
+ expectType<typeof result, readonly true[]>('=');
117
+ expect(result).toStrictEqual([true, true]);
118
+ });
119
+
120
+ test('should create array with function values', () => {
121
+ const fn = (): string => 'test';
122
+ const result = Arr.create(3, fn);
123
+ expect(result).toStrictEqual([fn, fn, fn]);
124
+ expect(result[0]).toBe(fn);
125
+ });
126
+
127
+ test('should create array with object values', () => {
128
+ const obj = { a: 1 };
129
+ const result = Arr.create(2, obj);
130
+ expect(result).toStrictEqual([obj, obj]);
131
+ expect(result[0]).toBe(obj); // Same reference
132
+ });
133
+
134
+ test('should create empty array when length is 0', () => {
135
+ const result = Arr.create(0, 'value');
136
+ expect(result).toStrictEqual([]);
137
+ });
138
+
139
+ test('newArray is alias for create', () => {
140
+ const created1 = Arr.create(3, 'test');
141
+ const created2 = Arr.newArray(3, 'test');
142
+ expect(created1).toStrictEqual(created2);
143
+ expect(created1).toStrictEqual(['test', 'test', 'test']);
144
+ });
145
+ });
146
+
147
+ describe('copy', () => {
148
+ test('should create a shallow copy of an array of primitives', () => {
149
+ const original = [1, 2, 3] as const;
150
+ const copied = Arr.copy(original);
151
+ expectType<typeof copied, readonly [1, 2, 3]>('=');
152
+ expect(copied).toStrictEqual(original);
153
+ expect(copied).not.toBe(original);
154
+ });
155
+
156
+ test('should create a shallow copy of an array of objects', () => {
157
+ const obj1 = { id: 1 };
158
+ const obj2 = { id: 2 };
159
+ const original = [obj1, obj2] as const;
160
+ const copied = Arr.copy(original);
161
+
162
+ expectType<typeof copied, readonly [{ id: number }, { id: number }]>('=');
163
+ expect(copied).toStrictEqual(original);
164
+ expect(copied).not.toBe(original);
165
+ expect(copied[0]).toBe(original[0]); // Object references are the same
166
+ expect(copied[1]).toBe(original[1]);
167
+ });
168
+
169
+ test('should create a copy of an empty array', () => {
170
+ const original = [] as const;
171
+ const copied = Arr.copy(original);
172
+ expectType<typeof copied, readonly []>('=');
173
+ expect(copied).toStrictEqual(original);
174
+ expect(copied).not.toBe(original);
175
+ });
176
+
177
+ test('should create a copy of an array with mixed types', () => {
178
+ const original = [1, 'hello', true, null, undefined] as const;
179
+ const copied = Arr.copy(original);
180
+ expectType<typeof copied, readonly [1, 'hello', true, null, undefined]>(
181
+ '=',
182
+ );
183
+ expect(copied).toStrictEqual(original);
184
+ expect(copied).not.toBe(original);
185
+ });
186
+
187
+ test('should handle unknown array type', () => {
188
+ const original: number[] = [1, 2, 3];
189
+ const copied = Arr.copy(original);
190
+ expectType<typeof copied, number[]>('=');
191
+ expect(copied).toStrictEqual(original);
192
+ expect(copied).not.toBe(original);
193
+ // Modify original to ensure copy is shallow
194
+ original.push(4);
195
+ expect(original).toStrictEqual([1, 2, 3, 4]);
196
+ expect(copied).toStrictEqual([1, 2, 3]);
197
+ });
198
+
199
+ test('should create shallow copy of array', () => {
200
+ const original = [1, 2, 3] as const;
201
+ const copied = Arr.copy(original);
202
+ expectType<typeof copied, readonly [1, 2, 3]>('=');
203
+ expect(copied).toStrictEqual(original);
204
+ expect(copied).not.toBe(original);
205
+ });
206
+
207
+ test('should work with empty array', () => {
208
+ const empty = [] as const;
209
+ const copied = Arr.copy(empty);
210
+ expect(copied).toStrictEqual([]);
211
+ expect(copied).not.toBe(empty);
212
+ });
213
+
214
+ test('should preserve array type', () => {
215
+ const mixed = [1, 'hello', true] as const;
216
+ const copied = Arr.copy(mixed);
217
+ expectType<typeof copied, readonly [1, 'hello', true]>('=');
218
+ expect(copied).toStrictEqual([1, 'hello', true]);
219
+ });
220
+ });
221
+
222
+ describe('range', () => {
223
+ test('start < end, step = 1 (default)', () => {
224
+ const result = Arr.range(1, 5);
225
+ expectType<typeof result, readonly [1, 2, 3, 4]>('=');
226
+ expect(result).toStrictEqual([1, 2, 3, 4]);
227
+ });
228
+
229
+ test('start === end, step = 1 (default)', () => {
230
+ const result = Arr.range(3, 3);
231
+ expectType<typeof result, readonly []>('=');
232
+ expect(result).toStrictEqual([]);
233
+ });
234
+
235
+ test('start > end, step = 1 (default)', () => {
236
+ const result = Arr.range(5, 1);
237
+ expectType<typeof result, readonly []>('=');
238
+ expect(result).toStrictEqual([]);
239
+ });
240
+
241
+ test('start < end, step > 1', () => {
242
+ const result = Arr.range(0, 6, 2);
243
+ expectType<typeof result, readonly SafeUint[]>('='); // Type is less specific with explicit step
244
+ expect(result).toStrictEqual([0, 2, 4]);
245
+ });
246
+
247
+ test('start < end, step > 1, not reaching end', () => {
248
+ const result = Arr.range(0, 5, 2);
249
+ expect(result).toStrictEqual([0, 2, 4]);
250
+ });
251
+
252
+ test('start > end, step < 0', () => {
253
+ const result = Arr.range(5, 0, -1);
254
+ expect(result).toStrictEqual([5, 4, 3, 2, 1]);
255
+ });
256
+
257
+ test('start > end, step < 0, not reaching end', () => {
258
+ const result = Arr.range(5, 1, -2);
259
+ expect(result).toStrictEqual([5, 3]);
260
+ });
261
+
262
+ test('start < end, step < 0 (empty result)', () => {
263
+ const result = Arr.range(1, 5, -1);
264
+ expect(result).toStrictEqual([]);
265
+ });
266
+
267
+ test('start > end, step > 0 (empty result)', () => {
268
+ const result = Arr.range(5, 1, 1);
269
+ expect(result).toStrictEqual([]);
270
+ });
271
+
272
+ test('unknown start/end/step', () => {
273
+ const start: number = 1;
274
+ const end: number = 4;
275
+ const step: number = 1;
276
+ const result = Arr.range(
277
+ asUint32(start),
278
+ asUint32(end),
279
+ asNonZeroSafeInt(step),
280
+ );
281
+ expectType<typeof result, readonly SafeInt[]>('=');
282
+ expect(result).toStrictEqual([1, 2, 3]);
283
+ });
284
+
285
+ test('range(1, 3)', () => {
286
+ const result = Arr.range(1, 3);
287
+
288
+ expectType<typeof result, readonly [1, 2]>('=');
289
+
290
+ expect(result).toStrictEqual([1, 2]);
291
+ });
292
+
293
+ test('range(1, 3, 1)', () => {
294
+ const result = Arr.range(1, 3, 1);
295
+
296
+ expectType<typeof result, readonly [1, 2]>('=');
297
+
298
+ expect(result).toStrictEqual([1, 2]);
299
+ });
300
+
301
+ test('range(0, 0)', () => {
302
+ const result = Arr.range(0, 0);
303
+
304
+ expectType<typeof result, readonly []>('=');
305
+
306
+ expect(result).toStrictEqual([]);
307
+ });
308
+
309
+ test('range(0, 1)', () => {
310
+ const result = Arr.range(0, 1);
311
+
312
+ expectType<typeof result, readonly [0]>('=');
313
+
314
+ expect(result).toStrictEqual([0]);
315
+ });
316
+
317
+ test('range(0, -1)', () => {
318
+ const result = Arr.range(0, -1);
319
+
320
+ expectType<typeof result, readonly SafeInt[]>('=');
321
+
322
+ expect(result).toStrictEqual([]);
323
+ });
324
+
325
+ test('range(SmallUint, SmallUint)', () => {
326
+ const result = Arr.range<SmallUint, SmallUint>(0, 1);
327
+
328
+ expectType<
329
+ typeof result,
330
+ readonly (
331
+ | 0
332
+ | 1
333
+ | 2
334
+ | 3
335
+ | 4
336
+ | 5
337
+ | 6
338
+ | 7
339
+ | 8
340
+ | 9
341
+ | 10
342
+ | 11
343
+ | 12
344
+ | 13
345
+ | 14
346
+ | 15
347
+ | 16
348
+ | 17
349
+ | 18
350
+ | 19
351
+ | 20
352
+ | 21
353
+ | 22
354
+ | 23
355
+ | 24
356
+ | 25
357
+ | 26
358
+ | 27
359
+ | 28
360
+ | 29
361
+ | 30
362
+ | 31
363
+ | 32
364
+ | 33
365
+ | 34
366
+ | 35
367
+ | 36
368
+ | 37
369
+ | 38
370
+ )[]
371
+ >('=');
372
+
373
+ expect(result).toStrictEqual([0]);
374
+ });
375
+
376
+ test('range(0 | 1 | 2, 1 | 2 | 3)', () => {
377
+ const result = Arr.range<0 | 1 | 2, 1 | 2 | 3>(0, 1);
378
+
379
+ expectType<typeof result, readonly (0 | 1 | 2)[]>('=');
380
+
381
+ expect(result).toStrictEqual([0]);
382
+ });
383
+
384
+ test('range(2|3, 5|6|7)', () => {
385
+ const result = Arr.range<2 | 3, 5 | 6 | 7>(2, 5);
386
+
387
+ expectType<typeof result, readonly (2 | 3 | 4 | 5 | 6)[]>('=');
388
+
389
+ expect(result).toStrictEqual([2, 3, 4]);
390
+ });
391
+
392
+ test('range(0, 10, 2)', () => {
393
+ const result = Arr.range(0, 10, 2);
394
+
395
+ expectType<typeof result, readonly SafeUint[]>('=');
396
+
397
+ expect(result).toStrictEqual([0, 2, 4, 6, 8]);
398
+ });
399
+
400
+ test('range(0, 11, 2)', () => {
401
+ const result = Arr.range(0, 11, 2);
402
+
403
+ expectType<typeof result, readonly SafeUint[]>('=');
404
+
405
+ expect(result).toStrictEqual([0, 2, 4, 6, 8, 10]);
406
+ });
407
+
408
+ test('range(1, 12, 2)', () => {
409
+ const result = Arr.range(1, 12, 2);
410
+
411
+ expectType<typeof result, readonly SafeUint[]>('=');
412
+
413
+ expect(result).toStrictEqual([1, 3, 5, 7, 9, 11]);
414
+ });
415
+
416
+ // Note: These tests were removed as the range function doesn't return Result type
417
+ // and doesn't validate inputs in this way
418
+
419
+ test('should handle range with step larger than difference', () => {
420
+ const result = Arr.range(0, 5, 10);
421
+ expect(result).toStrictEqual([0]);
422
+ });
423
+
424
+ test('should handle negative step with increasing range', () => {
425
+ const result = Arr.range(0, 5, -1);
426
+ expect(result).toStrictEqual([]); // Should be empty when step direction conflicts
427
+ });
428
+
429
+ test('should work with basic range functionality', () => {
430
+ // Test basic range functionality without currying assumptions
431
+ const result = Arr.range(0, 5, 1);
432
+ expect(result).toStrictEqual([0, 1, 2, 3, 4]);
433
+ });
434
+ });
435
+
436
+ describe('size/length', () => {
437
+ test('length should be alias for size', () => {
438
+ const array = [1, 2, 3];
439
+ expect(Arr.length(array)).toBe(Arr.size(array));
440
+ expect(Arr.length(array)).toBe(3);
441
+ });
442
+ });
443
+ });
@@ -0,0 +1,197 @@
1
+ import { expectType } from '../expect-type.mjs';
2
+ import { asUint32 } from '../number/index.mjs';
3
+ import { Arr } from './array-utils.mjs';
4
+
5
+ describe('Arr modifications', () => {
6
+ describe('toUpdated', () => {
7
+ const xs = [1, 2, 3] as const;
8
+ const result = Arr.toUpdated(xs, 1, (x) => x + 2);
9
+
10
+ expectType<typeof result, readonly number[]>('=');
11
+
12
+ test('case 1', () => {
13
+ expect(result).toStrictEqual([1, 4, 3]);
14
+ });
15
+ });
16
+
17
+ describe('toInserted', () => {
18
+ const xs = [1, 2, 3] as const;
19
+
20
+ {
21
+ const result = Arr.toInserted(xs, 1, 5);
22
+
23
+ expectType<typeof result, NonEmptyArray<1 | 2 | 3 | 5>>('=');
24
+
25
+ test('case 1', () => {
26
+ expect(result).toStrictEqual([1, 5, 2, 3]);
27
+ });
28
+ }
29
+ {
30
+ const result = Arr.toInserted(xs, 0, 5);
31
+
32
+ expectType<typeof result, NonEmptyArray<1 | 2 | 3 | 5>>('=');
33
+
34
+ test('case 2 (insert head)', () => {
35
+ expect(result).toStrictEqual([5, 1, 2, 3]);
36
+ });
37
+ }
38
+ {
39
+ const result = Arr.toInserted(xs, 3, 5);
40
+
41
+ expectType<typeof result, NonEmptyArray<1 | 2 | 3 | 5>>('=');
42
+
43
+ test('case 3 (insert tail)', () => {
44
+ expect(result).toStrictEqual([1, 2, 3, 5]);
45
+ });
46
+ }
47
+ {
48
+ const result = Arr.toInserted(xs, asUint32(999), 5);
49
+
50
+ expectType<typeof result, NonEmptyArray<1 | 2 | 3 | 5>>('=');
51
+
52
+ test('case 4 (insert tail)', () => {
53
+ expect(result).toStrictEqual([1, 2, 3, 5]);
54
+ });
55
+ }
56
+ });
57
+
58
+ describe('toRemoved', () => {
59
+ const xs = [1, 2, 3] as const;
60
+
61
+ {
62
+ const result = Arr.toRemoved(xs, 1);
63
+
64
+ expectType<typeof result, readonly (1 | 2 | 3)[]>('=');
65
+
66
+ test('case 1', () => {
67
+ expect(result).toStrictEqual([1, 3]);
68
+ });
69
+ }
70
+ {
71
+ const result = Arr.toRemoved(xs, 0);
72
+
73
+ expectType<typeof result, readonly (1 | 2 | 3)[]>('=');
74
+
75
+ test('case 2 (remove head)', () => {
76
+ expect(result).toStrictEqual([2, 3]);
77
+ });
78
+ }
79
+ {
80
+ const result = Arr.toRemoved(xs, 2);
81
+
82
+ expectType<typeof result, readonly (1 | 2 | 3)[]>('=');
83
+
84
+ test('case 3 (remove tail)', () => {
85
+ expect(result).toStrictEqual([1, 2]);
86
+ });
87
+ }
88
+ {
89
+ const result = Arr.toRemoved(xs, 3);
90
+
91
+ expectType<typeof result, readonly (1 | 2 | 3)[]>('=');
92
+
93
+ test('case 3 (noop)', () => {
94
+ expect(result).toStrictEqual([1, 2, 3]);
95
+ });
96
+ }
97
+ {
98
+ const result = Arr.toRemoved(xs, 5);
99
+
100
+ expectType<typeof result, readonly (1 | 2 | 3)[]>('=');
101
+
102
+ test('case 4 (noop)', () => {
103
+ expect(result).toStrictEqual([1, 2, 3]);
104
+ });
105
+ }
106
+ });
107
+
108
+ describe('toPushed', () => {
109
+ const xs = [1, 2, 3] as const;
110
+ const result = Arr.toPushed(xs, 4 as const);
111
+
112
+ expectType<typeof result, readonly [1, 2, 3, 4]>('=');
113
+
114
+ test('case 1', () => {
115
+ expect(result).toStrictEqual([1, 2, 3, 4]);
116
+ });
117
+ });
118
+
119
+ describe('toUnshifted', () => {
120
+ const xs = [1, 2, 3] as const;
121
+ const result = Arr.toUnshifted(xs, 4 as const);
122
+
123
+ expectType<typeof result, readonly [4, 1, 2, 3]>('=');
124
+
125
+ test('case 1', () => {
126
+ expect(result).toStrictEqual([4, 1, 2, 3]);
127
+ });
128
+ });
129
+
130
+ describe('toFilled', () => {
131
+ test('should fill entire array with value', () => {
132
+ const arr = [1, 2, 3, 4, 5];
133
+ const result = Arr.toFilled(arr, 0);
134
+
135
+ expect(result).toStrictEqual([0, 0, 0, 0, 0]);
136
+ });
137
+
138
+ test('should work with curried version', () => {
139
+ const fillWithZero = Arr.toFilled(0);
140
+ const arr = [1, 2, 3];
141
+ const result = fillWithZero(arr);
142
+
143
+ expect(result).toStrictEqual([0, 0, 0]);
144
+ });
145
+ });
146
+
147
+ describe('toRangeFilled', () => {
148
+ test('should fill array with range', () => {
149
+ const arr = [1, 2, 3, 4, 5];
150
+ const result = Arr.toRangeFilled(arr, 0, [1, 4]);
151
+
152
+ expect(result).toStrictEqual([1, 0, 0, 0, 5]);
153
+ });
154
+
155
+ test('should fill with range starting from 0', () => {
156
+ const arr = [1, 2, 3, 4, 5];
157
+ const result = Arr.toRangeFilled(arr, 9, [0, 3]);
158
+
159
+ expect(result).toStrictEqual([9, 9, 9, 4, 5]);
160
+ });
161
+
162
+ test('should handle empty range', () => {
163
+ const arr = [1, 2, 3];
164
+ const result = Arr.toRangeFilled(arr, 0, [2, 2]);
165
+
166
+ expect(result).toStrictEqual([1, 2, 3]);
167
+ });
168
+
169
+ test('should clamp range to array bounds', () => {
170
+ const arr = [1, 2, 3];
171
+ const result = Arr.toRangeFilled(arr, 0, [1, 10]);
172
+
173
+ expect(result).toStrictEqual([1, 0, 0]);
174
+ });
175
+
176
+ test('should handle negative start (clamped to 0)', () => {
177
+ const arr = [1, 2, 3];
178
+ const result = Arr.toRangeFilled(arr, 9, [-5, 2]);
179
+
180
+ expect(result).toStrictEqual([9, 9, 3]);
181
+ });
182
+
183
+ test('A non-integer starting value should result in a type error', () => {
184
+ const arr = [1, 2, 3];
185
+
186
+ // @ts-expect-error start must be an integer
187
+ expect(Arr.toRangeFilled(arr, 0, [1.5, 3])).toStrictEqual([1, 0, 0]);
188
+ });
189
+
190
+ test('A non-integer ending value should result in a type error', () => {
191
+ const arr = [1, 2, 3];
192
+
193
+ // @ts-expect-error end must be an integer
194
+ expect(Arr.toRangeFilled(arr, 0, [1, 2.5])).toStrictEqual([1, 0, 3]);
195
+ });
196
+ });
197
+ });