@satoshibits/functional 1.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.
Files changed (46) hide show
  1. package/README.md +242 -0
  2. package/dist/array-utils.d.mts +317 -0
  3. package/dist/array-utils.d.mts.map +1 -0
  4. package/dist/array-utils.mjs +370 -0
  5. package/dist/array-utils.mjs.map +1 -0
  6. package/dist/composition.d.mts +603 -0
  7. package/dist/composition.d.mts.map +1 -0
  8. package/dist/composition.mjs +516 -0
  9. package/dist/composition.mjs.map +1 -0
  10. package/dist/object-utils.d.mts +267 -0
  11. package/dist/object-utils.d.mts.map +1 -0
  12. package/dist/object-utils.mjs +258 -0
  13. package/dist/object-utils.mjs.map +1 -0
  14. package/dist/option.d.mts +622 -0
  15. package/dist/option.d.mts.map +1 -0
  16. package/dist/option.mjs +637 -0
  17. package/dist/option.mjs.map +1 -0
  18. package/dist/performance.d.mts +265 -0
  19. package/dist/performance.d.mts.map +1 -0
  20. package/dist/performance.mjs +453 -0
  21. package/dist/performance.mjs.map +1 -0
  22. package/dist/pipeline.d.mts +431 -0
  23. package/dist/pipeline.d.mts.map +1 -0
  24. package/dist/pipeline.mjs +460 -0
  25. package/dist/pipeline.mjs.map +1 -0
  26. package/dist/predicates.d.mts +722 -0
  27. package/dist/predicates.d.mts.map +1 -0
  28. package/dist/predicates.mjs +802 -0
  29. package/dist/predicates.mjs.map +1 -0
  30. package/dist/reader-result.d.mts +422 -0
  31. package/dist/reader-result.d.mts.map +1 -0
  32. package/dist/reader-result.mjs +758 -0
  33. package/dist/reader-result.mjs.map +1 -0
  34. package/dist/result.d.mts +684 -0
  35. package/dist/result.d.mts.map +1 -0
  36. package/dist/result.mjs +814 -0
  37. package/dist/result.mjs.map +1 -0
  38. package/dist/types.d.mts +439 -0
  39. package/dist/types.d.mts.map +1 -0
  40. package/dist/types.mjs +191 -0
  41. package/dist/types.mjs.map +1 -0
  42. package/dist/validation.d.mts +622 -0
  43. package/dist/validation.d.mts.map +1 -0
  44. package/dist/validation.mjs +852 -0
  45. package/dist/validation.mjs.map +1 -0
  46. package/package.json +46 -0
