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.
- package/dist/array/array-utils.d.mts +137 -358
- package/dist/array/array-utils.d.mts.map +1 -1
- package/dist/array/array-utils.mjs +191 -1966
- package/dist/array/array-utils.mjs.map +1 -1
- package/dist/array/tuple-utils.d.mts +9 -23
- package/dist/array/tuple-utils.d.mts.map +1 -1
- package/dist/array/tuple-utils.mjs +10 -56
- package/dist/array/tuple-utils.mjs.map +1 -1
- package/dist/collections/imap-mapped.mjs.map +1 -1
- package/dist/collections/imap.mjs.map +1 -1
- package/dist/collections/iset-mapped.mjs.map +1 -1
- package/dist/collections/iset.mjs.map +1 -1
- package/dist/collections/queue.mjs.map +1 -1
- package/dist/collections/stack.mjs.map +1 -1
- package/dist/functional/match.d.mts +2 -33
- package/dist/functional/match.d.mts.map +1 -1
- package/dist/functional/match.mjs +2 -119
- package/dist/functional/match.mjs.map +1 -1
- package/dist/functional/optional.d.mts +34 -197
- package/dist/functional/optional.d.mts.map +1 -1
- package/dist/functional/optional.mjs +40 -312
- package/dist/functional/optional.mjs.map +1 -1
- package/dist/functional/pipe.d.mts +2 -15
- package/dist/functional/pipe.d.mts.map +1 -1
- package/dist/functional/pipe.mjs +2 -110
- package/dist/functional/pipe.mjs.map +1 -1
- package/dist/functional/result.d.mts +18 -209
- package/dist/functional/result.d.mts.map +1 -1
- package/dist/functional/result.mjs +40 -360
- package/dist/functional/result.mjs.map +1 -1
- package/dist/guard/has-key.d.mts +1 -1
- package/dist/guard/has-key.mjs +1 -1
- package/dist/iterator/range.d.mts +2 -6
- package/dist/iterator/range.d.mts.map +1 -1
- package/dist/iterator/range.mjs +2 -93
- package/dist/iterator/range.mjs.map +1 -1
- package/dist/json/json.d.mts +14 -438
- package/dist/json/json.d.mts.map +1 -1
- package/dist/json/json.mjs +14 -438
- package/dist/json/json.mjs.map +1 -1
- package/dist/number/num.d.mts +7 -107
- package/dist/number/num.d.mts.map +1 -1
- package/dist/number/num.mjs +7 -122
- package/dist/number/num.mjs.map +1 -1
- package/dist/number/refined-number-utils.mjs.map +1 -1
- package/dist/object/object.d.mts +4 -10
- package/dist/object/object.d.mts.map +1 -1
- package/dist/object/object.mjs +8 -140
- package/dist/object/object.mjs.map +1 -1
- package/dist/others/map-nullable.d.mts +2 -6
- package/dist/others/map-nullable.d.mts.map +1 -1
- package/dist/others/map-nullable.mjs +2 -146
- package/dist/others/map-nullable.mjs.map +1 -1
- package/dist/others/memoize-function.mjs.map +1 -1
- package/dist/others/unknown-to-string.mjs.map +1 -1
- package/package.json +11 -11
- package/src/array/array-utils.mts +707 -881
- package/src/array/tuple-utils.mts +20 -41
- package/src/functional/match.mts +18 -44
- package/src/functional/optional.mts +93 -248
- package/src/functional/pipe.mts +25 -20
- package/src/functional/result.mts +114 -288
- package/src/guard/has-key.mts +1 -1
- package/src/iterator/range.mts +14 -17
- package/src/json/json.mts +14 -438
- package/src/number/num.mts +20 -113
- package/src/object/object.mts +30 -45
- 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); //
|
|
199
|
+
* const value = Optional.unwrap(some); // 42
|
|
214
200
|
*
|
|
215
|
-
*
|
|
216
|
-
* const
|
|
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
|
|
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
|
-
|
|
236
|
-
<O extends Some<unknown>>(optional: O): Unwrap<O>;
|
|
207
|
+
export function unwrap<O extends Base>(optional: O): Unwrap<O> | undefined;
|
|
237
208
|
|
|
238
|
-
|
|
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
|
|
238
|
+
* // Curried usage
|
|
269
239
|
* const unwrapWithDefault = Optional.unwrapOr("default");
|
|
270
|
-
* const result =
|
|
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
|
|
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
|
|
292
|
-
?
|
|
293
|
-
|
|
294
|
-
|
|
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
|
-
}
|
|
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
|
|
358
|
-
O
|
|
359
|
-
|
|
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
|
-
}
|
|
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
|
-
|
|
425
|
-
|
|
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
|
-
}
|
|
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
|
-
|
|
481
|
-
|
|
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
|
-
}
|
|
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
|
-
|
|
533
|
-
|
|
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
|
-
}
|
|
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
|
-
|
|
589
|
-
|
|
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
|
-
}
|
|
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>(
|
package/src/functional/pipe.mts
CHANGED
|
@@ -117,37 +117,27 @@ type MergeIntersection<T> = {
|
|
|
117
117
|
* .value; // number | undefined
|
|
118
118
|
* ```
|
|
119
119
|
*/
|
|
120
|
-
|
|
121
|
-
|
|
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
|
-
}
|
|
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
|
-
}
|
|
138
|
+
};
|
|
134
139
|
}
|
|
135
|
-
}
|
|
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
|
+
>;
|