ts-data-forge 1.5.0 → 1.5.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.
Files changed (68) hide show
  1. package/dist/array/array-utils.d.mts +137 -358
  2. package/dist/array/array-utils.d.mts.map +1 -1
  3. package/dist/array/array-utils.mjs +191 -1966
  4. package/dist/array/array-utils.mjs.map +1 -1
  5. package/dist/array/tuple-utils.d.mts +9 -23
  6. package/dist/array/tuple-utils.d.mts.map +1 -1
  7. package/dist/array/tuple-utils.mjs +10 -56
  8. package/dist/array/tuple-utils.mjs.map +1 -1
  9. package/dist/collections/imap-mapped.mjs.map +1 -1
  10. package/dist/collections/imap.mjs.map +1 -1
  11. package/dist/collections/iset-mapped.mjs.map +1 -1
  12. package/dist/collections/iset.mjs.map +1 -1
  13. package/dist/collections/queue.mjs.map +1 -1
  14. package/dist/collections/stack.mjs.map +1 -1
  15. package/dist/functional/match.d.mts +2 -33
  16. package/dist/functional/match.d.mts.map +1 -1
  17. package/dist/functional/match.mjs +2 -119
  18. package/dist/functional/match.mjs.map +1 -1
  19. package/dist/functional/optional.d.mts +34 -197
  20. package/dist/functional/optional.d.mts.map +1 -1
  21. package/dist/functional/optional.mjs +40 -312
  22. package/dist/functional/optional.mjs.map +1 -1
  23. package/dist/functional/pipe.d.mts +2 -15
  24. package/dist/functional/pipe.d.mts.map +1 -1
  25. package/dist/functional/pipe.mjs +2 -110
  26. package/dist/functional/pipe.mjs.map +1 -1
  27. package/dist/functional/result.d.mts +18 -209
  28. package/dist/functional/result.d.mts.map +1 -1
  29. package/dist/functional/result.mjs +40 -360
  30. package/dist/functional/result.mjs.map +1 -1
  31. package/dist/guard/has-key.d.mts +1 -1
  32. package/dist/guard/has-key.mjs +1 -1
  33. package/dist/iterator/range.d.mts +2 -6
  34. package/dist/iterator/range.d.mts.map +1 -1
  35. package/dist/iterator/range.mjs +2 -93
  36. package/dist/iterator/range.mjs.map +1 -1
  37. package/dist/json/json.d.mts +14 -438
  38. package/dist/json/json.d.mts.map +1 -1
  39. package/dist/json/json.mjs +14 -438
  40. package/dist/json/json.mjs.map +1 -1
  41. package/dist/number/num.d.mts +7 -107
  42. package/dist/number/num.d.mts.map +1 -1
  43. package/dist/number/num.mjs +7 -122
  44. package/dist/number/num.mjs.map +1 -1
  45. package/dist/number/refined-number-utils.mjs.map +1 -1
  46. package/dist/object/object.d.mts +4 -10
  47. package/dist/object/object.d.mts.map +1 -1
  48. package/dist/object/object.mjs +8 -140
  49. package/dist/object/object.mjs.map +1 -1
  50. package/dist/others/map-nullable.d.mts +2 -6
  51. package/dist/others/map-nullable.d.mts.map +1 -1
  52. package/dist/others/map-nullable.mjs +2 -146
  53. package/dist/others/map-nullable.mjs.map +1 -1
  54. package/dist/others/memoize-function.mjs.map +1 -1
  55. package/dist/others/unknown-to-string.mjs.map +1 -1
  56. package/package.json +11 -11
  57. package/src/array/array-utils.mts +707 -881
  58. package/src/array/tuple-utils.mts +20 -41
  59. package/src/functional/match.mts +18 -44
  60. package/src/functional/optional.mts +93 -248
  61. package/src/functional/pipe.mts +25 -20
  62. package/src/functional/result.mts +114 -288
  63. package/src/guard/has-key.mts +1 -1
  64. package/src/iterator/range.mts +14 -17
  65. package/src/json/json.mts +14 -438
  66. package/src/number/num.mts +20 -113
  67. package/src/object/object.mts +30 -45
  68. package/src/others/map-nullable.mts +13 -15
