ts-data-forge 2.0.0 → 2.0.2

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 CHANGED
@@ -166,7 +166,7 @@ const maybeValue = Optional.some(42);
166
166
 
167
167
  const doubled = Optional.map(maybeValue, (x) => x * 2);
168
168
 
169
- assert.strictEqual(Optional.unwrapOr(doubled, 0), 84);
169
+ assert(Optional.unwrapOr(doubled, 0) === 84);
170
170
 
171
171
  // Result for error handling
172
172
  const success = Result.ok(42);
@@ -196,16 +196,16 @@ const handleStatus = (status: Status, data?: string): string =>
196
196
  error: 'An error occurred',
197
197
  });
198
198
 
199
- assert.strictEqual(handleStatus('loading'), 'Please wait...');
200
- assert.strictEqual(handleStatus('success', 'Hello'), 'Data: Hello');
201
- assert.strictEqual(handleStatus('error'), 'An error occurred');
199
+ assert(handleStatus('loading') === 'Please wait...');
200
+ assert(handleStatus('success', 'Hello') === 'Data: Hello');
201
+ assert(handleStatus('error') === 'An error occurred');
202
202
 
203
203
  // Pattern matching with Result
204
204
  const processResult = (result: Result<number, string>): string =>
205
205
  Result.isOk(result) ? `Success: ${result.value}` : `Error: ${result.value}`;
206
206
 
207
- assert.strictEqual(processResult(Result.ok(42)), 'Success: 42');
208
- assert.strictEqual(processResult(Result.err('Failed')), 'Error: Failed');
207
+ assert(processResult(Result.ok(42)) === 'Success: 42');
208
+ assert(processResult(Result.err('Failed')) === 'Error: Failed');
209
209
  ```
210
210
 
211
211
  ### 3. Number Utilities with `Num` and Branded Number Types
@@ -216,35 +216,35 @@ The `Num` object provides safe and convenient functions for numerical operations
216
216
  import { Num } from 'ts-data-forge';
217
217
 
218
218
  // Basic conversions
219
- assert.strictEqual(Num.from('123'), 123);
220
- assert.strictEqual(Number.isNaN(Num.from('abc')), true);
219
+ assert(Num.from('123') === 123);
220
+ assert(Number.isNaN(Num.from('abc')));
221
221
 
222
222
  // Range checking
223
223
  const inRange = Num.isInRange(0, 10);
224
224
 
225
- assert.strictEqual(inRange(5), true);
226
- assert.strictEqual(inRange(0), true); // (inclusive lower bound)
227
- assert.strictEqual(inRange(10), false); // (exclusive upper bound)
225
+ assert(inRange(5));
226
+ assert(inRange(0)); // (inclusive lower bound)
227
+ assert(!inRange(10)); // (exclusive upper bound)
228
228
 
229
229
  // Clamping values
230
230
  const clamp = Num.clamp(0, 100);
231
231
 
232
- assert.strictEqual(clamp(150), 100);
233
- assert.strictEqual(clamp(-10), 0);
232
+ assert(clamp(150) === 100);
233
+ assert(clamp(-10) === 0);
234
234
 
235
235
  // Rounding utilities
236
236
  const round2 = Num.round(2);
237
237
 
238
- assert.strictEqual(round2(3.14159), 3.14);
239
- assert.strictEqual(Num.roundAt(3.14159, 3), 3.142);
240
- assert.strictEqual(Num.roundToInt(3.7), 4);
238
+ assert(round2(3.14159) === 3.14);
239
+ assert(Num.roundAt(3.14159, 3) === 3.142);
240
+ assert(Num.roundToInt(3.7) === 4);
241
241
 
242
242
  // Type guards
243
243
  const value = 5; // example value
244
244
  if (Num.isNonZero(value)) {
245
245
  // value is guaranteed to be non-zero
246
246
  const result = Num.div(10, value); // Safe division
247
- assert.strictEqual(result, 2);
247
+ assert(result === 2);
248
248
  }
249
249
  ```
250
250
 
@@ -272,10 +272,10 @@ const unsigned = asUint(42); // Uint - non-negative integer
272
272
  const finite = asFiniteNumber(3.14); // FiniteNumber - finite floating-point
273
273
  const safeInt = asSafeInt(42); // SafeInt - integer in safe range
274
274
 
275
- assert.strictEqual(integer, 42);
276
- assert.strictEqual(unsigned, 42);
277
- assert.strictEqual(finite, 3.14);
278
- assert.strictEqual(safeInt, 42);
275
+ assert(integer === 42);
276
+ assert(unsigned === 42);
277
+ assert(finite === 3.14);
278
+ assert(safeInt === 42);
279
279
 
