functype 0.8.84 → 0.9.0

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/index.d.ts CHANGED
@@ -1,16 +1,15 @@
1
1
  import { Brand } from './branded/index.js';
2
2
  export { BrandedBoolean, BrandedNumber, BrandedString, ExtractBrand, Unbrand, createBrander, hasBrand, unbrand } from './branded/index.js';
3
- import { O as Option, E as Either, F as Foldable, L as List, A as AsyncMonad, T as Traversable, a as FunctypeBase, b as Extractable, P as Pipe, S as Serializable, M as Matchable } from './Either-CncND8cm.js';
4
- export { s as Applicative, C as Collection, q as CollectionOps, r as ContainerOps, u as Functor, j as Functype, k as FunctypeCollection, d as Left, l as MatchableUtils, v as Monad, N as None, n as OptionConstructor, R as Right, o as SerializationMethods, p as Set, m as Some, c as TestEither, g as TypeCheckLeft, f as TypeCheckRight, e as isLeft, i as isRight, t as tryCatch, h as tryCatchAsync } from './Either-CncND8cm.js';
5
- import { T as Type, a as Typeable } from './Typeable-BBXrKPTY.js';
6
- export { E as ExtractTag, b as TypeableParams, i as isTypeable } from './Typeable-BBXrKPTY.js';
3
+ import { O as Option, E as Either, L as List, F as FunctypeBase, a as Extractable, T as Traversable, M as Matchable } from './Either-C-PDWX2U.js';
4
+ export { A as Applicative, p as AsyncMonad, C as Collection, n as CollectionOps, o as ContainerOps, q as Functor, h as Functype, j as FunctypeCollection, c as Left, k as MatchableUtils, r as Monad, N as None, l as OptionConstructor, R as Right, m as Set, S as Some, b as TestEither, f as TypeCheckLeft, e as TypeCheckRight, d as isLeft, i as isRight, t as tryCatch, g as tryCatchAsync } from './Either-C-PDWX2U.js';
5
+ import { T as Type, a as Typeable, F as Foldable, P as Pipe, S as Serializable } from './Serializable-D9GKEo30.js';
6
+ export { E as ExtractTag, b as SerializationMethods, c as TypeableParams, i as isTypeable } from './Serializable-D9GKEo30.js';
7
7
  import { FPromise } from './fpromise/index.js';
8
8
  export { ErrorContext, FPromiseCompanion } from './fpromise/index.js';
9
9
  import { Try } from './try/index.js';
10
10
  export { TypeNames } from './try/index.js';
11
11
  export { Map, SafeTraversable } from './map/index.js';
12
- import { V as Valuable } from './Tuple-ZYh96cGE.js';
13
- export { T as Tuple, a as ValuableParams } from './Tuple-ZYh96cGE.js';
12
+ export { Tuple } from './tuple/index.js';
14
13
 
15
14
  /**
16
15
  * A brand with runtime validation
@@ -276,11 +275,30 @@ declare const Cond: (<T extends Type>() => Cond<T>) & {
276
275
  lazy: <T extends Type>() => LazyCondChain<T>;
277
276
  };
278
277
 
278
+ /**
279
+ * Type-level utilities for exhaustiveness checking
280
+ */
281
+ type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
282
+ type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;
283
+ type RequireExhaustive<T, Cases> = IsUnion<T> extends true ? (keyof Cases extends T ? (T extends keyof Cases ? Cases : never) : never) : Cases;
284
+ /**
285
+ * Pattern types for nested matching
286
+ */
287
+ type Pattern<T> = T | {
288
+ [K in keyof T]?: Pattern<T[K]>;
289
+ } | ((value: T) => boolean) | {
290
+ _: (value: T) => boolean;
291
+ };
292
+ /**
293
+ * Extract result from pattern
294
+ */
295
+ type PatternResult<T, R> = R | ((matched: T) => R);
279
296
  /**
280
297
  * Pattern matching construct similar to Scala's match expressions.
281
- * Enforces exhaustive matching and returns values.
298
+ * Supports exhaustive matching, nested patterns, and guards.
282
299
  *
283
300
  * @example
301
+ * // Basic pattern matching
284
302
  * const result = Match(value)
285
303
  * .case(x => x > 100, "large")
286
304
  * .case(x => x > 50, "medium")
@@ -293,31 +311,57 @@ declare const Cond: (<T extends Type>() => Cond<T>) & {
293
311
  * .caseValue("success", "Completed!")
294
312
  * .caseValue("error", "Failed")
295
313
  * .default("Unknown")
314
+ *
315
+ * @example
316
+ * // Nested pattern matching
317
+ * const user = { name: "John", age: 30, role: "admin" }
318
+ * const msg = Match(user)
319
+ * .case({ role: "admin", age: n => n >= 18 }, "Adult admin")
320
+ * .case({ role: "user" }, u => `User: ${u.name}`)
321
+ * .default("Guest")
296
322
  */