@@ -106,9 +106,6 @@ export namespace Optional {
106
106
  * @example
107
107
  * ```typescript
108
108
  * const someValue = Optional.some(42);
109
- * const someString = Optional.some("hello");
110
- * const someObject = Optional.some({ name: "Alice", age: 30 });
111
- *
112
109
  * console.log(Optional.isSome(someValue)); // true
113
110
  * console.log(Optional.unwrap(someValue)); // 42
114
111
  * ```
@@ -123,9 +120,7 @@ export namespace Optional {
123
120
  * @example
124
121
  * ```typescript
125
122
  * const emptyValue = Optional.none;
126
- *
127
123
  * console.log(Optional.isNone(emptyValue)); // true
128
- * console.log(Optional.unwrap(emptyValue)); // undefined
129
124
  * console.log(Optional.unwrapOr(emptyValue, "default")); // "default"
130
125
  * ```
131
126
  */
@@ -167,14 +162,6 @@ export namespace Optional {
167
162
  * @throws {Error} Error with message "`unwrapThrow()` has failed because it is `None`" if the `Optional` is `Optional.None`.
168
163
  * @example
169
164
  * ```typescript
170
- * // Safe unwrapping when you know the value exists
171
- * const config = loadConfig(); // returns Optional<Config>
172
- * if (Optional.isSome(config)) {
173
- * const value = Optional.unwrapThrow(config); // Safe to unwrap
174
- * console.log(value); // Config object
175
- * }
176
- *
177
- * // Unsafe unwrapping - will throw if empty
178
165
  * const userInput = Optional.some(42);
179
166
  * console.log(Optional.unwrapThrow(userInput)); // 42
180
167
  *
@@ -208,35 +195,23 @@ export namespace Optional {
208
195
  * @returns The contained value if `Optional.Some`, otherwise `undefined`.
209
196
  * @example
210
197
  * ```typescript
211
- * // With Some - guaranteed to return value
212
198
  * const some = Optional.some(42);
213
- * const value = Optional.unwrap(some); // Type: number, Value: 42
199
+ * const value = Optional.unwrap(some); // 42
214
200
  *
215
- * // With general Optional - may return undefined
216
- * const maybeValue: Optional<string> = getOptionalString();
217
- * const result = Optional.unwrap(maybeValue); // Type: string | undefined
218
- *
219
- * // Safe pattern for handling both cases
220
- * const optional = Optional.some("hello");
221
- * const unwrapped = Optional.unwrap(optional);
222
- * if (unwrapped !== undefined) {
223
- * console.log(unwrapped.toUpperCase()); // "HELLO"
224
- * }
201
+ * const none = Optional.none;
202
+ * const result = Optional.unwrap(none); // undefined
225
203
  * ```
226
204
  */
227
- export const unwrap: UnwrapFnOverload = (<O extends Base>(
228
- optional: O,
229
- ): Unwrap<O> | undefined =>
230
- isNone(optional)
231
- ? undefined
232
- : // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
233
- ((optional as NarrowToSome<O>).value as Unwrap<O>)) as UnwrapFnOverload;
205
+ export function unwrap<O extends Some<unknown>>(optional: O): Unwrap<O>;
234
206
 
235
- type UnwrapFnOverload = {
236
- <O extends Some<unknown>>(optional: O): Unwrap<O>;
207
+ export function unwrap<O extends Base>(optional: O): Unwrap<O> | undefined;
237
208
 
238
- <O extends Base>(optional: O): Unwrap<O> | undefined;
239
- };
209
+ export function unwrap<O extends Base>(optional: O): Unwrap<O> | undefined {
210
+ return isSome(optional)
211
+ ? // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
212
+ (optional.value as Unwrap<O>)
213
+ : undefined;
214
+ }
240
215
 
241
216
  /**
242
217
  * Unwraps an `Optional`, returning the contained value or a default value if it's `Optional.None`.
@@ -252,11 +227,6 @@ export namespace Optional {
252
227
  * @example
253
228
  * ```typescript
254
229
  * // Direct usage - most common pattern
255
- * const userAge = Optional.fromNullable(user.age);
256
- * const displayAge = Optional.unwrapOr(userAge, "Unknown");
257
- * console.log(`Age: ${displayAge}`); // "Age: 25" or "Age: Unknown"
258
- *
259
- * // With different Optional types
260
230
  * const some = Optional.some(42);
261
231
  * const value1 = Optional.unwrapOr(some, 0);
262
232
  * console.log(value1); // 42
@@ -265,33 +235,34 @@ export namespace Optional {
265
235
  * const value2 = Optional.unwrapOr(none, 0);
266
236
  * console.log(value2); // 0
267
237
  *
268
- * // Curried usage for functional composition
238
+ * // Curried usage
269
239
  * const unwrapWithDefault = Optional.unwrapOr("default");
270
- * const result = pipe(Optional.some("hello"))
271
- * .map(unwrapWithDefault)
272
- * .value;
240
+ * const result = unwrapWithDefault(Optional.some("hello"));
273
241
  * console.log(result); // "hello"
274
- *
275
- * // Chaining with other Optional operations
276
- * const processValue = (input: string) =>
277
- * pipe(Optional.fromNullable(input))
278
- * .map(Optional.map(s => s.toUpperCase()))
279
- * .map(Optional.unwrapOr("NO INPUT"))
280
- * .value;
281
242
  * ```
282
243
  */
283
- export const unwrapOr: UnwrapOrFnOverload = (<O extends Base, D>(
244
+ export function unwrapOr<O extends Base, D>(
245
+ optional: O,
246
+ defaultValue: D,
247
+ ): D | Unwrap<O>;
248
+
249
+ // Curried version
250
+ export function unwrapOr<S, D>(
251
+ defaultValue: D,
252
+ ): (optional: Optional<S>) => D | S;
253
+
254
+ export function unwrapOr<O extends Base, D>(
284
255
  ...args:
285
256
  | readonly [optional: O, defaultValue: D]
286
257
  | readonly [defaultValue: D]
287
- ): (D | Unwrap<O>) | ((optional: Optional<Unwrap<O>>) => D | Unwrap<O>) => {
258
+ ): (D | Unwrap<O>) | ((optional: Optional<Unwrap<O>>) => D | Unwrap<O>) {
288
259
  switch (args.length) {
289
260
  case 2: {
290
261
  const [optional, defaultValue] = args;
291
- return isNone(optional)
292
- ? defaultValue
293
- : // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
294
- ((optional as NarrowToSome<O>).value as Unwrap<O>);
262
+ return isSome(optional)
263
+ ? // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
264
+ (optional.value as Unwrap<O>)
265
+ : defaultValue;
295
266
  }
296
267
 
297
268
  case 1: {
@@ -301,14 +272,7 @@ export namespace Optional {
301
272
  unwrapOr(optional, defaultValue);
302
273
  }
303
274
  }
304
- }) as UnwrapOrFnOverload;
305
-
306
- type UnwrapOrFnOverload = {
307
- <O extends Base, D>(optional: O, defaultValue: D): D | Unwrap<O>;
308
-
309
- // Curried version
310
- <S, D>(defaultValue: D): (optional: Optional<S>) => D | S;
311
- };
275
+ }
312
276
 
313
277
  /**
314
278
  * Returns the `Optional` if it is `Some`, otherwise returns the alternative.
@@ -323,47 +287,27 @@ export namespace Optional {
323
287
  * @returns The first `Optional` if `Some`, otherwise the alternative.
324
288
  * @example
325
289
  * ```typescript
326
- * // Direct usage - cascading lookups
327
- * const primaryConfig = loadPrimaryConfig(); // Optional<Config>
328
- * const fallbackConfig = loadFallbackConfig(); // Optional<Config>
329
- * const config = Optional.orElse(primaryConfig, fallbackConfig);
330
- *
331
- * // Multiple fallbacks
332
- * const userPreference = getUserPreference(); // Optional<string>
333
- * const systemDefault = Optional.some("default-theme");
334
- * const theme = Optional.orElse(userPreference, systemDefault);
335
- * console.log(Optional.unwrap(theme)); // User's preference or "default-theme"
336
- *
337
- * // Regular usage example
338
290
  * const primary = Optional.none;
339
291
  * const fallback = Optional.some("default");
340
292
  * const result = Optional.orElse(primary, fallback);
341
293
  * console.log(Optional.unwrap(result)); // "default"
342
- *
343
- * // Curried usage for functional composition
344
- * const withFallback = Optional.orElse(Optional.some("fallback"));
345
- * const result2 = pipe(Optional.none)
346
- * .map(withFallback)
347
- * .value;
348
- * console.log(Optional.unwrap(result2)); // "fallback"
349
- *
350
- * // Chaining multiple orElse operations
351
- * const finalResult = pipe(Optional.none)
352
- * .map(Optional.orElse(Optional.none)) // Still none
353
- * .map(Optional.orElse(Optional.some("last resort")))
354
- * .value;
355
294
  * ```
356
295
  */
357
- export const orElse: OrElseFnOverload = (<
358
- O extends Base,
359
- const O2 extends Base,
360
- >(
296
+ export function orElse<O extends Base, const O2 extends Base>(
297
+ optional: O,
298
+ alternative: O2,
299
+ ): O | O2;
300
+
301
+ // Curried version
302
+ export function orElse<S, S2>(
303
+ alternative: Optional<S2>,
304
+ ): (optional: Optional<S>) => Optional<S> | Optional<S2>;
305
+
306
+ export function orElse<O extends Base, const O2 extends Base>(
361
307
  ...args:
362
308
  | readonly [optional: O, alternative: O2]
363
309
  | readonly [alternative: O2]
364
- ):
365
- | (O | O2)
366
- | ((optional: Optional<Unwrap<O>>) => Optional<Unwrap<O>> | O2) => {
310
+ ): (O | O2) | ((optional: Optional<Unwrap<O>>) => Optional<Unwrap<O>> | O2) {
367
311
  switch (args.length) {
368
312
  case 2: {
369
313
  const [optional, alternative] = args;
@@ -375,19 +319,7 @@ export namespace Optional {
375
319
  return (optional: Optional<Unwrap<O>>) => orElse(optional, alternative);
376
320
  }
377
321
  }
378
- }) as OrElseFnOverload;
379
-
380
- type OrElseFnOverload = {
381
- <O extends Base, const O2 extends Base>(
382
- optional: O,
383
- alternative: O2,
384
- ): O | O2;
385
-
386
- // Curried version
387
- <S, S2>(
388
- alternative: Optional<S2>,
389
- ): (optional: Optional<S>) => Optional<S> | Optional<S2>;
390
- };
322
+ }
391
323
 
392
324
  /**
393
325
  * Maps an {@link Optional}<S> to {@link Optional}<S2> by applying a function to a contained value.
@@ -407,26 +339,23 @@ export namespace Optional {
407
339
  * const noneValue = Optional.none;
408
340
  * const mappedNone = Optional.map(noneValue, x => x * 2);
409
341
  * console.log(Optional.isNone(mappedNone)); // true
410
- *
411
- * // Chaining maps
412
- * const result = Optional.map(
413
- * Optional.map(Optional.some("hello"), s => s.toUpperCase()),
414
- * s => s.length
415
- * );
416
- * console.log(Optional.unwrap(result)); // 5
417
- *
418
- * // Curried version for use with pipe
419
- * const doubler = Optional.map((x: number) => x * 2);
420
- * const result2 = pipe(Optional.some(5)).map(doubler).value;
421
- * console.log(Optional.unwrap(result2)); // 10
422
342
  * ```
423
343
  */
424
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
425
- export const map: MapFnOverload = (<O extends Base, S2>(
344
+ export function map<O extends Base, S2>(
345
+ optional: O,
346
+ mapFn: (value: Unwrap<O>) => S2,
347
+ ): Optional<S2>;
348
+
349
+ // Curried version
350
+ export function map<S, S2>(
351
+ mapFn: (value: S) => S2,
352
+ ): (optional: Optional<S>) => Optional<S2>;
353
+
354
+ export function map<O extends Base, S2>(
426
355
  ...args:
427
356
  | readonly [optional: O, mapFn: (value: Unwrap<O>) => S2]
428
357
  | readonly [mapFn: (value: Unwrap<O>) => S2]
429
- ): Optional<S2> | ((optional: O) => Optional<S2>) => {
358
+ ): Optional<S2> | ((optional: O) => Optional<S2>) {
430
359
  switch (args.length) {
431
360
  case 2: {
432
361
  const [optional, mapFn] = args;
@@ -439,17 +368,7 @@ export namespace Optional {
439
368
  return (optional: O) => map(optional, mapFn);
440
369
  }
441
370
  }
442
- }) as MapFnOverload;
443
-
444
- type MapFnOverload = {
445
- <O extends Base, S2>(
446
- optional: O,
447
- mapFn: (value: Unwrap<O>) => S2,
448
- ): Optional<S2>;
449
-
450
- // Curried version
451
- <S, S2>(mapFn: (value: S) => S2): (optional: Optional<S>) => Optional<S2>;
452
- };
371
+ }
453
372
 
454
373
  /**
455
374
  * Applies a function that returns an `Optional` to the value in an `Optional.Some`.
@@ -462,7 +381,6 @@ export namespace Optional {
462
381
  * @returns The result of applying the function, or `Optional.None`.
463
382
  * @example
464
383
  * ```typescript
465
- * // Regular usage
466
384
  * const parseNumber = (s: string): Optional<number> => {
467
385
  * const n = Number(s);
468
386
  * return isNaN(n) ? Optional.none : Optional.some(n);
@@ -470,19 +388,23 @@ export namespace Optional {
470
388
  *
471
389
  * const result = Optional.flatMap(Optional.some("42"), parseNumber);
472
390
  * console.log(Optional.unwrap(result)); // 42
473
- *
474
- * // Curried usage for pipe composition
475
- * const parser = Optional.flatMap(parseNumber);
476
- * const result2 = pipe(Optional.some("42")).map(parser).value;
477
- * console.log(Optional.unwrap(result2)); // 42
478
391
  * ```
479
392
  */
480
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
481
- export const flatMap: FlatMapFnOverload = (<O extends Base, S2>(
393
+ export function flatMap<O extends Base, S2>(
394
+ optional: O,
395
+ flatMapFn: (value: Unwrap<O>) => Optional<S2>,
396
+ ): Optional<S2>;
397
+
398
+ // Curried version
399
+ export function flatMap<S, S2>(
400
+ flatMapFn: (value: S) => Optional<S2>,
401
+ ): (optional: Optional<S>) => Optional<S2>;
402
+
403
+ export function flatMap<O extends Base, S2>(
482
404
  ...args:
483
405
  | readonly [optional: O, flatMapFn: (value: Unwrap<O>) => Optional<S2>]
484
406
  | readonly [flatMapFn: (value: Unwrap<O>) => Optional<S2>]
485
- ): Optional<S2> | ((optional: O) => Optional<S2>) => {
407
+ ): Optional<S2> | ((optional: O) => Optional<S2>) {
486
408
  switch (args.length) {
487
409
  case 2: {
488
410
  const [optional, flatMapFn] = args;
@@ -494,19 +416,7 @@ export namespace Optional {
494
416
  return (optional: O) => flatMap(optional, flatMapFn);
495
417
  }
496
418
  }
497
- }) as FlatMapFnOverload;
498
-
499
- type FlatMapFnOverload = {
500
- <O extends Base, S2>(
501
- optional: O,
502
- flatMapFn: (value: Unwrap<O>) => Optional<S2>,
503
- ): Optional<S2>;
504
-
505
- // Curried version
506
- <S, S2>(
507
- flatMapFn: (value: S) => Optional<S2>,
508
- ): (optional: Optional<S>) => Optional<S2>;
509
- };
419
+ }
510
420
 
511
421
  /**
512
422
  * Filters an `Optional` based on a predicate.
@@ -518,23 +428,26 @@ export namespace Optional {
518
428
  * @returns The filtered `Optional`.
519
429
  * @example
520
430
  * ```typescript
521
- * // Regular usage
522
431
  * const someEven = Optional.some(4);
523
432
  * const filtered = Optional.filter(someEven, x => x % 2 === 0);
524
433
  * console.log(Optional.unwrap(filtered)); // 4
525
- *
526
- * // Curried usage for pipe composition
527
- * const evenFilter = Optional.filter((x: number) => x % 2 === 0);
528
- * const result = pipe(Optional.some(4)).map(evenFilter).value;
529
- * console.log(Optional.unwrap(result)); // 4
530
434
  * ```
531
435
  */
532
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
533
- export const filter: FilterFnOverload = (<O extends Base>(
436
+ export function filter<O extends Base>(
437
+ optional: O,
438
+ predicate: (value: Unwrap<O>) => boolean,
439
+ ): Optional<Unwrap<O>>;
440
+
441
+ // Curried version
442
+ export function filter<S>(
443
+ predicate: (value: S) => boolean,
444
+ ): (optional: Optional<S>) => Optional<S>;
445
+
446
+ export function filter<O extends Base>(
534
447
  ...args:
535
448
  | readonly [optional: O, predicate: (value: Unwrap<O>) => boolean]
536
449
  | readonly [predicate: (value: Unwrap<O>) => boolean]
537
- ): Optional<Unwrap<O>> | ((optional: O) => Optional<Unwrap<O>>) => {
450
+ ): Optional<Unwrap<O>> | ((optional: O) => Optional<Unwrap<O>>) {
538
451
  switch (args.length) {
539
452
  case 2: {
540
453
  const [optional, predicate] = args;
@@ -551,19 +464,7 @@ export namespace Optional {
551
464
  return (optional: O) => filter(optional, predicate);
552
465
  }
553
466
  }
554
- }) as FilterFnOverload;
555
-
556
- type FilterFnOverload = {
557
- <O extends Base>(
558
- optional: O,
559
- predicate: (value: Unwrap<O>) => boolean,
560
- ): Optional<Unwrap<O>>;
561
-
562
- // Curried version
563
- <S>(
564
- predicate: (value: S) => boolean,
565
- ): (optional: Optional<S>) => Optional<S>;
566
- };
467
+ }
567
468
 
568
469
  /**
569
470
  * Unwraps an `Optional`, returning the contained value or throwing an error with the provided message.
@@ -574,23 +475,24 @@ export namespace Optional {
574
475
  * @throws Error with the provided message if the `Optional` is `Optional.None`.
575
476
  * @example
576
477
  * ```typescript
577
- * // Regular usage
578
478
  * const some = Optional.some(42);
579
479
  * const value = Optional.expectToBe(some, "Value must exist");
580
480
  * console.log(value); // 42
581
- *
582
- * // Curried usage for pipe composition
583
- * const getValue = Optional.expectToBe("Value must exist");
584
- * const value2 = pipe(Optional.some(42)).map(getValue).value;
585
- * console.log(value2); // 42
586
481
  * ```
587
482
  */
588
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
589
- export const expectToBe: ExpectToBeFnOverload = (<O extends Base>(
483
+ export function expectToBe<O extends Base>(
484
+ optional: O,
485
+ message: string,
486
+ ): Unwrap<O>;
487
+
488
+ // Curried version
489
+ export function expectToBe<S>(message: string): (optional: Optional<S>) => S;
490
+
491
+ export function expectToBe<O extends Base>(
590
492
  ...args:
591
493
  | readonly [optional: O, message: string]
592
494
  | readonly [message: string]
593
- ): Unwrap<O> | ((optional: Optional<Unwrap<O>>) => Unwrap<O>) => {
495
+ ): Unwrap<O> | ((optional: Optional<Unwrap<O>>) => Unwrap<O>) {
594
496
  switch (args.length) {
595
497
  case 2: {
596
498
  const [optional, message] = args;
@@ -607,14 +509,7 @@ export namespace Optional {
607
509
  expectToBe(optional, message);
608
510
  }
609
511
  }
610
- }) as ExpectToBeFnOverload;
611
-
612
- type ExpectToBeFnOverload = {
613
- <O extends Base>(optional: O, message: string): Unwrap<O>;
614
-
615
- // Curried version
616
- <S>(message: string): (optional: Optional<S>) => S;
617
- };
512
+ }
618
513
 
619
514
  /**
620
515
  * Combines two `Optional` values into a single `Optional` containing a tuple.
@@ -655,39 +550,13 @@ export namespace Optional {
655
550
  * @returns `Optional.Some<NonNullable<T>>` if the value is not null or undefined, otherwise `Optional.None`.
656
551
  * @example
657
552
  * ```typescript
658
- * // Basic nullable conversion
659
553
  * const value: string | null = "hello";
660
554
  * const optional = Optional.fromNullable(value);
661
555
  * console.log(Optional.unwrap(optional)); // "hello"
662
- * console.log(Optional.isSome(optional)); // true
663
556
  *
664
- * // Handling null values
665
557
  * const nullValue: string | null = null;
666
558
  * const noneOptional = Optional.fromNullable(nullValue);
667
559
  * console.log(Optional.isNone(noneOptional)); // true
668
- *
669
- * // Handling undefined values
670
- * const undefinedValue: number | undefined = undefined;
671
- * const alsoNone = Optional.fromNullable(undefinedValue);
672
- * console.log(Optional.isNone(alsoNone)); // true
673
- *
674
- * // Common use case with API responses
675
- * interface User {
676
- * name: string;
677
- * email?: string; // Optional field
678
- * }
679
- *
680
- * const user: User = { name: "John" };
681
- * const email = Optional.fromNullable(user.email);
682
- * const emailDisplay = Optional.unwrapOr(email, "No email provided");
683
- * console.log(emailDisplay); // "No email provided"
684
- *
685
- * // Chaining with other Optional operations
686
- * const processNullableInput = (input: string | null) =>
687
- * Optional.fromNullable(input)
688
- * .map(Optional.map(s => s.trim()))
689
- * .map(Optional.filter(s => s.length > 0))
690
- * .map(Optional.unwrapOr("empty input"));
691
560
  * ```
692
561
  */
693
562
  export const fromNullable = <T,>(
@@ -709,35 +578,11 @@ export namespace Optional {
709
578
  * @returns The contained value if `Some`, otherwise `undefined`.
710
579
  * @example
711
580
  * ```typescript
712
- * // Basic conversion
713
581
  * const some = Optional.some(42);
714
582
  * console.log(Optional.toNullable(some)); // 42
715
583
  *
716
584
  * const none = Optional.none;
717
585
  * console.log(Optional.toNullable(none)); // undefined
718
- *
719
- * // Interface with nullable APIs
720
- * interface ApiResponse {
721
- * data?: string;
722
- * }
723
- *
724
- * const optionalData: Optional<string> = processData();
725
- * const response: ApiResponse = {
726
- * data: Optional.toNullable(optionalData)
727
- * };
728
- *
729
- * // Converting back and forth
730
- * const original: string | undefined = getValue();
731
- * const optional = Optional.fromNullable(original);
732
- * const processed = Optional.map(optional, s => s.toUpperCase());
733
- * const result: string | undefined = Optional.toNullable(processed);
734
- *
735
- * // Useful in conditional logic
736
- * const maybeUser = findUser(id);
737
- * const userName = Optional.toNullable(maybeUser);
738
- * if (userName !== undefined) {
739
- * console.log(`Found user: ${userName}`);
740
- * }
741
586
  * ```
742
587
  */
743
588
  export const toNullable = <O extends Base>(
@@ -117,37 +117,27 @@ type MergeIntersection<T> = {
117
117
  * .value; // number | undefined
118
118
  * ```
119
119
  */
120
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
121
- export const pipe: PipeFnOverload = (<const A,>(a: A) => {
120
+ export function pipe<const A extends Optional.Base>(
121
+ a: A,
122
+ ): PipeWithMapOptional<A>;
123
+
124
+ export function pipe<const A>(a: A): PipeWithMapNullable<A>;
125
+
126
+ export function pipe<const A>(a: A): PipeImpl<A> {
122
127
  if (Optional.isOptional(a)) {
123
128
  return {
124
129
  value: a,
125
130
  map: (fn) => pipe(fn(a)),
126
131
  mapOptional: (fn) => pipe(Optional.map(a, fn)),
127
- } satisfies PipeWithMapOptional<Optional.Base>;
132
+ };
128
133
  } else {
129
134
  return {
130
135
  value: a,
131
136
  map: (fn) => pipe(fn(a)),
132
137
  mapNullable: (fn) => pipe(a == null ? undefined : fn(a)),
133
- } satisfies PipeWithMapNullable<A>;
138
+ };
134
139
  }
135
- }) as PipeFnOverload;
136
-
137
- /**
138
- * @internal
139
- * Overloaded function type for the pipe function.
140
- * Automatically selects the appropriate pipe type based on input:
141
- * - Optional types get PipeWithMapOptional
142
- * - All other types get PipeWithMapNullable
143
- * @template A The type of value being piped.
144
- */
145
- type PipeFnOverload = {
146
- /** Creates a pipe for Optional values with mapOptional support. */
147
- <const A extends Optional.Base>(a: A): PipeWithMapOptional<A>;
148
- /** Creates a pipe for any other value type with mapNullable support. */
149
- <const A>(a: A): PipeWithMapNullable<A>;
150
- };
140
+ }
151
141
 
152
142
  /**
153
143
  * @internal
@@ -210,3 +200,18 @@ type PipeWithMapOptional<A extends Optional.Base> = MergeIntersection<
210
200
  ) => PipeBase<Optional<B>>;
211
201
  }>
212
202
  >;
203
+
204
+ /** @internal */
205
+ type Cast<T, U> = T & U;
206
+
207
+ /** @internal */
208
+ type PipeImpl<A> = Partial<
209
+ Readonly<{
210
+ value: A;
211
+ map: <B>(fn: (a: A) => B) => PipeBase<B>;
212
+ mapNullable: <B>(fn: (a: NonNullable<A>) => B) => PipeBase<B | undefined>;
213
+ mapOptional: <B>(
214
+ fn: (a: Optional.Unwrap<Cast<A, Optional.Base>>) => B,
215
+ ) => PipeBase<Optional<B>>;
216
+ }>
217
+ >;