@@ -0,0 +1,622 @@
1
+ /**
2
+ * @module option
3
+ * @description Option/Maybe type for explicit null/undefined handling in a functional way.
4
+ * Provides a safe alternative to nullable values by wrapping them in a container type.
5
+ * Forces explicit handling of edge cases and eliminates null pointer exceptions.
6
+ * Inspired by functional programming languages like Haskell and Rust.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { Option, some, none, fromNullable, map, getOrElse } from './option.mts';
11
+ *
12
+ * // creating options
13
+ * const user = some({ id: '123', name: 'Alice' });
14
+ * const notFound = none();
15
+ * const maybeUser = fromNullable(localStorage.getItem('user'));
16
+ *
17
+ * // transforming values
18
+ * const userName = map((u: User) => u.name)(user);
19
+ *
20
+ * // extracting values safely
21
+ * const name = getOrElse(() => 'Anonymous')(userName);
22
+ *
23
+ * // chaining operations
24
+ * const greeting = pipe(
25
+ * fromNullable(getUserById(id)),
26
+ * map(u => u.name),
27
+ * map(name => `Hello, ${name}!`),
28
+ * getOrElse(() => 'Hello, stranger!')
29
+ * );
30
+ * ```
31
+ *
32
+ * @category Core
33
+ * @since 2025-07-03
34
+ */
35
+ /**
36
+ * Option type representing a value that may or may not exist.
37
+ * @description A discriminated union type that forces explicit handling of null/undefined cases.
38
+ * An Option is either Some<T> (containing a value) or None (representing absence).
39
+ *
40
+ * @template T - The type of the value when present
41
+ *
42
+ * @category Core Types
43
+ * @since 2025-07-03
44
+ */
45
+ export type Option<T> = Some<T> | None;
46
+ /**
47
+ * Represents a value that exists.
48
+ * @description The Some variant of Option, containing a non-null value.
49
+ *
50
+ * @template T - The type of the contained value
51
+ * @property {"Some"} _tag - Discriminant for pattern matching
52
+ * @property {T} value - The contained value
53
+ *
54
+ * @category Core Types
55
+ * @since 2025-07-03
56
+ */
57
+ export interface Some<T> {
58
+ readonly _tag: 'Some';
59
+ readonly value: T;
60
+ }
61
+ /**
62
+ * Represents the absence of a value.
63
+ * @description The None variant of Option, representing no value.
64
+ *
65
+ * @property {"None"} _tag - Discriminant for pattern matching
66
+ *
67
+ * @category Core Types
68
+ * @since 2025-07-03
69
+ */
70
+ export interface None {
71
+ readonly _tag: 'None';
72
+ }
73
+ /**
74
+ * Creates a Some variant containing the provided value.
75
+ * @description Wraps a value in the Some variant of Option.
76
+ * Use this when you have a value that definitely exists.
77
+ *
78
+ * @template T - The type of the value to wrap
79
+ * @param {T} value - The value to wrap in Some
80
+ * @returns {Option<T>} A Some variant containing the value
81
+ *
82
+ * @category Constructors
83
+ * @example
84
+ * const user = some({ id: '123', name: 'Alice' });
85
+ * // => { _tag: 'Some', value: { id: '123', name: 'Alice' } }
86
+ *
87
+ * @example
88
+ * // Wrapping a found value
89
+ * const found = database.find(id);
90
+ * const result = found ? some(found) : none();
91
+ *
92
+ * @example
93
+ * // Creating from non-null assertion
94
+ * const config = getConfig();
95
+ * if (config.apiKey) {
96
+ * return some(config.apiKey);
97
+ * }
98
+ *
99
+ * @see none - Create an empty Option
100
+ * @see fromNullable - Create Option from nullable value
101
+ * @since 2025-07-03
102
+ */
103
+ export declare const some: <T>(value: T) => Option<T>;
104
+ /**
105
+ * Creates a None variant representing no value.
106
+ * @description Creates the None variant of Option, representing absence of value.
107
+ * Use this when you want to explicitly represent "no value" in a type-safe way.
108
+ *
109
+ * @returns {Option<never>} A None variant
110
+ *
111
+ * @category Constructors
112
+ * @example
113
+ * const notFound = none();
114
+ * // => { _tag: 'None' }
115
+ *
116
+ * @example
117
+ * // Representing search miss
118
+ * const user = users.find(u => u.id === targetId);
119
+ * return user ? some(user) : none();
120
+ *
121
+ * @example
122
+ * // Empty configuration
123
+ * const apiKey = process.env.API_KEY;
124
+ * return apiKey ? some(apiKey) : none();
125
+ *
126
+ * @see some - Create an Option with a value
127
+ * @see fromNullable - Create Option from nullable value
128
+ * @since 2025-07-03
129
+ */
130
+ export declare const none: () => Option<never>;
131
+ /**
132
+ * Creates an Option from a nullable value.
133
+ * @description Converts a nullable value into an Option.
134
+ * Returns Some if the value is not null/undefined, None otherwise.
135
+ * This is the primary way to bridge nullable APIs with Option.
136
+ *
137
+ * @template T - The type of the non-null value
138
+ * @param {T | null | undefined} value - The nullable value to convert
139
+ * @returns {Option<T>} Some if value exists, None otherwise
140
+ *
141
+ * @category Constructors
142
+ * @example
143
+ * const maybeUser = fromNullable(localStorage.getItem('user'));
144
+ * // => Some(userData) if exists, None if null
145
+ *
146
+ * @example
147
+ * // Safe property access
148
+ * const email = fromNullable(user?.contact?.email);
149
+ *
150
+ * @example
151
+ * // Array element access
152
+ * const firstItem = fromNullable(items[0]);
153
+ *
154
+ * @see some - Wrap a non-null value
155
+ * @see none - Create an empty Option
156
+ * @since 2025-07-03
157
+ */
158
+ export declare const fromNullable: <T>(value: T | null | undefined) => Option<T>;
159
+ /**
160
+ * Creates an Option from a predicate function.
161
+ * Returns Some if the predicate is true, None otherwise.
162
+ *
163
+ * @category Constructors
164
+ * @example
165
+ * const positive = Option.fromPredicate((n: number) => n > 0);
166
+ * positive(5); // => Some(5)
167
+ * positive(-1); // => None
168
+ *
169
+ * @example
170
+ * // Validation wrapper
171
+ * const validEmail = Option.fromPredicate((s: string) =>
172
+ * /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(s)
173
+ * );
174
+ *
175
+ * @example
176
+ * // Range check
177
+ * const inRange = Option.fromPredicate((n: number) => n >= 0 && n <= 100);
178
+ */
179
+ export declare const fromPredicate: <T>(predicate: (value: T) => boolean) => (value: T) => Option<T>;
180
+ /**
181
+ * Type guard to check if an Option is Some.
182
+ *
183
+ * @category Type Guards
184
+ * @example
185
+ * const opt = Option.fromNullable(getValue());
186
+ * if (Option.isSome(opt)) {
187
+ * console.log(opt.value); // TypeScript knows opt.value exists
188
+ * }
189
+ *
190
+ * @example
191
+ * // Filtering array of options
192
+ * const values = options.filter(Option.isSome).map(opt => opt.value);
193
+ *
194
+ * @example
195
+ * // Early return pattern
196
+ * if (!Option.isSome(result)) {
197
+ * return defaultValue;
198
+ * }
199
+ * return processValue(result.value);
200
+ */
201
+ export declare const isSome: <T>(option: Option<T>) => option is Some<T>;
202
+ /**
203
+ * Type guard to check if an Option is None.
204
+ *
205
+ * @category Type Guards
206
+ * @example
207
+ * const user = findUser(id);
208
+ * if (Option.isNone(user)) {
209
+ * throw new Error('User not found');
210
+ * }
211
+ *
212
+ * @example
213
+ * // Conditional rendering
214
+ * if (Option.isNone(data)) {
215
+ * return <LoadingSpinner />;
216
+ * }
217
+ *
218
+ * @example
219
+ * // Validation check
220
+ * const validated = validate(input);
221
+ * if (Option.isNone(validated)) {
222
+ * return { error: 'Invalid input' };
223
+ * }
224
+ */
225
+ export declare const isNone: <T>(option: Option<T>) => option is None;
226
+ /**
227
+ * Maps a function over the value in Some, does nothing for None.
228
+ *
229
+ * @category Transformations
230
+ * @example
231
+ * const doubled = Option.map((n: number) => n * 2);
232
+ * doubled(Option.some(5)); // => Some(10)
233
+ * doubled(Option.none()); // => None
234
+ *
235
+ * @example
236
+ * // Transform user data
237
+ * const userName = pipe(
238
+ * findUser(id),
239
+ * Option.map(user => user.name),
240
+ * Option.map(name => name.toUpperCase())
241
+ * );
242
+ *
243
+ * @example
244
+ * // Parse and transform
245
+ * const parsed = pipe(
246
+ * Option.fromNullable(jsonString),
247
+ * Option.map(str => JSON.parse(str)),
248
+ * Option.map(data => data.value)
249
+ * );
250
+ */
251
+ export declare const map: <A, B>(fn: (value: A) => B) => (option: Option<A>) => Option<B>;
252
+ /**
253
+ * FlatMaps a function over the value in Some, does nothing for None.
254
+ * Also known as chain or bind in other libraries.
255
+ *
256
+ * @category Transformations
257
+ * @example
258
+ * const safeDivide = (n: number) =>
259
+ * n === 0 ? Option.none() : Option.some(10 / n);
260
+ *
261
+ * const result = pipe(
262
+ * Option.some(5),
263
+ * Option.flatMap(safeDivide)
264
+ * ); // => Some(2)
265
+ *
266
+ * @example
267
+ * // Chaining optional operations
268
+ * const getManager = (employee: Employee) =>
269
+ * Option.fromNullable(employee.managerId)
270
+ * .pipe(Option.flatMap(id => findEmployee(id)));
271
+ *
272
+ * @example
273
+ * // Validation chain
274
+ * const processUser = pipe(
275
+ * parseUser(input),
276
+ * Option.flatMap(validateAge),
277
+ * Option.flatMap(validateEmail)
278
+ * );
279
+ */
280
+ export declare const flatMap: <A, B>(fn: (value: A) => Option<B>) => (option: Option<A>) => Option<B>;
281
+ /**
282
+ * Alias for flatMap - monadic bind operation.
283
+ *
284
+ * @category Transformations
285
+ * @see flatMap
286
+ */
287
+ export declare const chain: <A, B>(fn: (value: A) => Option<B>) => (option: Option<A>) => Option<B>;
288
+ /**
289
+ * Returns the value if Some, otherwise returns the provided default.
290
+ *
291
+ * @category Extractors
292
+ * @example
293
+ * const value = Option.getOrElse(() => 'default')(maybeValue);
294
+ *
295
+ * @example
296
+ * // Configuration with defaults
297
+ * const port = pipe(
298
+ * Option.fromNullable(process.env.PORT),
299
+ * Option.map(parseInt),
300
+ * Option.getOrElse(() => 3000)
301
+ * );
302
+ *
303
+ * @example
304
+ * // User preferences
305
+ * const theme = pipe(
306
+ * getUserPreference('theme'),
307
+ * Option.getOrElse(() => 'light')
308
+ * );
309
+ */
310
+ export declare const getOrElse: <T>(defaultValue: () => T) => (option: Option<T>) => T;
311
+ /**
312
+ * Returns the first Some option, or None if both are None.
313
+ * Useful for fallback chains.
314
+ *
315
+ * @category Combinations
316
+ * @example
317
+ * const config = Option.orElse(
318
+ * () => Option.fromNullable(process.env.API_KEY)
319
+ * )(Option.fromNullable(config.apiKey));
320
+ *
321
+ * @example
322
+ * // Multiple fallbacks
323
+ * const findUser = (id: string) => pipe(
324
+ * findInCache(id),
325
+ * Option.orElse(() => findInDatabase(id)),
326
+ * Option.orElse(() => findInArchive(id))
327
+ * );
328
+ *
329
+ * @example
330
+ * // Try alternative parsing
331
+ * const parsed = pipe(
332
+ * tryParseJSON(input),
333
+ * Option.orElse(() => tryParseYAML(input))
334
+ * );
335
+ */
336
+ export declare const orElse: <T>(alternative: () => Option<T>) => (option: Option<T>) => Option<T>;
337
+ /**
338
+ * Filters the value in Some based on a predicate.
339
+ * Returns None if the predicate is false or if already None.
340
+ * Supports type guard predicates for type refinement.
341
+ *
342
+ * @category Refinements
343
+ * @example
344
+ * const positive = Option.filter((n: number) => n > 0);
345
+ * positive(Option.some(5)); // => Some(5)
346
+ * positive(Option.some(-1)); // => None
347
+ *
348
+ * @example
349
+ * // Type narrowing with type guards
350
+ * const maybeString: Option<string | number> = Option.some(123);
351
+ * const isString = (v: unknown): v is string => typeof v === 'string';
352
+ * const onlyString: Option<string> = pipe(maybeString, Option.filter(isString));
353
+ *
354
+ * @example
355
+ * // User authorization
356
+ * const authorizedUser = pipe(
357
+ * findUser(id),
358
+ * Option.filter(user => user.role === 'admin')
359
+ * );
360
+ *
361
+ * @example
362
+ * // Valid data filtering
363
+ * const validData = pipe(
364
+ * parseData(input),
365
+ * Option.filter(data => data.length > 0),
366
+ * Option.filter(data => data.every(isValid))
367
+ * );
368
+ */
369
+ export declare function filter<T, S extends T>(predicate: (value: T) => value is S): (option: Option<T>) => Option<S>;
370
+ export declare function filter<T>(predicate: (value: T) => boolean): (option: Option<T>) => Option<T>;
371
+ /**
372
+ * Pattern matching for Option types.
373
+ * Provides exhaustive handling of both Some and None cases.
374
+ *
375
+ * @category Pattern Matching
376
+ * @example
377
+ * const message = Option.match({
378
+ * some: (user) => `Hello, ${user.name}!`,
379
+ * none: () => 'Hello, guest!'
380
+ * })(maybeUser);
381
+ *
382
+ * @example
383
+ * // React component rendering
384
+ * const UserProfile = ({ userId }: Props) => {
385
+ * const user = useUser(userId);
386
+ *
387
+ * return Option.match({
388
+ * some: (u) => <Profile user={u} />,
389
+ * none: () => <NotFound />
390
+ * })(user);
391
+ * };
392
+ *
393
+ * @example
394
+ * // API response handling
395
+ * const response = await Option.match({
396
+ * some: async (data) => api.update(data),
397
+ * none: async () => api.create(defaults)
398
+ * })(existingData);
399
+ */
400
+ export declare const match: <T, A, B>(patterns: {
401
+ some: (value: T) => A;
402
+ none: () => B;
403
+ }) => (option: Option<T>) => A | B;
404
+ /**
405
+ * Converts an Option to a nullable value.
406
+ * Some(value) becomes value, None becomes null.
407
+ *
408
+ * @category Conversions
409
+ * @example
410
+ * const value = Option.toNullable(maybeValue);
411
+ * localStorage.setItem('key', value ?? '');
412
+ *
413
+ * @example
414
+ * // Database update
415
+ * const update = {
416
+ * name: Option.toNullable(maybeName),
417
+ * email: Option.toNullable(maybeEmail),
418
+ * phone: Option.toNullable(maybePhone)
419
+ * };
420
+ *
421
+ * @example
422
+ * // JSON serialization
423
+ * const data = {
424
+ * id: user.id,
425
+ * nickname: Option.toNullable(user.nickname)
426
+ * };
427
+ */
428
+ export declare const toNullable: <T>(option: Option<T>) => T | null;
429
+ /**
430
+ * Converts an Option to undefined if None.
431
+ * Some(value) becomes value, None becomes undefined.
432
+ *
433
+ * @category Conversions
434
+ * @example
435
+ * const params = {
436
+ * limit: 10,
437
+ * offset: Option.toUndefined(maybeOffset)
438
+ * };
439
+ *
440
+ * @example
441
+ * // Optional chaining alternative
442
+ * const city = Option.toUndefined(
443
+ * Option.map((addr: Address) => addr.city)(maybeAddress)
444
+ * );
445
+ */
446
+ export declare const toUndefined: <T>(option: Option<T>) => T | undefined;
447
+ /**
448
+ * Creates an Option from a function that might throw an error.
449
+ * Returns Some with the result if the function succeeds, None if it throws.
450
+ *
451
+ * @category Constructors
452
+ * @example
453
+ * const safeParse = (json: string) => Option.tryCatch(() => JSON.parse(json));
454
+ * safeParse('{"a":1}'); // => Some({ a: 1 })
455
+ * safeParse('invalid json'); // => None
456
+ *
457
+ * @example
458
+ * // Safe file parsing
459
+ * const config = Option.tryCatch(() =>
460
+ * JSON.parse(fs.readFileSync('config.json', 'utf8'))
461
+ * );
462
+ *
463
+ * @example
464
+ * // Safe URL parsing
465
+ * const url = Option.tryCatch(() => new URL(input));
466
+ */
467
+ export declare const tryCatch: <T>(fn: () => T) => Option<T>;
468
+ /**
469
+ * Executes a side-effecting function on the value in Some.
470
+ * Returns the original Option unchanged.
471
+ *
472
+ * @category Side Effects
473
+ * @example
474
+ * const logValue = pipe(
475
+ * Option.some(42),
476
+ * Option.tap(value => console.log('Found value:', value))
477
+ * ); // logs "Found value: 42" and returns Some(42)
478
+ *
479
+ * @example
480
+ * // Debug logging in a chain
481
+ * const result = pipe(
482
+ * getUserInput(),
483
+ * Option.tap(input => console.log('Raw input:', input)),
484
+ * Option.map(normalize),
485
+ * Option.tap(normalized => console.log('Normalized:', normalized)),
486
+ * Option.filter(isValid)
487
+ * );
488
+ *
489
+ * @example
490
+ * // Side effects like analytics
491
+ * const trackEvent = pipe(
492
+ * findUser(id),
493
+ * Option.tap(user => analytics.track('user.found', { id: user.id }))
494
+ * );
495
+ */
496
+ export declare const tap: <T>(fn: (value: T) => void) => (option: Option<T>) => Option<T>;
497
+ /**
498
+ * Namespace containing all Option utilities.
499
+ *
500
+ * @category Namespace
501
+ */
502
+ export declare const Option: {
503
+ readonly some: <T>(value: T) => Option<T>;
504
+ readonly none: () => Option<never>;
505
+ readonly fromNullable: <T>(value: T | null | undefined) => Option<T>;
506
+ readonly fromPredicate: <T>(predicate: (value: T) => boolean) => (value: T) => Option<T>;
507
+ readonly tryCatch: <T>(fn: () => T) => Option<T>;
508
+ readonly isSome: <T>(option: Option<T>) => option is Some<T>;
509
+ readonly isNone: <T>(option: Option<T>) => option is None;
510
+ readonly map: <A, B>(fn: (value: A) => B) => (option: Option<A>) => Option<B>;
511
+ readonly flatMap: <A, B>(fn: (value: A) => Option<B>) => (option: Option<A>) => Option<B>;
512
+ readonly chain: <A, B>(fn: (value: A) => Option<B>) => (option: Option<A>) => Option<B>;
513
+ readonly getOrElse: <T>(defaultValue: () => T) => (option: Option<T>) => T;
514
+ readonly orElse: <T>(alternative: () => Option<T>) => (option: Option<T>) => Option<T>;
515
+ readonly filter: typeof filter;
516
+ readonly tap: <T>(fn: (value: T) => void) => (option: Option<T>) => Option<T>;
517
+ readonly match: <T, A, B>(patterns: {
518
+ some: (value: T) => A;
519
+ none: () => B;
520
+ }) => (option: Option<T>) => A | B;
521
+ readonly toNullable: <T>(option: Option<T>) => T | null;
522
+ readonly toUndefined: <T>(option: Option<T>) => T | undefined;
523
+ };
524
+ /**
525
+ * Combines two Options using a binary function.
526
+ * Returns None if either Option is None.
527
+ *
528
+ * @category Combinations
529
+ * @example
530
+ * const add = (a: number, b: number) => a + b;
531
+ * const sum = lift2(add)(Option.some(5), Option.some(3));
532
+ * // => Some(8)
533
+ *
534
+ * @example
535
+ * // Form validation
536
+ * const createUser = (name: string, email: string) => ({ name, email });
537
+ * const validUser = lift2(createUser)(
538
+ * validateName(input.name),
539
+ * validateEmail(input.email)
540
+ * );
541
+ *
542
+ * @example
543
+ * // Coordinate operations
544
+ * const distance = (x: number, y: number) => Math.sqrt(x * x + y * y);
545
+ * const result = lift2(distance)(parseX(input), parseY(input));
546
+ */
547
+ export declare const lift2: <A, B, C>(fn: (a: A, b: B) => C) => (optionA: Option<A>, optionB: Option<B>) => Option<C>;
548
+ /**
549
+ * Sequences an array of Options into an Option of array.
550
+ * Returns Some with all values if all are Some, None if any is None.
551
+ *
552
+ * @category Combinations
553
+ * @example
554
+ * const results = sequence([
555
+ * Option.some(1),
556
+ * Option.some(2),
557
+ * Option.some(3)
558
+ * ]);
559
+ * // => Some([1, 2, 3])
560
+ *
561
+ * @example
562
+ * // Parse multiple values
563
+ * const numbers = sequence(
564
+ * inputs.map(input => parseNumber(input))
565
+ * );
566
+ *
567
+ * @example
568
+ * // Validate all fields
569
+ * const validatedFields = sequence([
570
+ * validateField('name', data.name),
571
+ * validateField('email', data.email),
572
+ * validateField('age', data.age)
573
+ * ]);
574
+ */
575
+ export declare const sequence: <T>(options: Option<T>[]) => Option<T[]>;
576
+ /**
577
+ * Applies a function wrapped in an Option to a value wrapped in an Option.
578
+ *
579
+ * @category Apply
580
+ * @example
581
+ * const addOne = (n: number) => n + 1;
582
+ * const result = ap(Option.some(addOne))(Option.some(5));
583
+ * // => Some(6)
584
+ *
585
+ * @example
586
+ * // Partial application with options
587
+ * const add = (a: number) => (b: number) => a + b;
588
+ * const maybeAdd5 = Option.map(add)(Option.some(5));
589
+ * const result = ap(maybeAdd5)(Option.some(3));
590
+ * // => Some(8)
591
+ */
592
+ export declare const ap: <A, B>(optionFn: Option<(a: A) => B>) => (optionA: Option<A>) => Option<B>;
593
+ /**
594
+ * Sequences a struct of Options into an Option of a struct.
595
+ * Returns Some with the struct of all values if all are Some, None if any is None.
596
+ *
597
+ * @category Combinations
598
+ * @example
599
+ * const result = sequenceS({
600
+ * a: Option.some(1),
601
+ * b: Option.some('hello')
602
+ * });
603
+ * // => Some({ a: 1, b: 'hello' })
604
+ *
605
+ * @example
606
+ * // Form validation
607
+ * const validForm = sequenceS({
608
+ * name: validateName(input.name),
609
+ * email: validateEmail(input.email),
610
+ * age: validateAge(input.age)
611
+ * });
612
+ *
613
+ * @example
614
+ * // Configuration validation
615
+ * const config = sequenceS({
616
+ * apiKey: Option.fromNullable(process.env.API_KEY),
617
+ * port: Option.tryCatch(() => parseInt(process.env.PORT!)),
618
+ * debug: Option.fromNullable(process.env.DEBUG).pipe(Option.map(v => v === 'true'))
619
+ * });
620
+ */
621
+ export declare const sequenceS: <T extends Record<string, Option<unknown>>>(struct: T) => Option<{ [K in keyof T]: T[K] extends Option<infer U> ? U : never; }>;
622
+ //# sourceMappingURL=option.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"option.d.mts","sourceRoot":"","sources":["../src/option.mts"],"names":[],"mappings":"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"}