297
323
  type Match<T extends Type, R extends Type> = {
298
324
  /**
299
- * Add a case with a predicate
325
+ * Match against a pattern (value, nested object, or predicate)
300
326
  */
301
- case: (predicate: (value: T) => boolean, result: R | ((value: T) => R)) => Match<T, R>;
327
+ case: (pattern: Pattern<T>, result: PatternResult<T, R>) => Match<T, R>;
302
328
  /**
303
- * Add a case that matches a specific value
329
+ * Add a case that matches a specific value (backward compatibility)
304
330
  */
305
331
  caseValue: (match: T, result: R | (() => R)) => Match<T, R>;
306
332
  /**
307
- * Add a case that matches multiple values
333
+ * Add a case that matches multiple values (backward compatibility)
308
334
  */
309
335
  caseValues: (matches: T[], result: R | (() => R)) => Match<T, R>;
310
336
  /**
311
- * Default case - required to get result
337
+ * Match with a guard function (alias for readability)
338
+ */
339
+ when: (guard: (value: T) => boolean, result: PatternResult<T, R>) => Match<T, R>;
340
+ /**
341
+ * Match multiple patterns (OR operation)
312
342
  */
313
- default: (result: R | ((value: T) => R)) => R;
343
+ caseAny: (patterns: Pattern<T>[], result: PatternResult<T, R>) => Match<T, R>;
314
344
  /**
315
- * Get result if a case matched, throws if no match
345
+ * Default case - makes match non-exhaustive
316
346
  */
317
- getOrThrow: () => R;
347
+ default: (result: PatternResult<T, R>) => R;
348
+ /**
349
+ * Force exhaustive matching (compile-time check for union types)
350
+ */
351
+ exhaustive: () => R;
352
+ /**
353
+ * Get result if matched, throws if no match
354
+ */
355
+ getOrThrow: (errorMessage?: string) => R;
356
+ /**
357
+ * Get result wrapped in Option
358
+ */
359
+ toOption: () => Option<R>;
318
360
  };
319
361
  /**
320
- * Pattern matching utility for type-safe conditional logic
362
+ * Pattern matching utility for type-safe conditional logic with exhaustiveness checking,
363
+ * nested patterns, and guard support
364
+ *
321
365
  * @example
322
366
  * // Basic pattern matching
323
367
  * const result = Match(value)
@@ -335,12 +379,24 @@ type Match<T extends Type, R extends Type> = {
335
379
  * })(color)
336
380
  *
337
381
  * @example
338
- * // Partial matching with default
339
- * const name = Match.partial<number, string>({
340
- * 1: "one",
341
- * 2: "two",
342
- * 3: "three"
343
- * }).withDefault(n => `number ${n}`)(value)
382
+ * // Nested pattern matching
383
+ * type User = { name: string; age: number; role: "admin" | "user" }
384
+ * const user: User = { name: "John", age: 30, role: "admin" }
385
+ *
386
+ * const message = Match<User, string>(user)
387
+ * .case({ role: "admin", age: (n) => n >= 18 }, "Adult admin")
388
+ * .case({ role: "user" }, u => `User: ${u.name}`)
389
+ * .default("Unknown")
390
+ *
391
+ * @example
392
+ * // Using exhaustive() method
393
+ * type Status = "idle" | "loading" | "success" | "error"
394
+ * const result = Match<Status, string>("success")
395
+ * .case("idle", "Waiting...")
396
+ * .case("loading", "Loading...")
397
+ * .case("success", "Done!")
398
+ * .case("error", "Failed!")
399
+ * .exhaustive()
344
400
  */
345
401
  declare const Match: (<T extends Type, R extends Type>(value: T) => Match<T, R>) & {
346
402
  /**
@@ -366,7 +422,7 @@ declare const Match: (<T extends Type, R extends Type>(value: T) => Match<T, R>)
366
422
  * const compute = ops("multiply").fn
367
423
  * const result = compute(4, 5) // 20
368
424
  */
369
- exhaustive: <T extends string | number | symbol, R extends Type>(cases: Record<T, R>) => (value: T) => R;
425
+ exhaustive: <T extends string | number | symbol, R extends Type>(cases: RequireExhaustive<T, Record<T, R>>) => (value: T) => R;
370
426
  /**
371
427
  * Create a partial match that requires a default
372
428
  * @example
@@ -417,6 +473,46 @@ declare const Match: (<T extends Type, R extends Type>(value: T) => Match<T, R>)
417
473
  withGuards: <T extends Type, R extends Type>(guards: Array<[(value: T) => boolean, R | ((value: T) => R)]>) => {
418
474
  withDefault: (defaultValue: R | ((value: T) => R)) => (value: T) => R;
419
475
  };
476
+ /**
477
+ * Pattern matching for objects with specific structure
478
+ * @example
479
+ * type Event =
480
+ * | { type: "click"; x: number; y: number }
481
+ * | { type: "keypress"; key: string }
482
+ * | { type: "hover"; element: string }
483
+ *
484
+ * const handler = Match.struct<Event, void>()
485
+ * .case({ type: "click" }, (e) => console.log(`Click at ${e.x}, ${e.y}`))
486
+ * .case({ type: "keypress", key: "Enter" }, () => console.log("Enter pressed"))
487
+ * .case({ type: "hover" }, (e) => console.log(`Hovering over ${e.element}`))
488
+ * .build()
489
+ */
490
+ struct: <T extends Type, R extends Type>() => {
491
+ case: (pattern: Pattern<T>, handler: (value: T) => R) => /*elided*/ any;
492
+ build: () => (value: T) => R;
493
+ };
494
+ /**
495
+ * Create a pattern matcher with guards and nested patterns
496
+ * @example
497
+ * type User = {
498
+ * name: string
499
+ * age: number
500
+ * permissions: string[]
501
+ * }
502
+ *
503
+ * const canAccess = Match.builder<User, boolean>()
504
+ * .when(u => u.permissions.includes("admin"), true)
505
+ * .case({ age: n => n >= 18, permissions: p => p.length > 0 }, true)
506
+ * .default(false)
507
+ * .build()
508
+ */
509
+ builder: <T extends Type, R extends Type>() => {
510
+ case: (pattern: Pattern<T>, result: PatternResult<T, R>) => /*elided*/ any;
511
+ when: (guard: (value: T) => boolean, result: PatternResult<T, R>) => /*elided*/ any;
512
+ default: (result: PatternResult<T, R>) => {
513
+ build: () => (value: T) => R;
514
+ };
515
+ };
420
516
  };