280
280
  // This line would cause a runtime error:
281
281
  assert.throw(() => {
@@ -285,29 +285,29 @@ assert.throw(() => {
285
285
  // Range-constrained types (16-bit, 32-bit)
286
286
  const int16 = asInt16(1000); // Int16: [-32768, 32767]
287
287
  const uint32 = asUint32(3000000000); // Uint32: [0, 4294967295]
288
- assert.strictEqual(int16, 1000);
289
- assert.strictEqual(uint32, 3000000000);
288
+ assert(int16 === 1000);
289
+ assert(uint32 === 3000000000);
290
290
 
291
291
  // Non-zero and positive variants
292
292
  const nonZeroInt = asNonZeroInt(5); // NonZeroInt - excludes zero
293
293
  const positiveInt = asPositiveInt(10); // PositiveInt - excludes zero and negatives
294
- assert.strictEqual(nonZeroInt, 5);
295
- assert.strictEqual(positiveInt, 10);
294
+ assert(nonZeroInt === 5);
295
+ assert(positiveInt === 10);
296
296
 
297
297
  // Type-safe arithmetic with automatic clamping
298
298
  const sum = Int16.add(int16, asInt16(2000)); // Int16 (3000)
299
299
  const clamped = Int16.clamp(100000); // Int16 (32767 - clamped to MAX_VALUE)
300
- assert.strictEqual(sum, 3000);
301
- assert.strictEqual(clamped, 32767);
300
+ assert(sum === 3000);
301
+ assert(clamped === 32767);
302
302
 
303
303
  // Safe division with non-zero types
304
304
  const ratio = NonZeroInt.div(asNonZeroInt(10), nonZeroInt); // No division by zero risk
305
- assert.strictEqual(ratio, 2);
305
+ assert(ratio === 2);
306
306
 
307
307
  // Random generation within type constraints
308
308
  const randomInt16 = Int16.random(); // Int16 (random value in valid range)
309
- assert.strictEqual(-32768 <= randomInt16, true);
310
- assert.strictEqual(randomInt16 <= 32767, true);
309
+ assert(-32768 <= randomInt16);
310
+ assert(randomInt16 <= 32767);
311
311
  ```
312
312
 
313
313
  ### 4. Array Utilities with `Arr`
@@ -322,13 +322,13 @@ const numbers: readonly number[] = [1, 2, 3, 4, 5, 2, 3];
322
322
  // Reduction
323
323
  const sum = Arr.sum(numbers);
324
324
 
325
- assert.strictEqual(sum, 20);
325
+ assert(sum === 20);
326
326
 
327
327
  // Type-safe length checking
328
328
  if (Arr.isArrayAtLeastLength(numbers, 2)) {
329
329
  // numbers is now guaranteed to have at least 2 elements
330
330
  expectType<typeof numbers, readonly [number, number, ...number[]]>('=');
331
- assert.strictEqual(numbers[1], 2); // Safe access to index 1
331
+ assert(numbers[1] === 2); // Safe access to index 1
332
332
  }
333
333
 
334
334
  // Take first n elements
@@ -361,7 +361,7 @@ assert.deepStrictEqual(
361
361
  Optional.some({ name: 'Charlie', age: 35 } as const),
362
362
  );
363
363
  if (Optional.isSome(oldestPerson)) {
364
- assert.strictEqual(oldestPerson.value.name, 'Charlie');
364
+ assert(oldestPerson.value.name === 'Charlie');
365
365
  }
366
366
  ```
367
367
 
@@ -378,10 +378,10 @@ const mapWithOne = originalMap.set('one', 1);
378
378
  const mapWithTwo = mapWithOne.set('two', 2);
379
379
 
380
380
  // Original map is unchanged
381
- assert.strictEqual(originalMap.size, 0);
381
+ assert(originalMap.size === 0);
382
382
  assert.deepStrictEqual(mapWithTwo.get('one'), Optional.some(1));
383
383
 
384
- assert.strictEqual(mapWithTwo.has('three'), false);
384
+ assert(!mapWithTwo.has('three'));
385
385
 
386
386
  // Using pipe for fluent updates
387
387
  const sequence = Arr.seq(10); // [0, 1, 2, ..., 9]
@@ -391,7 +391,7 @@ const pairs = sequence.map(
391
391
  const skipped = Arr.skip(pairs, 1); // [[1, "1"], ..., [9, "9"]]
392
392
  const idMap = IMap.create<number, string>(skipped);
393
393
 
394
- assert.strictEqual(idMap.size, 9);
394
+ assert(idMap.size === 9);
395
395
 
396
396
  // Efficient batch updates with withMutations
397
397
  const idMapUpdated = idMap.withMutations([
@@ -400,15 +400,15 @@ const idMapUpdated = idMap.withMutations([
400
400
  { type: 'delete', key: 4 },
401
401
  ]);
402
402
 
403
- assert.strictEqual(idMapUpdated.size, 9);
403
+ assert(idMapUpdated.size === 9);
404
404
 
405
405
  // ISet usage
406
406
  const originalSet = ISet.create<number>([]);
407
407
  const setWithItems = originalSet.add(1).add(2).add(1); // Duplicate ignored
408
408
 
409
- assert.strictEqual(originalSet.size, 0); // (unchanged)
410
- assert.strictEqual(setWithItems.has(1), true);
411
- assert.strictEqual(setWithItems.size, 2);
409
+ assert(originalSet.size === 0); // (unchanged)
410
+ assert(setWithItems.has(1));
411
+ assert(setWithItems.size === 2);
412
412
  ```
413
413
 
414
414
  ### 6. Type Guards
@@ -441,9 +441,9 @@ if (isNonNullObject(value)) {
441
441
  }
442
442
 
443
443
  // Example usage
444
- assert.strictEqual(processData({ name: 'Alice' }), 'Hello, Alice!');
445
- assert.strictEqual(processData({ age: 30 }), undefined);
446
- assert.strictEqual(processData('not an object'), undefined);
444
+ assert(processData({ name: 'Alice' }) === 'Hello, Alice!');
445
+ assert(processData({ age: 30 }) === undefined);
446
+ assert(processData('not an object') === undefined);
447
447
  ```
448
448
 
449
449
  ### 7. Iteration with `range`
@@ -1,13 +1,4 @@
1
1
  import { Optional } from './optional.mjs';
2
- /**
3
- * @internal
4
- * Utility type to merge intersection types into a single object type.
5
- * This helps with TypeScript's display of complex intersection types.
6
- * @template T The intersection type to merge.
7
- */
8
- type MergeIntersection<T> = {
9
- [K in keyof T]: T[K];
10
- };
11
2
  /**
12
3
  * Creates a new pipe object that allows for chaining operations on a value.
13
4
  *
@@ -26,13 +17,14 @@ type MergeIntersection<T> = {
26
17
  *
27
18
  * @example
28
19
  * Basic value transformation chaining:
29
- * ```typescript
20
+ * ```ts
30
21
  * // Simple sequential transformations
31
22
  * const result = pipe(10)
32
23
  * .map(x => x * 2) // 20
33
24
  * .map(x => x + 5) // 25
34
25
  * .map(x => x.toString()) // '25'
35
26
  * .value;
27
+ * assert(result === '25');
36
28
  *
37
29
  * // String processing pipeline
38
30
  * const processed = pipe(" Hello World ")
@@ -41,82 +33,93 @@ type MergeIntersection<T> = {
41
33
  * .map(s => s.split(' ')) // ["hello", "world"]
42
34
  * .map(arr => arr.join('-')) // "hello-world"
43
35
  * .value;
36
+ * assert(processed === "hello-world");
44
37
  * ```
45
38
  *
46
39
  * @example
47
40
  * Nullable value handling with automatic null checking:
48
- * ```typescript
49
- * // Safe operations on potentially null values
50
- * const maybeNumber: number | null = getNumberFromAPI();
41
+ * ```ts
42
+ * // Safe operations on potentially nullish values
43
+ * const maybeNumber: number | undefined = 10;
51
44
  * const result = pipe(maybeNumber)
52
45
  * .mapNullable(x => x * 2) // Only applies if not null
53
46
  * .mapNullable(x => `Result: ${x}`) // Only applies if previous step succeeded
54
47
  * .value; // 'Result: 20' or undefined
48
+ * assert(result === 'Result: 20');
55
49
  *
56
- * // Handling undefined values
57
- * const maybeUser: User | undefined = findUser(id);
58
- * const userName = pipe(maybeUser)
59
- * .mapNullable(user => user.name)
60
- * .mapNullable(name => name.toUpperCase())
61
- * .value; // string or undefined
50
+ * // Handling null values
51
+ * const nullValue: number | null = null;
52
+ * const nullResult = pipe(nullValue)
53
+ * .mapNullable(x => x * 2)
54
+ * .value;
55
+ * assert(nullResult === undefined);
62
56
  * ```
63
57
  *
64
58
  * @example
65
59
  * Optional value handling with monadic operations:
66
- * ```typescript
60
+ * ```ts
67
61
  * // Working with Optional types
68
62
  * const optional = Optional.some(42);
69
63
  * const result = pipe(optional)
70
64
  * .mapOptional(x => x / 2) // Optional.some(21)
71
65
  * .mapOptional(x => Math.sqrt(x)) // Optional.some(~4.58)
72
66
  * .value; // Optional.some(4.58...)
67
+ * assert(Optional.isSome(result) === true);
68
+ * assert(Math.abs(Optional.unwrap(result)! - Math.sqrt(21)) < 0.01);
73
69
  *
74
- * // Optional chains that can become None
75
- * const parseAndProcess = (input: string) =>
76
- * pipe(Optional.fromNullable(input))
77
- * .mapOptional(s => s.trim())
78
- * .mapOptional(s => s.length > 0 ? s : null) // Could become None
79
- * .mapOptional(s => parseInt(s, 10))
80
- * .mapOptional(n => isNaN(n) ? null : n)
81
- * .value; // Optional<number>
70
+ * // Optional with None
71
+ * const noneOptional = Optional.none;
72
+ * const noneResult = pipe(noneOptional)
73
+ * .mapOptional(x => x * 2)
74
+ * .value;
75
+ * assert(Optional.isNone(noneResult) === true);
82
76
  * ```
83
77
  *
84
78
  * @example
85
79
  * Mixed type transformations:
86
- * ```typescript
80
+ * ```ts
87
81
  * // Starting with a string, transforming through different types
88
82
  * const complex = pipe('hello')
89
83
  * .map(s => s.length) // number: 5
90
- * .map(n => n > 3 ? n : null) // number | null: 5
91
- * .mapNullable(n => n * 10) // number: 50 (or undefined if null)
84
+ * .map(n => n > 3 ? n : undefined) // number | undefined: 5
85
+ * .mapNullable(n => n * 10) // number: 50 (or undefined if undefined)
92
86
  * .value; // 50 or undefined
87
+ * assert(complex === 50);
93
88
  *
94
- * // API response processing
95
- * const processApiResponse = (response: ApiResponse) =>
96
- * pipe(response)
97
- * .map(r => r.data) // Extract data
98
- * .mapNullable(data => data.user) // Safe user access
99
- * .mapNullable(user => user.profile) // Safe profile access
100
- * .mapNullable(profile => profile.avatar) // Safe avatar access
101
- * .value; // string | undefined
89
+ * // Short string case
90
+ * const shortString = pipe('hi')
91
+ * .map(s => s.length) // number: 2
92
+ * .map(n => n > 3 ? n : undefined) // number | undefined: undefined
93
+ * .mapNullable(n => n * 10) // undefined
94
+ * .value;
95
+ * assert(shortString === undefined);
102
96
  * ```
103
97
  *
104
98
  * @example
105
99
  * Error-safe computation chains:
106
- * ```typescript
100
+ * ```ts
107
101
  * // Building complex computations safely
108
- * const safeCalculation = (input: unknown) =>
109
- * pipe(input)
110
- * .map(val => typeof val === 'number' ? val : null)
111
- * .mapNullable(n => n > 0 ? n : null) // Positive numbers only
112
- * .mapNullable(n => Math.sqrt(n)) // Safe square root
113
- * .mapNullable(n => n < 100 ? n : null) // Limit result
114
- * .mapNullable(n => Math.round(n * 100) / 100) // Round to 2 decimals
115
- * .value; // number | undefined
102
+ * const maybeNumber: number | undefined = 25;
103
+ * const result = pipe(maybeNumber)
104
+ * .mapNullable(n => n > 0 ? n : undefined) // Positive numbers only
105
+ * .mapNullable(n => Math.sqrt(n)) // Safe square root
106
+ * .mapNullable(n => n < 100 ? n : undefined) // Limit result
107
+ * .mapNullable(n => Math.round(n * 100) / 100) // Round to 2 decimals
108
+ * .value; // number | undefined
109
+ *
110
+ * assert(result === 5); // sqrt(25) = 5
111
+ *
112
+ * const negativeNumber: number | undefined = -5;
113
+ * const negativeResult = pipe(negativeNumber)
114
+ * .mapNullable(n => n > 0 ? n : undefined)
115
+ * .value;
116
+ * assert(negativeResult === undefined); // negative number
116
117
  * ```
118
+ *
117
119
  */
118
120
  export declare function pipe<const A extends Optional.Base>(a: A): PipeWithMapOptional<A>;
119
- export declare function pipe<const A>(a: A): PipeWithMapNullable<A>;
121
+ export declare function pipe<const A>(a: A): PipeBase<A>;
122
+ type Pipe<A> = A extends Optional.Base ? PipeWithMapOptional<A> : PipeBase<A>;
120
123
  /**
121
124
  * @internal
122
125
  * Base pipe interface providing core functionality.
@@ -132,15 +135,7 @@ type PipeBase<A> = Readonly<{
132
135
  * @param fn Function to transform the current value.
133
136
  * @returns A new pipe containing the transformed value.
134
137
  */
135
- map: <B>(fn: (a: A) => B) => PipeBase<B>;
136
- }>;
137
- /**
138
- * @internal
139
- * Pipe interface for non-Optional values, providing null-safe mapping.
140
- * Extends PipeBase with mapNullable functionality.
141
- * @template A The type of the current value in the pipe.
142
- */
143
- type PipeWithMapNullable<A> = MergeIntersection<PipeBase<A> & Readonly<{
138
+ map: <B>(fn: (a: A) => B) => Pipe<B>;
144
139
  /**
145
140
  * Maps the current value only if it's not null or undefined.
146
141
  * If the current value is null/undefined, the transformation is skipped
@@ -149,8 +144,8 @@ type PipeWithMapNullable<A> = MergeIntersection<PipeBase<A> & Readonly<{
149
144
  * @param fn Function to transform the non-null value.
150
145
  * @returns A new pipe containing the transformed value or undefined.
151
146
  */
152
- mapNullable: <B>(fn: (a: NonNullable<A>) => B) => PipeBase<B | undefined>;
153
- }>>;
147
+ mapNullable: <B>(fn: (a: NonNullable<A>) => B) => Pipe<B | undefined>;
148
+ }>;
154
149
  /**
155
150
  * @internal
156
151
  * Pipe interface for Optional values, providing Optional-aware mapping.
@@ -166,7 +161,7 @@ type PipeWithMapOptional<A extends Optional.Base> = MergeIntersection<PipeBase<A
166
161
  * @param fn Function to transform the inner value of the Optional.
167
162
  * @returns A new pipe containing an Optional with the transformed value.
168
163
  */
169
- mapOptional: <B>(fn: (a: Optional.Unwrap<A>) => B) => PipeBase<Optional<B>>;
164
+ mapOptional: <B>(fn: (a: Optional.Unwrap<A>) => B) => Pipe<Optional<B>>;
170
165
  }>>;
171
166
  export {};
172
167
  //# sourceMappingURL=pipe.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pipe.d.mts","sourceRoot":"","sources":["../../src/functional/pipe.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C;;;;;GAKG;AACH,KAAK,iBAAiB,CAAC,CAAC,IAAI;KACzB,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CACrB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0GG;AACH,wBAAgB,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,QAAQ,CAAC,IAAI,EAChD,CAAC,EAAE,CAAC,GACH,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAE1B,wBAAgB,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAkB5D;;;;;GAKG;AACH,KAAK,QAAQ,CAAC,CAAC,IAAI,QAAQ,CAAC;IAC1B,qCAAqC;IACrC,KAAK,EAAE,CAAC,CAAC;IACT;;;;;OAKG;IACH,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC;CAC1C,CAAC,CAAC;AAEH;;;;;GAKG;AACH,KAAK,mBAAmB,CAAC,CAAC,IAAI,iBAAiB,CAC7C,QAAQ,CAAC,CAAC,CAAC,GACT,QAAQ,CAAC;IACP;;;;;;;OAOG;IACH,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,QAAQ,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;CAC3E,CAAC,CACL,CAAC;AAEF;;;;;GAKG;AACH,KAAK,mBAAmB,CAAC,CAAC,SAAS,QAAQ,CAAC,IAAI,IAAI,iBAAiB,CACnE,QAAQ,CAAC,CAAC,CAAC,GACT,QAAQ,CAAC;IACP;;;;;;;OAOG;IACH,WAAW,EAAE,CAAC,CAAC,EACb,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAC7B,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;CAC5B,CAAC,CACL,CAAC"}
1
+ {"version":3,"file":"pipe.d.mts","sourceRoot":"","sources":["../../src/functional/pipe.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqHG;AACH,wBAAgB,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,QAAQ,CAAC,IAAI,EAChD,CAAC,EAAE,CAAC,GACH,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAE1B,wBAAgB,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;AAkBjD,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,QAAQ,CAAC,IAAI,GAAG,mBAAmB,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;AAE9E;;;;;GAKG;AACH,KAAK,QAAQ,CAAC,CAAC,IAAI,QAAQ,CAAC;IAC1B,qCAAqC;IACrC,KAAK,EAAE,CAAC,CAAC;IACT;;;;;OAKG;IACH,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;IAErC;;;;;;;OAOG;IACH,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;CACvE,CAAC,CAAC;AAEH;;;;;GAKG;AACH,KAAK,mBAAmB,CAAC,CAAC,SAAS,QAAQ,CAAC,IAAI,IAAI,iBAAiB,CACnE,QAAQ,CAAC,CAAC,CAAC,GACT,QAAQ,CAAC;IACP;;;;;;;OAOG;IACH,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;CACzE,CAAC,CACL,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"pipe.mjs","sources":["../../src/functional/pipe.mts"],"sourcesContent":[null],"names":[],"mappings":";;AA6HM,SAAU,IAAI,CAAU,CAAI,EAAA;AAChC,IAAA,IAAI,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;QAC1B,OAAO;AACL,YAAA,KAAK,EAAE,CAAC;AACR,YAAA,GAAG,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACxB,YAAA,WAAW,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;SAC/C;IACH;SAAO;QACL,OAAO;AACL,YAAA,KAAK,EAAE,CAAC;AACR,YAAA,GAAG,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACxB,WAAW,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,IAAI,IAAI,GAAG,SAAS,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;SACzD;IACH;AACF;;;;"}
1
+ {"version":3,"file":"pipe.mjs","sources":["../../src/functional/pipe.mts"],"sourcesContent":[null],"names":[],"mappings":";;AA8HM,SAAU,IAAI,CAAU,CAAI,EAAA;AAChC,IAAA,IAAI,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;QAC1B,OAAO;AACL,YAAA,KAAK,EAAE,CAAC;AACR,YAAA,GAAG,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACxB,YAAA,WAAW,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;SAC/C;IACH;SAAO;QACL,OAAO;AACL,YAAA,KAAK,EAAE,CAAC;AACR,YAAA,GAAG,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACxB,WAAW,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,IAAI,IAAI,GAAG,SAAS,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;SACzD;IACH;AACF;;;;"}
@@ -258,7 +258,7 @@ export declare namespace Obj {
258
258
  * }
259
259
  * ```
260
260
  */
261
- export const fromEntries: <const Entries extends readonly (readonly [PropertyKey, unknown])[]>(entries: Entries) => IsFixedLengthList<Entries> extends true ? TsDataForgeInternals.EntriesToObject<Entries> : TsDataForgeInternals.PartialIfKeyIsUnion<TsDataForgeInternals.KeysOfEntries<Entries>, Record<TsDataForgeInternals.KeysOfEntries<Entries>, TsDataForgeInternals.ValuesOfEntries<Entries>>>;
261
+ export const fromEntries: <const Entries extends readonly (readonly [PropertyKey, unknown])[]>(entries: Entries) => IsFixedLengthList<Entries> extends true ? TsDataForgeInternals.EntriesToObject<Entries> : TsDataForgeInternals.PartialIfKeyIsUnion<TsDataForgeInternals.KeysOfEntries<Entries>, ReadonlyRecord<TsDataForgeInternals.KeysOfEntries<Entries>, TsDataForgeInternals.ValuesOfEntries<Entries>>>;
262
262
  /**
263
263
  * @internal
264
264
  * Internal type utilities for the Obj module.
@@ -1 +1 @@
1
- {"version":3,"file":"object.d.mts","sourceRoot":"","sources":["../../src/object/object.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"object.d.mts","sourceRoot":"","sources":["../../src/object/object.mts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-data-forge",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "private": false,
5
5
  "keywords": [
6
6
  "typescript",
@@ -1,15 +1,5 @@
1
1
  import { Optional } from './optional.mjs';
2
2
 
3
- /**
4
- * @internal
5
- * Utility type to merge intersection types into a single object type.
6
- * This helps with TypeScript's display of complex intersection types.
7
- * @template T The intersection type to merge.
8
- */
9
- type MergeIntersection<T> = {
10
- [K in keyof T]: T[K];
11
- };
12
-
13
3
  /**
14
4
  * Creates a new pipe object that allows for chaining operations on a value.
15
5
  *
@@ -28,13 +18,14 @@ type MergeIntersection<T> = {
28
18
  *
29
19
  * @example
30
20
  * Basic value transformation chaining:
31
- * ```typescript
21
+ * ```ts
32
22
  * // Simple sequential transformations
33
23
  * const result = pipe(10)
34
24
  * .map(x => x * 2) // 20
35
25
  * .map(x => x + 5) // 25
36
26
  * .map(x => x.toString()) // '25'
37
27
  * .value;
28
+ * assert(result === '25');
38
29
  *
39
30
  * // String processing pipeline
40
31
  * const processed = pipe(" Hello World ")
@@ -43,85 +34,95 @@ type MergeIntersection<T> = {
43
34
  * .map(s => s.split(' ')) // ["hello", "world"]
44
35
  * .map(arr => arr.join('-')) // "hello-world"
45
36
  * .value;
37
+ * assert(processed === "hello-world");
46
38
  * ```
47
39
  *
48
40
  * @example
49
41
  * Nullable value handling with automatic null checking:
50
- * ```typescript
51
- * // Safe operations on potentially null values
52
- * const maybeNumber: number | null = getNumberFromAPI();
42
+ * ```ts
43
+ * // Safe operations on potentially nullish values
44
+ * const maybeNumber: number | undefined = 10;
53
45
  * const result = pipe(maybeNumber)
54
46
  * .mapNullable(x => x * 2) // Only applies if not null
55
47
  * .mapNullable(x => `Result: ${x}`) // Only applies if previous step succeeded
56
48
  * .value; // 'Result: 20' or undefined
49
+ * assert(result === 'Result: 20');
57
50
  *
58
- * // Handling undefined values
59
- * const maybeUser: User | undefined = findUser(id);
60
- * const userName = pipe(maybeUser)
61
- * .mapNullable(user => user.name)
62
- * .mapNullable(name => name.toUpperCase())
63
- * .value; // string or undefined
51
+ * // Handling null values
52
+ * const nullValue: number | null = null;
53
+ * const nullResult = pipe(nullValue)
54
+ * .mapNullable(x => x * 2)
55
+ * .value;
56
+ * assert(nullResult === undefined);
64
57
  * ```
65
58
  *
66
59
  * @example
67
60
  * Optional value handling with monadic operations:
68
- * ```typescript
61
+ * ```ts
69
62
  * // Working with Optional types
70
63
  * const optional = Optional.some(42);
71
64
  * const result = pipe(optional)
72
65
  * .mapOptional(x => x / 2) // Optional.some(21)
73
66
  * .mapOptional(x => Math.sqrt(x)) // Optional.some(~4.58)
74
67
  * .value; // Optional.some(4.58...)
68
+ * assert(Optional.isSome(result) === true);
69
+ * assert(Math.abs(Optional.unwrap(result)! - Math.sqrt(21)) < 0.01);
75
70
  *
76
- * // Optional chains that can become None
77
- * const parseAndProcess = (input: string) =>
78
- * pipe(Optional.fromNullable(input))
79
- * .mapOptional(s => s.trim())
80
- * .mapOptional(s => s.length > 0 ? s : null) // Could become None
81
- * .mapOptional(s => parseInt(s, 10))
82
- * .mapOptional(n => isNaN(n) ? null : n)
83
- * .value; // Optional<number>
71
+ * // Optional with None
72
+ * const noneOptional = Optional.none;
73
+ * const noneResult = pipe(noneOptional)
74
+ * .mapOptional(x => x * 2)
75
+ * .value;
76
+ * assert(Optional.isNone(noneResult) === true);
84
77
  * ```
85
78
  *
86
79
  * @example
87
80
  * Mixed type transformations:
88
- * ```typescript
81
+ * ```ts
89
82
  * // Starting with a string, transforming through different types
90
83
  * const complex = pipe('hello')
91
84
  * .map(s => s.length) // number: 5
92
- * .map(n => n > 3 ? n : null) // number | null: 5
93
- * .mapNullable(n => n * 10) // number: 50 (or undefined if null)
85
+ * .map(n => n > 3 ? n : undefined) // number | undefined: 5
86
+ * .mapNullable(n => n * 10) // number: 50 (or undefined if undefined)
94
87
  * .value; // 50 or undefined
88
+ * assert(complex === 50);
95
89
  *
96
- * // API response processing
97
- * const processApiResponse = (response: ApiResponse) =>
98
- * pipe(response)
99
- * .map(r => r.data) // Extract data
100
- * .mapNullable(data => data.user) // Safe user access
101
- * .mapNullable(user => user.profile) // Safe profile access
102
- * .mapNullable(profile => profile.avatar) // Safe avatar access
103
- * .value; // string | undefined
90
+ * // Short string case
91
+ * const shortString = pipe('hi')
92
+ * .map(s => s.length) // number: 2
93
+ * .map(n => n > 3 ? n : undefined) // number | undefined: undefined
94
+ * .mapNullable(n => n * 10) // undefined
95
+ * .value;
96
+ * assert(shortString === undefined);
104
97
  * ```
105
98
  *
106
99
  * @example
107
100
  * Error-safe computation chains:
108
- * ```typescript
101
+ * ```ts
109
102
  * // Building complex computations safely
110
- * const safeCalculation = (input: unknown) =>
111
- * pipe(input)
112
- * .map(val => typeof val === 'number' ? val : null)
113
- * .mapNullable(n => n > 0 ? n : null) // Positive numbers only
114
- * .mapNullable(n => Math.sqrt(n)) // Safe square root
115
- * .mapNullable(n => n < 100 ? n : null) // Limit result
116
- * .mapNullable(n => Math.round(n * 100) / 100) // Round to 2 decimals
117
- * .value; // number | undefined
103
+ * const maybeNumber: number | undefined = 25;
104
+ * const result = pipe(maybeNumber)
105
+ * .mapNullable(n => n > 0 ? n : undefined) // Positive numbers only
106
+ * .mapNullable(n => Math.sqrt(n)) // Safe square root
107
+ * .mapNullable(n => n < 100 ? n : undefined) // Limit result
108
+ * .mapNullable(n => Math.round(n * 100) / 100) // Round to 2 decimals
109
+ * .value; // number | undefined
110
+ *
111
+ * assert(result === 5); // sqrt(25) = 5
112
+ *
113
+ * const negativeNumber: number | undefined = -5;
114
+ * const negativeResult = pipe(negativeNumber)
115
+ * .mapNullable(n => n > 0 ? n : undefined)
116
+ * .value;
117
+ * assert(negativeResult === undefined); // negative number
118
118
  * ```
119
+ *
119
120
  */
120
121
  export function pipe<const A extends Optional.Base>(
121
122
  a: A,
122
123
  ): PipeWithMapOptional<A>;
123
124
 
124
- export function pipe<const A>(a: A): PipeWithMapNullable<A>;
125
+ export function pipe<const A>(a: A): PipeBase<A>;
125
126
 
126
127
  export function pipe<const A>(a: A): PipeImpl<A> {
127
128
  if (Optional.isOptional(a)) {
@@ -139,6 +140,8 @@ export function pipe<const A>(a: A): PipeImpl<A> {
139
140
  }
140
141
  }
141
142
 
143
+ type Pipe<A> = A extends Optional.Base ? PipeWithMapOptional<A> : PipeBase<A>;
144
+
142
145
  /**
143
146
  * @internal
144
147
  * Base pipe interface providing core functionality.
@@ -154,29 +157,18 @@ type PipeBase<A> = Readonly<{
154
157
  * @param fn Function to transform the current value.
155
158
  * @returns A new pipe containing the transformed value.
156
159
  */
157
- map: <B>(fn: (a: A) => B) => PipeBase<B>;
158
- }>;
160
+ map: <B>(fn: (a: A) => B) => Pipe<B>;
159
161
 
160
- /**
161
- * @internal
162
- * Pipe interface for non-Optional values, providing null-safe mapping.
163
- * Extends PipeBase with mapNullable functionality.
164
- * @template A The type of the current value in the pipe.
165
- */
166
- type PipeWithMapNullable<A> = MergeIntersection<
167
- PipeBase<A> &
168
- Readonly<{
169
- /**
170
- * Maps the current value only if it's not null or undefined.
171
- * If the current value is null/undefined, the transformation is skipped
172
- * and undefined is propagated through the pipe.
173
- * @template B The type of the transformed value.
174
- * @param fn Function to transform the non-null value.
175
- * @returns A new pipe containing the transformed value or undefined.
176
- */
177
- mapNullable: <B>(fn: (a: NonNullable<A>) => B) => PipeBase<B | undefined>;
178
- }>
179
- >;
162
+ /**
163
+ * Maps the current value only if it's not null or undefined.
164
+ * If the current value is null/undefined, the transformation is skipped
165
+ * and undefined is propagated through the pipe.
166
+ * @template B The type of the transformed value.
167
+ * @param fn Function to transform the non-null value.
168
+ * @returns A new pipe containing the transformed value or undefined.
169
+ */
170
+ mapNullable: <B>(fn: (a: NonNullable<A>) => B) => Pipe<B | undefined>;
171
+ }>;
180
172
 
181
173
  /**
182
174
  * @internal
@@ -195,9 +187,7 @@ type PipeWithMapOptional<A extends Optional.Base> = MergeIntersection<
195
187
  * @param fn Function to transform the inner value of the Optional.
196
188
  * @returns A new pipe containing an Optional with the transformed value.
197
189
  */
198
- mapOptional: <B>(
199
- fn: (a: Optional.Unwrap<A>) => B,
200
- ) => PipeBase<Optional<B>>;
190
+ mapOptional: <B>(fn: (a: Optional.Unwrap<A>) => B) => Pipe<Optional<B>>;
201
191
  }>
202
192
  >;
203
193
 
@@ -361,7 +361,7 @@ export namespace Obj {
361
361
  ? TsDataForgeInternals.EntriesToObject<Entries>
362
362
  : TsDataForgeInternals.PartialIfKeyIsUnion<
363
363
  TsDataForgeInternals.KeysOfEntries<Entries>,
364
- Record<
364
+ ReadonlyRecord<
365
365
  TsDataForgeInternals.KeysOfEntries<Entries>,
366
366
  TsDataForgeInternals.ValuesOfEntries<Entries>
367
367
  >