ts-data-forge 1.5.2 → 2.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.
- package/README.md +56 -44
- package/dist/array/array-utils.d.mts +661 -166
- package/dist/array/array-utils.d.mts.map +1 -1
- package/dist/array/array-utils.mjs +719 -79
- package/dist/array/array-utils.mjs.map +1 -1
- package/dist/array/index.d.mts +0 -1
- package/dist/array/index.d.mts.map +1 -1
- package/dist/array/index.mjs +0 -1
- package/dist/array/index.mjs.map +1 -1
- package/dist/collections/queue.mjs +0 -1
- package/dist/collections/queue.mjs.map +1 -1
- package/dist/collections/stack.mjs +4 -5
- package/dist/collections/stack.mjs.map +1 -1
- package/dist/functional/pipe.d.mts +56 -61
- package/dist/functional/pipe.d.mts.map +1 -1
- package/dist/functional/pipe.mjs.map +1 -1
- package/dist/globals.d.mts +10 -9
- package/dist/index.mjs +0 -1
- package/dist/index.mjs.map +1 -1
- package/dist/json/json.mjs +0 -1
- package/dist/json/json.mjs.map +1 -1
- package/dist/number/num.d.mts +1 -1
- package/package.json +2 -2
- package/src/array/array-utils-modification.test.mts +93 -67
- package/src/array/array-utils-overload-type-error.test.mts +2 -2
- package/src/array/array-utils-reducing-value.test.mts +31 -37
- package/src/array/array-utils-slice-clamped.test.mts +94 -70
- package/src/array/array-utils-transformation.test.mts +557 -10
- package/src/array/array-utils.mts +1457 -516
- package/src/array/index.mts +0 -1
- package/src/collections/queue.mts +2 -2
- package/src/collections/stack.mts +8 -8
- package/src/functional/pipe.mts +65 -75
- package/src/globals.d.mts +10 -9
- package/src/number/num.mts +1 -1
- package/dist/array/tuple-utils.d.mts +0 -407
- package/dist/array/tuple-utils.d.mts.map +0 -1
- package/dist/array/tuple-utils.mjs +0 -345
- package/dist/array/tuple-utils.mjs.map +0 -1
- package/src/array/tuple-utils.mts +0 -498
- package/src/array/tuple-utils.test.mts +0 -518
package/README.md
CHANGED
|
@@ -7,6 +7,17 @@
|
|
|
7
7
|
|
|
8
8
|
**ts-data-forge** is a TypeScript utility library that provides type-safe functional programming utilities with zero runtime dependencies. It aims to enhance development robustness, maintainability, and correctness by leveraging TypeScript's powerful type system.
|
|
9
9
|
|
|
10
|
+
## Perfect Companion to ts-type-forge
|
|
11
|
+
|
|
12
|
+
**ts-data-forge** is designed as the ideal runtime companion to [**ts-type-forge**](https://github.com/noshiro-pf/ts-type-forge), a powerful type utility library. While ts-type-forge provides compile-time type utilities for advanced TypeScript type manipulation, ts-data-forge complements it with runtime utilities that maintain the same level of type safety.
|
|
13
|
+
|
|
14
|
+
Together, they form a complete TypeScript development toolkit:
|
|
15
|
+
|
|
16
|
+
- **ts-type-forge**: Compile-time type utilities (type manipulation, type inference, advanced type patterns)
|
|
17
|
+
- **ts-data-forge**: Runtime utilities with strong type safety (type guards, branded types, functional programming utilities)
|
|
18
|
+
|
|
19
|
+
This synergy enables you to build fully type-safe applications from compile-time to runtime, ensuring type correctness throughout your entire codebase.
|
|
20
|
+
|
|
10
21
|
## Features
|
|
11
22
|
|
|
12
23
|
This library offers a range of utilities, including:
|
|
@@ -155,7 +166,7 @@ const maybeValue = Optional.some(42);
|
|
|
155
166
|
|
|
156
167
|
const doubled = Optional.map(maybeValue, (x) => x * 2);
|
|
157
168
|
|
|
158
|
-
assert
|
|
169
|
+
assert(Optional.unwrapOr(doubled, 0) === 84);
|
|
159
170
|
|
|
160
171
|
// Result for error handling
|
|
161
172
|
const success = Result.ok(42);
|
|
@@ -185,16 +196,16 @@ const handleStatus = (status: Status, data?: string): string =>
|
|
|
185
196
|
error: 'An error occurred',
|
|
186
197
|
});
|
|
187
198
|
|
|
188
|
-
assert
|
|
189
|
-
assert
|
|
190
|
-
assert
|
|
199
|
+
assert(handleStatus('loading') === 'Please wait...');
|
|
200
|
+
assert(handleStatus('success', 'Hello') === 'Data: Hello');
|
|
201
|
+
assert(handleStatus('error') === 'An error occurred');
|
|
191
202
|
|
|
192
203
|
// Pattern matching with Result
|
|
193
204
|
const processResult = (result: Result<number, string>): string =>
|
|
194
205
|
Result.isOk(result) ? `Success: ${result.value}` : `Error: ${result.value}`;
|
|
195
206
|
|
|
196
|
-
assert
|
|
197
|
-
assert
|
|
207
|
+
assert(processResult(Result.ok(42)) === 'Success: 42');
|
|
208
|
+
assert(processResult(Result.err('Failed')) === 'Error: Failed');
|
|
198
209
|
```
|
|
199
210
|
|
|
200
211
|
### 3. Number Utilities with `Num` and Branded Number Types
|
|
@@ -205,35 +216,35 @@ The `Num` object provides safe and convenient functions for numerical operations
|
|
|
205
216
|
import { Num } from 'ts-data-forge';
|
|
206
217
|
|
|
207
218
|
// Basic conversions
|
|
208
|
-
assert
|
|
209
|
-
assert
|
|
219
|
+
assert(Num.from('123') === 123);
|
|
220
|
+
assert(Number.isNaN(Num.from('abc')));
|
|
210
221
|
|
|
211
222
|
// Range checking
|
|
212
223
|
const inRange = Num.isInRange(0, 10);
|
|
213
224
|
|
|
214
|
-
assert
|
|
215
|
-
assert
|
|
216
|
-
assert
|
|
225
|
+
assert(inRange(5));
|
|
226
|
+
assert(inRange(0)); // (inclusive lower bound)
|
|
227
|
+
assert(!inRange(10)); // (exclusive upper bound)
|
|
217
228
|
|
|
218
229
|
// Clamping values
|
|
219
230
|
const clamp = Num.clamp(0, 100);
|
|
220
231
|
|
|
221
|
-
assert
|
|
222
|
-
assert
|
|
232
|
+
assert(clamp(150) === 100);
|
|
233
|
+
assert(clamp(-10) === 0);
|
|
223
234
|
|
|
224
235
|
// Rounding utilities
|
|
225
236
|
const round2 = Num.round(2);
|
|
226
237
|
|
|
227
|
-
assert
|
|
228
|
-
assert
|
|
229
|
-
assert
|
|
238
|
+
assert(round2(3.14159) === 3.14);
|
|
239
|
+
assert(Num.roundAt(3.14159, 3) === 3.142);
|
|
240
|
+
assert(Num.roundToInt(3.7) === 4);
|
|
230
241
|
|
|
231
242
|
// Type guards
|
|
232
243
|
const value = 5; // example value
|
|
233
244
|
if (Num.isNonZero(value)) {
|
|
234
245
|
// value is guaranteed to be non-zero
|
|
235
246
|
const result = Num.div(10, value); // Safe division
|
|
236
|
-
assert
|
|
247
|
+
assert(result === 2);
|
|
237
248
|
}
|
|
238
249
|
```
|
|
239
250
|
|
|
@@ -261,10 +272,10 @@ const unsigned = asUint(42); // Uint - non-negative integer
|
|
|
261
272
|
const finite = asFiniteNumber(3.14); // FiniteNumber - finite floating-point
|
|
262
273
|
const safeInt = asSafeInt(42); // SafeInt - integer in safe range
|
|
263
274
|
|
|
264
|
-
assert
|
|
265
|
-
assert
|
|
266
|
-
assert
|
|
267
|
-
assert
|
|
275
|
+
assert(integer === 42);
|
|
276
|
+
assert(unsigned === 42);
|
|
277
|
+
assert(finite === 3.14);
|
|
278
|
+
assert(safeInt === 42);
|
|
268
279
|
|
|
269
280
|
// This line would cause a runtime error:
|
|
270
281
|
assert.throw(() => {
|
|
@@ -274,29 +285,29 @@ assert.throw(() => {
|
|
|
274
285
|
// Range-constrained types (16-bit, 32-bit)
|
|
275
286
|
const int16 = asInt16(1000); // Int16: [-32768, 32767]
|
|
276
287
|
const uint32 = asUint32(3000000000); // Uint32: [0, 4294967295]
|
|
277
|
-
assert
|
|
278
|
-
assert
|
|
288
|
+
assert(int16 === 1000);
|
|
289
|
+
assert(uint32 === 3000000000);
|
|
279
290
|
|
|
280
291
|
// Non-zero and positive variants
|
|
281
292
|
const nonZeroInt = asNonZeroInt(5); // NonZeroInt - excludes zero
|
|
282
293
|
const positiveInt = asPositiveInt(10); // PositiveInt - excludes zero and negatives
|
|
283
|
-
assert
|
|
284
|
-
assert
|
|
294
|
+
assert(nonZeroInt === 5);
|
|
295
|
+
assert(positiveInt === 10);
|
|
285
296
|
|
|
286
297
|
// Type-safe arithmetic with automatic clamping
|
|
287
298
|
const sum = Int16.add(int16, asInt16(2000)); // Int16 (3000)
|
|
288
299
|
const clamped = Int16.clamp(100000); // Int16 (32767 - clamped to MAX_VALUE)
|
|
289
|
-
assert
|
|
290
|
-
assert
|
|
300
|
+
assert(sum === 3000);
|
|
301
|
+
assert(clamped === 32767);
|
|
291
302
|
|
|
292
303
|
// Safe division with non-zero types
|
|
293
304
|
const ratio = NonZeroInt.div(asNonZeroInt(10), nonZeroInt); // No division by zero risk
|
|
294
|
-
assert
|
|
305
|
+
assert(ratio === 2);
|
|
295
306
|
|
|
296
307
|
// Random generation within type constraints
|
|
297
308
|
const randomInt16 = Int16.random(); // Int16 (random value in valid range)
|
|
298
|
-
assert
|
|
299
|
-
assert
|
|
309
|
+
assert(-32768 <= randomInt16);
|
|
310
|
+
assert(randomInt16 <= 32767);
|
|
300
311
|
```
|
|
301
312
|
|
|
302
313
|
### 4. Array Utilities with `Arr`
|
|
@@ -311,13 +322,13 @@ const numbers: readonly number[] = [1, 2, 3, 4, 5, 2, 3];
|
|
|
311
322
|
// Reduction
|
|
312
323
|
const sum = Arr.sum(numbers);
|
|
313
324
|
|
|
314
|
-
assert
|
|
325
|
+
assert(sum === 20);
|
|
315
326
|
|
|
316
327
|
// Type-safe length checking
|
|
317
328
|
if (Arr.isArrayAtLeastLength(numbers, 2)) {
|
|
318
329
|
// numbers is now guaranteed to have at least 2 elements
|
|
319
330
|
expectType<typeof numbers, readonly [number, number, ...number[]]>('=');
|
|
320
|
-
assert
|
|
331
|
+
assert(numbers[1] === 2); // Safe access to index 1
|
|
321
332
|
}
|
|
322
333
|
|
|
323
334
|
// Take first n elements
|
|
@@ -350,7 +361,7 @@ assert.deepStrictEqual(
|
|
|
350
361
|
Optional.some({ name: 'Charlie', age: 35 } as const),
|
|
351
362
|
);
|
|
352
363
|
if (Optional.isSome(oldestPerson)) {
|
|
353
|
-
assert
|
|
364
|
+
assert(oldestPerson.value.name === 'Charlie');
|
|
354
365
|
}
|
|
355
366
|
```
|
|
356
367
|
|
|
@@ -367,10 +378,10 @@ const mapWithOne = originalMap.set('one', 1);
|
|
|
367
378
|
const mapWithTwo = mapWithOne.set('two', 2);
|
|
368
379
|
|
|
369
380
|
// Original map is unchanged
|
|
370
|
-
assert
|
|
381
|
+
assert(originalMap.size === 0);
|
|
371
382
|
assert.deepStrictEqual(mapWithTwo.get('one'), Optional.some(1));
|
|
372
383
|
|
|
373
|
-
assert
|
|
384
|
+
assert(!mapWithTwo.has('three'));
|
|
374
385
|
|
|
375
386
|
// Using pipe for fluent updates
|
|
376
387
|
const sequence = Arr.seq(10); // [0, 1, 2, ..., 9]
|
|
@@ -380,7 +391,7 @@ const pairs = sequence.map(
|
|
|
380
391
|
const skipped = Arr.skip(pairs, 1); // [[1, "1"], ..., [9, "9"]]
|
|
381
392
|
const idMap = IMap.create<number, string>(skipped);
|
|
382
393
|
|
|
383
|
-
assert
|
|
394
|
+
assert(idMap.size === 9);
|
|
384
395
|
|
|
385
396
|
// Efficient batch updates with withMutations
|
|
386
397
|
const idMapUpdated = idMap.withMutations([
|
|
@@ -389,15 +400,15 @@ const idMapUpdated = idMap.withMutations([
|
|
|
389
400
|
{ type: 'delete', key: 4 },
|
|
390
401
|
]);
|
|
391
402
|
|
|
392
|
-
assert
|
|
403
|
+
assert(idMapUpdated.size === 9);
|
|
393
404
|
|
|
394
405
|
// ISet usage
|
|
395
406
|
const originalSet = ISet.create<number>([]);
|
|
396
407
|
const setWithItems = originalSet.add(1).add(2).add(1); // Duplicate ignored
|
|
397
408
|
|
|
398
|
-
assert
|
|
399
|
-
assert
|
|
400
|
-
assert
|
|
409
|
+
assert(originalSet.size === 0); // (unchanged)
|
|
410
|
+
assert(setWithItems.has(1));
|
|
411
|
+
assert(setWithItems.size === 2);
|
|
401
412
|
```
|
|
402
413
|
|
|
403
414
|
### 6. Type Guards
|
|
@@ -430,9 +441,9 @@ if (isNonNullObject(value)) {
|
|
|
430
441
|
}
|
|
431
442
|
|
|
432
443
|
// Example usage
|
|
433
|
-
assert
|
|
434
|
-
assert
|
|
435
|
-
assert
|
|
444
|
+
assert(processData({ name: 'Alice' }) === 'Hello, Alice!');
|
|
445
|
+
assert(processData({ age: 30 }) === undefined);
|
|
446
|
+
assert(processData('not an object') === undefined);
|
|
436
447
|
```
|
|
437
448
|
|
|
438
449
|
### 7. Iteration with `range`
|
|
@@ -532,7 +543,8 @@ assert.deepStrictEqual(updatedState.items, ['newItem1', 'newItem2']);
|
|
|
532
543
|
|
|
533
544
|
**Important Notes:**
|
|
534
545
|
|
|
535
|
-
- This library **only supports ESM (ES Modules)
|
|
546
|
+
- This library **only supports ESM (ES Modules)** and is designed for native ESM environments. CommonJS is not supported.
|
|
547
|
+
- The library uses `.mts` file extensions and proper ESM exports, making it compatible with modern Node.js ESM resolution and bundlers that support native ESM.
|
|
536
548
|
- This library uses advanced TypeScript features, including branded types for enhanced type safety. Some functions require specific branded types as parameters (such as `Uint32` in `newArray`). The examples above use the small literal numeric values specifically allowed in each function for brevity, but in actual use you should use the provided type conversion functions (such as `asUint32`) or cast to the appropriate branded type, for example `as Uint32`.
|
|
537
549
|
|
|
538
550
|
## Removing `expectType` in Production
|