421
517
 
422
518
  /**
@@ -721,6 +817,356 @@ type ParseError = Error & {
721
817
  name: "ParseError";
722
818
  };
723
819
 
820
+ /**
821
+ * Type-safe error codes using template literal types
822
+ */
823
+ type ErrorCode = "VALIDATION_FAILED" | "NETWORK_ERROR" | "AUTH_REQUIRED" | "NOT_FOUND" | "PERMISSION_DENIED" | "RATE_LIMITED" | "INTERNAL_ERROR" | "BAD_REQUEST" | "CONFLICT" | "TIMEOUT";
824
+ /**
825
+ * Template literal type for error messages based on error code
826
+ */
827
+ type ErrorMessage<T extends ErrorCode> = T extends "VALIDATION_FAILED" ? `Validation failed: ${string}` : T extends "NETWORK_ERROR" ? `Network error: ${string}` : T extends "AUTH_REQUIRED" ? `Authentication required: ${string}` : T extends "NOT_FOUND" ? `Not found: ${string}` : T extends "PERMISSION_DENIED" ? `Permission denied: ${string}` : T extends "RATE_LIMITED" ? `Rate limit exceeded: ${string}` : T extends "INTERNAL_ERROR" ? `Internal server error: ${string}` : T extends "BAD_REQUEST" ? `Bad request: ${string}` : T extends "CONFLICT" ? `Conflict: ${string}` : T extends "TIMEOUT" ? `Request timeout: ${string}` : never;
828
+ /**
829
+ * HTTP status codes mapped to error codes
830
+ */
831
+ type ErrorStatus<T extends ErrorCode> = T extends "VALIDATION_FAILED" | "BAD_REQUEST" ? 400 : T extends "AUTH_REQUIRED" ? 401 : T extends "PERMISSION_DENIED" ? 403 : T extends "NOT_FOUND" ? 404 : T extends "CONFLICT" ? 409 : T extends "RATE_LIMITED" ? 429 : T extends "TIMEOUT" ? 408 : T extends "INTERNAL_ERROR" ? 500 : T extends "NETWORK_ERROR" ? 503 : 500;
832
+ /**
833
+ * Context type for each error code
834
+ */
835
+ type TypedErrorContext<T extends ErrorCode> = T extends "VALIDATION_FAILED" ? {
836
+ field: string;
837
+ value: unknown;
838
+ rule: string;
839
+ } : T extends "NETWORK_ERROR" ? {
840
+ url: string;
841
+ method: string;
842
+ statusCode?: number;
843
+ } : T extends "AUTH_REQUIRED" ? {
844
+ resource: string;
845
+ requiredRole?: string;
846
+ } : T extends "NOT_FOUND" ? {
847
+ resource: string;
848
+ id: string | number;
849
+ } : T extends "PERMISSION_DENIED" ? {
850
+ action: string;
851
+ resource: string;
852
+ userId?: string;
853
+ } : T extends "RATE_LIMITED" ? {
854
+ limit: number;
855
+ window: string;
856
+ retryAfter?: number;
857
+ } : T extends "INTERNAL_ERROR" ? {
858
+ errorId: string;
859
+ timestamp: string;
860
+ } : T extends "BAD_REQUEST" ? {
861
+ reason: string;
862
+ expected?: string;
863
+ } : T extends "CONFLICT" ? {
864
+ resource: string;
865
+ conflictingValue: string;
866
+ } : T extends "TIMEOUT" ? {
867
+ duration: number;
868
+ operation: string;
869
+ } : Record<string, unknown>;
870
+ /**
871
+ * Type-safe error class with template literal types
872
+ */
873
+ interface TypedError<T extends ErrorCode> extends Throwable {
874
+ readonly code: T;
875
+ readonly message: ErrorMessage<T>;
876
+ readonly status: ErrorStatus<T>;
877
+ readonly context: TypedErrorContext<T>;
878
+ readonly timestamp: string;
879
+ readonly traceId?: string;
880
+ }
881
+ declare const TypedError: (<T extends ErrorCode>(code: T, message: ErrorMessage<T>, context: TypedErrorContext<T>, options?: {
882
+ cause?: unknown;
883
+ traceId?: string;
884
+ }) => TypedError<T>) & {
885
+ /**
886
+ * Create a validation error
887
+ * @example
888
+ * const error = TypedError.validation("email", "test@", "must be valid email")
889
+ * // Type: TypedError<"VALIDATION_FAILED">
890
+ * // Message must match: "Validation failed: ..."
891
+ */
892
+ validation: (field: string, value: unknown, rule: string) => TypedError<"VALIDATION_FAILED">;
893
+ /**
894
+ * Create a network error
895
+ * @example
896
+ * const error = TypedError.network("https://api.example.com", "POST", 500)
897
+ * // Type: TypedError<"NETWORK_ERROR">
898
+ */
899
+ network: (url: string, method: string, statusCode?: number) => TypedError<"NETWORK_ERROR">;
900
+ /**
901
+ * Create an authentication error
902
+ * @example
903
+ * const error = TypedError.auth("/api/admin", "admin")
904
+ * // Type: TypedError<"AUTH_REQUIRED">
905
+ */
906
+ auth: (resource: string, requiredRole?: string) => TypedError<"AUTH_REQUIRED">;
907
+ /**
908
+ * Create a not found error
909
+ * @example
910
+ * const error = TypedError.notFound("user", "123")
911
+ * // Type: TypedError<"NOT_FOUND">
912
+ */
913
+ notFound: (resource: string, id: string | number) => TypedError<"NOT_FOUND">;
914
+ /**
915
+ * Create a permission denied error
916
+ * @example
917
+ * const error = TypedError.permission("delete", "post", "user123")
918
+ * // Type: TypedError<"PERMISSION_DENIED">
919
+ */
920
+ permission: (action: string, resource: string, userId?: string) => TypedError<"PERMISSION_DENIED">;
921
+ /**
922
+ * Create a rate limit error
923
+ * @example
924
+ * const error = TypedError.rateLimit(100, "1h", 3600)
925
+ * // Type: TypedError<"RATE_LIMITED">
926
+ */
927
+ rateLimit: (limit: number, window: string, retryAfter?: number) => TypedError<"RATE_LIMITED">;
928
+ /**
929
+ * Create an internal error
930
+ * @example
931
+ * const error = TypedError.internal("ERR-500-ABC123")
932
+ * // Type: TypedError<"INTERNAL_ERROR">
933
+ */
934
+ internal: (errorId: string) => TypedError<"INTERNAL_ERROR">;
935
+ /**
936
+ * Create a bad request error
937
+ * @example
938
+ * const error = TypedError.badRequest("Invalid JSON", "valid JSON object")
939
+ * // Type: TypedError<"BAD_REQUEST">
940
+ */
941
+ badRequest: (reason: string, expected?: string) => TypedError<"BAD_REQUEST">;
942
+ /**
943
+ * Create a conflict error
944
+ * @example
945
+ * const error = TypedError.conflict("email", "user@example.com")
946
+ * // Type: TypedError<"CONFLICT">
947
+ */
948
+ conflict: (resource: string, conflictingValue: string) => TypedError<"CONFLICT">;
949
+ /**
950
+ * Create a timeout error
951
+ * @example
952
+ * const error = TypedError.timeout(30000, "database query")
953
+ * // Type: TypedError<"TIMEOUT">
954
+ */
955
+ timeout: (duration: number, operation: string) => TypedError<"TIMEOUT">;
956
+ /**
957
+ * Check if a value is a TypedError
958
+ */
959
+ isTypedError: (value: unknown) => value is TypedError<ErrorCode>;
960
+ /**
961
+ * Check if a TypedError has a specific code
962
+ */
963
+ hasCode: <T extends ErrorCode>(error: TypedError<ErrorCode>, code: T) => error is TypedError<T>;
964
+ };
965
+
966
+ /**
967
+ * LazyList provides lazy evaluation for list operations.
968
+ * Operations are deferred until the list is materialized.
969
+ *
970
+ * @example
971
+ * // Basic lazy evaluation
972
+ * const result = LazyList([1, 2, 3, 4, 5])
973
+ * .map(x => x * 2)
974
+ * .filter(x => x > 5)
975
+ * .toArray() // [6, 8, 10]
976
+ *
977
+ * @example
978
+ * // Infinite sequences with take
979
+ * const fibonacci = LazyList.iterate([0, 1], ([a, b]) => [b, a + b])
980
+ * .map(([a]) => a)
981
+ * .take(10)
982
+ * .toArray() // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
983
+ */
984
+ interface LazyList<A extends Type> extends Foldable<A>, Pipe<LazyList<A>>, Serializable<LazyList<A>>, Typeable<"LazyList"> {
985
+ [Symbol.iterator](): Iterator<A>;
986
+ map<B extends Type>(f: (a: A) => B): LazyList<B>;
987
+ flatMap<B extends Type>(f: (a: A) => LazyList<B>): LazyList<B>;
988
+ filter(predicate: (a: A) => boolean): LazyList<A>;
989
+ take(n: number): LazyList<A>;
990
+ drop(n: number): LazyList<A>;
991
+ takeWhile(predicate: (a: A) => boolean): LazyList<A>;
992
+ dropWhile(predicate: (a: A) => boolean): LazyList<A>;
993
+ concat(other: LazyList<A>): LazyList<A>;
994
+ zip<B extends Type>(other: LazyList<B>): LazyList<[A, B]>;
995
+ toList(): List<A>;
996
+ toArray(): A[];
997
+ forEach(f: (a: A) => void): void;
998
+ reduce<B extends Type>(f: (acc: B, a: A) => B, initial: B): B;
999
+ find(predicate: (a: A) => boolean): Option<A>;
1000
+ some(predicate: (a: A) => boolean): boolean;
1001
+ every(predicate: (a: A) => boolean): boolean;
1002
+ count(): number;
1003
+ first(): Option<A>;
1004
+ last(): Option<A>;
1005
+ toString(): string;
1006
+ }
1007
+ /**
1008
+ * Lazy list implementation for efficient deferred computation
1009
+ * @example
1010
+ * // Process large datasets efficiently
1011
+ * const result = LazyList.range(1, 1000000)
1012
+ * .filter(x => x % 2 === 0)
1013
+ * .map(x => x * x)
1014
+ * .take(5)
1015
+ * .toArray() // [4, 16, 36, 64, 100]
1016
+ *
1017
+ * @example
1018
+ * // Infinite sequences
1019
+ * const primes = LazyList.iterate(2, n => n + 1)
1020
+ * .filter(isPrime)
1021
+ * .take(10)
1022
+ * .toArray() // First 10 prime numbers
1023
+ *
1024
+ * @example
1025
+ * // Combining operations
1026
+ * const evens = LazyList.range(0, 100, 2)
1027
+ * const odds = LazyList.range(1, 100, 2)
1028
+ * const combined = evens.zip(odds)
1029
+ * .map(([e, o]) => e + o)
1030
+ * .take(5)
1031
+ * .toArray() // [1, 5, 9, 13, 17]
1032
+ */
1033
+ declare const LazyList: (<A extends Type>(iterable: Iterable<A>) => LazyList<A>) & {
1034
+ /**
1035
+ * Create an empty LazyList
1036
+ * @example
1037
+ * const empty = LazyList.empty<number>()
1038
+ * empty.toArray() // []
1039
+ */
1040
+ empty: <A extends Type>() => LazyList<A>;
1041
+ /**
1042
+ * Create a LazyList from a single value
1043
+ * @example
1044
+ * const single = LazyList.of(42)
1045
+ * .map(x => x * 2)
1046
+ * .toArray() // [84]
1047
+ */
1048
+ of: <A extends Type>(value: A) => LazyList<A>;
1049
+ /**
1050
+ * Create a LazyList from multiple values
1051
+ */
1052
+ from: <A extends Type>(...values: A[]) => LazyList<A>;
1053
+ /**
1054
+ * Create an infinite LazyList by repeatedly applying a function
1055
+ * @example
1056
+ * // Powers of 2
1057
+ * const powers = LazyList.iterate(1, x => x * 2)
1058
+ * .take(10)
1059
+ * .toArray() // [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
1060
+ *
1061
+ * @example
1062
+ * // Fibonacci sequence
1063
+ * const fib = LazyList.iterate([0, 1], ([a, b]) => [b, a + b])
1064
+ * .map(([a]) => a)
1065
+ * .take(8)
1066
+ * .toArray() // [0, 1, 1, 2, 3, 5, 8, 13]
1067
+ */
1068
+ iterate: <A extends Type>(initial: A, f: (a: A) => A) => LazyList<A>;
1069
+ /**
1070
+ * Create an infinite LazyList by repeatedly calling a function
1071
+ */
1072
+ generate: <A extends Type>(f: () => A) => LazyList<A>;
1073
+ /**
1074
+ * Create a LazyList of numbers from start to end (exclusive)
1075
+ * @example
1076
+ * LazyList.range(1, 6).toArray() // [1, 2, 3, 4, 5]
1077
+ * LazyList.range(0, 10, 2).toArray() // [0, 2, 4, 6, 8]
1078
+ * LazyList.range(10, 0, -1).toArray() // [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
1079
+ *
1080
+ * @example
1081
+ * // Sum of squares from 1 to 100
1082
+ * const sum = LazyList.range(1, 101)
1083
+ * .map(x => x * x)
1084
+ * .reduce((a, b) => a + b, 0) // 338350
1085
+ */
1086
+ range: (start: number, end: number, step?: number) => LazyList<number>;
1087
+ /**
1088
+ * Create a LazyList that repeats a value n times (or infinitely if n is not provided)
1089
+ */
1090
+ repeat: <A extends Type>(value: A, n?: number) => LazyList<A>;
1091
+ /**
1092
+ * Create a LazyList that cycles through an iterable infinitely
1093
+ */
1094
+ cycle: <A extends Type>(iterable: Iterable<A>) => LazyList<A>;
1095
+ };
1096
+
1097
+ /**
1098
+ * Validation rule types using template literal types
1099
+ */
1100
+ type ValidationRule = `min:${number}` | `max:${number}` | `minLength:${number}` | `maxLength:${number}` | `pattern:${string}` | `email` | `url` | `uuid` | `required` | `numeric` | `alpha` | `alphanumeric` | `date` | `future` | `past` | `in:${string}` | `notIn:${string}`;
1101
+ /**
1102
+ * Validator function type
1103
+ */
1104
+ type Validator<T> = (value: unknown) => Either<TypedError<"VALIDATION_FAILED">, T>;
1105
+ /**
1106
+ * Field validation result
1107
+ */
1108
+ type FieldValidation<T> = {
1109
+ field: string;
1110
+ value: unknown;
1111
+ result: Either<TypedError<"VALIDATION_FAILED">, T>;
1112
+ };
1113
+ /**
1114
+ * Form validation result
1115
+ */
1116
+ type FormValidation<T extends Record<string, Type>> = Either<List<TypedError<"VALIDATION_FAILED">>, T>;
1117
+ declare const Validation: (<T extends Type>(rule: ValidationRule) => Validator<T>) & {
1118
+ /**
1119
+ * Common pre-built validators
1120
+ */
1121
+ validators: {
1122
+ email: Validator<string>;
1123
+ url: Validator<string>;
1124
+ uuid: Validator<string>;
1125
+ required: Validator<string>;
1126
+ numeric: Validator<number>;
1127
+ positiveNumber: Validator<number>;
1128
+ nonEmptyString: Validator<string>;
1129
+ };
1130
+ /**
1131
+ * Create a validator from a rule string
1132
+ * @example
1133
+ * const validator = Validation.rule<number>("min:18")
1134
+ * const result = validator(25) // Right(25)
1135
+ * const error = validator(15) // Left(TypedError)
1136
+ */
1137
+ rule: <T extends Type>(rule: ValidationRule) => Validator<T>;
1138
+ /**
1139
+ * Combine multiple validators
1140
+ * @example
1141
+ * const validator = Validation.combine(
1142
+ * Validation.rule<string>("required"),
1143
+ * Validation.rule<string>("email"),
1144
+ * Validation.rule<string>("maxLength:100")
1145
+ * )
1146
+ */
1147
+ combine: <T extends Type>(...validators: Validator<T>[]) => Validator<T>;
1148
+ /**
1149
+ * Create a custom validator
1150
+ * @example
1151
+ * const isEven = Validation.custom<number>(
1152
+ * (value) => typeof value === "number" && value % 2 === 0,
1153
+ * "must be an even number"
1154
+ * )
1155
+ */
1156
+ custom: <T extends Type>(predicate: (value: unknown) => boolean, errorMessage: string) => Validator<T>;
1157
+ /**
1158
+ * Validate a form with multiple fields
1159
+ * @example
1160
+ * const schema = {
1161
+ * name: Validation.rule<string>("required"),
1162
+ * email: Validation.rule<string>("email"),
1163
+ * age: Validation.rule<number>("min:18")
1164
+ * }
1165
+ * const result = Validation.form(schema, { name: "John", email: "john@example.com", age: 25 })
1166
+ */
1167
+ form: <T extends Record<string, Type>>(schema: { [K in keyof T]: Validator<T[K]>; }, data: Record<string, unknown>) => FormValidation<T>;
1168
+ };
1169
+
724
1170
  /**
725
1171
  * Utility functions for working with Foldable data structures
726
1172
  */
@@ -826,31 +1272,6 @@ type Identity<T> = {
826
1272
  };
827
1273
  declare function Identity<T>(value: T): Identity<T>;
828
1274
 
829
- interface IterableType<A extends Type> extends Iterable<A>, AsyncMonad<A>, Traversable<A> {
830
- count(p: (x: A) => boolean): number;
831
- find(p: (a: A) => boolean): Option<A>;
832
- forEach(f: (a: A) => void): void;
833
- drop(n: number): IterableType<A>;
834
- dropRight(n: number): IterableType<A>;
835
- dropWhile(p: (a: A) => boolean): IterableType<A>;
836
- exists(p: (a: A) => boolean): boolean;
837
- filter(p: (a: A) => boolean): IterableType<A>;
838
- filterNot(p: (a: A) => boolean): IterableType<A>;
839
- flatten<B>(): IterableType<B>;
840
- reduce(f: (b: A, a: A) => A): A;
841
- reduceRight(f: (b: A, a: A) => A): A;
842
- foldLeft<B>(z: B): (op: (b: B, a: A) => B) => B;
843
- foldRight<B>(z: B): (op: (a: A, b: B) => B) => B;
844
- get head(): A | undefined;
845
- get headOption(): Option<A>;
846
- get isEmpty(): boolean;
847
- map<B extends Type>(f: (a: A) => B): IterableType<B>;
848
- ap<B extends Type>(ff: IterableType<(value: A) => B>): IterableType<B>;
849
- flatMap<B extends Type>(f: (a: A) => IterableType<B>): IterableType<B>;
850
- get size(): number;
851
- toArray<B = A>(): readonly B[];
852
- }
853
-
854
1275
  /**
855
1276
  * Lazy type module
856
1277
  * @module Lazy
@@ -1106,148 +1527,101 @@ declare const Lazy: (<T extends Type>(thunk: () => T) => Lazy<T>) & {
1106
1527
  };
1107
1528
 
1108
1529
  /**
1109
- * LazyList provides lazy evaluation for list operations.
1110
- * Operations are deferred until the list is materialized.
1111
- *
1112
- * @example
1113
- * // Basic lazy evaluation
1114
- * const result = LazyList([1, 2, 3, 4, 5])
1115
- * .map(x => x * 2)
1116
- * .filter(x => x > 5)
1117
- * .toArray() // [6, 8, 10]
1118
- *
1119
- * @example
1120
- * // Infinite sequences with take
1121
- * const fibonacci = LazyList.iterate([0, 1], ([a, b]) => [b, a + b])
1122
- * .map(([a]) => a)
1123
- * .take(10)
1124
- * .toArray() // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
1530
+ * Type alias for the native JavaScript Map
1531
+ * @interface
1532
+ * @module Map
1533
+ * @category Collections
1125
1534
  */
1126
- type LazyList<A extends Type> = {
1127
- [Symbol.iterator](): Iterator<A>;
1128
- map<B extends Type>(f: (a: A) => B): LazyList<B>;
1129
- flatMap<B extends Type>(f: (a: A) => LazyList<B>): LazyList<B>;
1130
- filter(predicate: (a: A) => boolean): LazyList<A>;
1131
- take(n: number): LazyList<A>;
1132
- drop(n: number): LazyList<A>;
1133
- takeWhile(predicate: (a: A) => boolean): LazyList<A>;
1134
- dropWhile(predicate: (a: A) => boolean): LazyList<A>;
1135
- concat(other: LazyList<A>): LazyList<A>;
1136
- zip<B extends Type>(other: LazyList<B>): LazyList<[A, B]>;
1137
- toList(): List<A>;
1138
- toArray(): A[];
1139
- forEach(f: (a: A) => void): void;
1140
- reduce<B extends Type>(f: (acc: B, a: A) => B, initial: B): B;
1141
- find(predicate: (a: A) => boolean): Option<A>;
1142
- some(predicate: (a: A) => boolean): boolean;
1143
- every(predicate: (a: A) => boolean): boolean;
1144
- count(): number;
1145
- first(): Option<A>;
1146
- last(): Option<A>;
1147
- };
1535
+ type ESMapType<K, V> = Map<K, V>;
1148
1536
  /**
1149
- * Lazy list implementation for efficient deferred computation
1150
- * @example
1151
- * // Process large datasets efficiently
1152
- * const result = LazyList.range(1, 1000000)
1153
- * .filter(x => x % 2 === 0)
1154
- * .map(x => x * x)
1155
- * .take(5)
1156
- * .toArray() // [4, 16, 36, 64, 100]
1157
- *
1158
- * @example
1159
- * // Infinite sequences
1160
- * const primes = LazyList.iterate(2, n => n + 1)
1161
- * .filter(isPrime)
1162
- * .take(10)
1163
- * .toArray() // First 10 prime numbers
1537
+ * Reference to the native JavaScript Map
1538
+ * @module Map
1539
+ * @category Collections
1540
+ */
1541
+ declare const ESMap: MapConstructor;
1542
+
1543
+ /**
1544
+ * A mutable reference container that holds a value of type A.
1545
+ * This provides controlled mutability in a functional context.
1164
1546
  *
1165
1547
  * @example
1166
- * // Combining operations
1167
- * const evens = LazyList.range(0, 100, 2)
1168
- * const odds = LazyList.range(1, 100, 2)
1169
- * const combined = evens.zip(odds)
1170
- * .map(([e, o]) => e + o)
1171
- * .take(5)
1172
- * .toArray() // [1, 5, 9, 13, 17]
1548
+ * const counter = Ref(0)
1549
+ * counter.get() // 0
1550
+ * counter.set(5)
1551
+ * counter.get() // 5
1552
+ * counter.update(n => n + 1)
1553
+ * counter.get() // 6
1173
1554
  */
1174
- declare const LazyList: (<A extends Type>(iterable: Iterable<A>) => LazyList<A>) & {
1555
+ interface Ref<A> {
1175
1556
  /**
1176
- * Create an empty LazyList
1177
- * @example
1178
- * const empty = LazyList.empty<number>()
1179
- * empty.toArray() // []
1557
+ * Get the current value
1180
1558
  */
1181
- empty: <A extends Type>() => LazyList<A>;
1559
+ get(): A;
1182
1560
  /**
1183
- * Create a LazyList from a single value
1184
- * @example
1185
- * const single = LazyList.of(42)
1186
- * .map(x => x * 2)
1187
- * .toArray() // [84]
1561
+ * Set a new value
1188
1562
  */
1189
- of: <A extends Type>(value: A) => LazyList<A>;
1563
+ set(value: A): void;
1190
1564
  /**
1191
- * Create a LazyList from multiple values
1565
+ * Update the value using a function
1192
1566
  */
1193
- from: <A extends Type>(...values: A[]) => LazyList<A>;
1567
+ update(f: (current: A) => A): void;
1194
1568
  /**
1195
- * Create an infinite LazyList by repeatedly applying a function
1196
- * @example
1197
- * // Powers of 2
1198
- * const powers = LazyList.iterate(1, x => x * 2)
1199
- * .take(10)
1200
- * .toArray() // [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
1201
- *
1202
- * @example
1203
- * // Fibonacci sequence
1204
- * const fib = LazyList.iterate([0, 1], ([a, b]) => [b, a + b])
1205
- * .map(([a]) => a)
1206
- * .take(8)
1207
- * .toArray() // [0, 1, 1, 2, 3, 5, 8, 13]
1569
+ * Update and return the old value
1208
1570
  */
1209
- iterate: <A extends Type>(initial: A, f: (a: A) => A) => LazyList<A>;
1571
+ getAndSet(value: A): A;
1210
1572
  /**
1211
- * Create an infinite LazyList by repeatedly calling a function
1573
+ * Update and return the new value
1212
1574
  */
1213
- generate: <A extends Type>(f: () => A) => LazyList<A>;
1575
+ updateAndGet(f: (current: A) => A): A;
1214
1576
  /**
1215
- * Create a LazyList of numbers from start to end (exclusive)
1216
- * @example
1217
- * LazyList.range(1, 6).toArray() // [1, 2, 3, 4, 5]
1218
- * LazyList.range(0, 10, 2).toArray() // [0, 2, 4, 6, 8]
1219
- * LazyList.range(10, 0, -1).toArray() // [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
1220
- *
1221
- * @example
1222
- * // Sum of squares from 1 to 100
1223
- * const sum = LazyList.range(1, 101)
1224
- * .map(x => x * x)
1225
- * .reduce((a, b) => a + b, 0) // 338350
1577
+ * Update and return the old value
1226
1578
  */
1227
- range: (start: number, end: number, step?: number) => LazyList<number>;
1579
+ getAndUpdate(f: (current: A) => A): A;
1228
1580
  /**
1229
- * Create a LazyList that repeats a value n times (or infinitely if n is not provided)
1581
+ * Compare and swap - only updates if current value equals expected
1230
1582
  */
1231
- repeat: <A extends Type>(value: A, n?: number) => LazyList<A>;
1583
+ compareAndSet(expected: A, newValue: A): boolean;
1232
1584
  /**
1233
- * Create a LazyList that cycles through an iterable infinitely
1585
+ * Modify the value and return a result
1234
1586
  */
1235
- cycle: <A extends Type>(iterable: Iterable<A>) => LazyList<A>;
1236
- };
1587
+ modify<B>(f: (current: A) => [A, B]): B;
1588
+ }
1589
+ /**
1590
+ * Creates a new mutable reference containing the given value
1591
+ */
1592
+ declare function Ref<A extends Type>(initial: A): Ref<A>;
1593
+ declare namespace Ref {
1594
+ var of: typeof Ref;
1595
+ }
1237
1596
 
1238
1597
  /**
1239
- * Type alias for the native JavaScript Map
1240
- * @interface
1241
- * @module Map
1242
- * @category Collections
1598
+ * Parameters for creating a Valuable instance
1243
1599
  */
1244
- type ESMapType<K, V> = Map<K, V>;
1600
+ type ValuableParams<Tag extends string, T, V> = {
1601
+ _tag: Tag;
1602
+ impl: T;
1603
+ value: V;
1604
+ };
1245
1605
  /**
1246
- * Reference to the native JavaScript Map
1247
- * @module Map
1248
- * @category Collections
1606
+ * Creates a Valuable wrapper that adds value extraction capabilities
1607
+ * @param params - Configuration parameters
1608
+ * @module Valuable
1609
+ * @category Utilities
1249
1610
  */
1250
- declare const ESMap: MapConstructor;
1611
+ declare function Valuable<Tag extends string, V, T = object>(params: ValuableParams<Tag, T, V>): T & {
1612
+ toValue: () => {
1613
+ _tag: Tag;
1614
+ value: V;
1615
+ };
1616
+ _tag: Tag;
1617
+ };
1618
+ /**
1619
+ * Represents a type that can extract its inner value
1620
+ * @interface
1621
+ * @module Valuable
1622
+ * @category Utilities
1623
+ */
1624
+ type Valuable<Tag extends string, V, T = object> = ReturnType<typeof Valuable<Tag, V, T>>;
1251
1625
 
1252
1626
  /**
1253
1627
  * Stack data structure - Last In, First Out (LIFO)
@@ -1351,4 +1725,4 @@ declare const Stack: (<A extends Type>(values?: A[]) => Stack<A>) & {
1351
1725
  fromBinary: <A>(binary: string) => Stack<A>;
1352
1726
  };
1353
1727
 
1354
- export { type Async, AsyncMonad, Base, BoundedNumber, BoundedString, Brand, type CancellationToken, type CancellationTokenSource, Companion, Cond, ESMap, type ESMapType, Either, type EitherKind, EmailAddress, type ErrorChainElement, type ErrorFormatterOptions, type ErrorWithTaskInfo, FPromise, Foldable, FoldableUtils, FunctypeBase, HKT, ISO8601Date, Identity, IntegerNumber, type IterableType, type Kind, Lazy, LazyList, Lazy as LazyType, List, type ListKind, Match, Matchable, NAME, NonEmptyString, NonNegativeNumber, Option, type OptionKind, ParseError, PatternString, Pipe, PositiveInteger, PositiveNumber, Serializable, Stack, type Sync, type TaggedThrowable, Task, type TaskErrorInfo, TaskException, type TaskInfo, type TaskParams, TaskResult, Throwable, type ThrowableType, Traversable, Try, type TryKind, Type, Typeable, UUID, type UniversalContainer, UrlString, ValidatedBrand, Valuable, createCancellationTokenSource, createErrorSerializer, formatError, formatStackTrace, isTaggedThrowable, safeStringify };
1728
+ export { type Async, Base, BoundedNumber, BoundedString, Brand, type CancellationToken, type CancellationTokenSource, Companion, Cond, ESMap, type ESMapType, Either, type EitherKind, EmailAddress, type ErrorChainElement, type ErrorCode, type ErrorFormatterOptions, type ErrorMessage, type ErrorStatus, type ErrorWithTaskInfo, FPromise, type FieldValidation, Foldable, FoldableUtils, type FormValidation, FunctypeBase, HKT, ISO8601Date, Identity, IntegerNumber, type Kind, Lazy, LazyList, Lazy as LazyType, List, type ListKind, Match, Matchable, NAME, NonEmptyString, NonNegativeNumber, Option, type OptionKind, ParseError, PatternString, Pipe, PositiveInteger, PositiveNumber, Ref, Ref as RefType, Serializable, Stack, type Sync, type TaggedThrowable, Task, type TaskErrorInfo, TaskException, type TaskInfo, type TaskParams, TaskResult, Throwable, type ThrowableType, Traversable, Try, type TryKind, Type, Typeable, TypedError, type TypedErrorContext, UUID, type UniversalContainer, UrlString, ValidatedBrand, Validation, type ValidationRule, type Validator, Valuable, type ValuableParams, createCancellationTokenSource, createErrorSerializer, formatError, formatStackTrace, isTaggedThrowable, safeStringify };