functype 0.16.0 → 0.17.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/README.md +30 -0
- package/README.processed.md +5 -1
- package/dist/{Either-C-P6QnvK.d.ts → Either-CM1xSzLl.d.ts} +15 -16
- package/dist/chunk-LW2YTB56.mjs +45 -0
- package/dist/chunk-LW2YTB56.mjs.map +1 -0
- package/dist/do/index.d.ts +2 -2
- package/dist/do/index.mjs +1 -1
- package/dist/either/index.d.ts +1 -1
- package/dist/either/index.mjs +1 -1
- package/dist/fpromise/index.d.ts +1 -1
- package/dist/fpromise/index.mjs +1 -1
- package/dist/index.d.ts +20 -14
- package/dist/index.mjs +1 -1
- package/dist/list/index.d.ts +1 -1
- package/dist/list/index.mjs +1 -1
- package/dist/map/index.d.ts +1 -1
- package/dist/map/index.mjs +1 -1
- package/dist/option/index.d.ts +1 -1
- package/dist/option/index.mjs +1 -1
- package/dist/set/index.d.ts +1 -1
- package/dist/set/index.mjs +1 -1
- package/dist/try/index.d.ts +1 -1
- package/dist/try/index.mjs +1 -1
- package/package.json +15 -10
- package/readme/BRAND_MIGRATION_GUIDE.md +2 -2
- package/readme/ai-guide.md +9 -9
- package/readme/examples.md +19 -19
- package/readme/quick-reference.md +6 -6
- package/dist/chunk-ZRLVS2S5.mjs +0 -45
- package/dist/chunk-ZRLVS2S5.mjs.map +0 -1
package/dist/do/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { O as Option, E as Either, L as List, T as Try, x as Reshapeable, b as Doable } from '../Either-
|
|
2
|
-
export { D as DoResult } from '../Either-
|
|
1
|
+
import { O as Option, E as Either, L as List, T as Try, x as Reshapeable, b as Doable } from '../Either-CM1xSzLl.js';
|
|
2
|
+
export { D as DoResult } from '../Either-CM1xSzLl.js';
|
|
3
3
|
import '../Typeable-DiGVtDnq.js';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/do/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{X as $,T as Do,U as DoAsync,_ as EmptyListError,$ as FailureError,Z as LeftError,Y as NoneError,V as isDoCapable,W as unwrap}from'../chunk-
|
|
1
|
+
export{X as $,T as Do,U as DoAsync,_ as EmptyListError,$ as FailureError,Z as LeftError,Y as NoneError,V as isDoCapable,W as unwrap}from'../chunk-LW2YTB56.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-OR6V4TCO.mjs';//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/either/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { E as Either, e as Left, R as Right, d as TestEither, h as TypeCheckLeft, g as TypeCheckRight, f as isLeft, i as isRight, t as tryCatch, j as tryCatchAsync } from '../Either-
|
|
1
|
+
export { E as Either, e as Left, R as Right, d as TestEither, h as TypeCheckLeft, g as TypeCheckRight, f as isLeft, i as isRight, t as tryCatch, j as tryCatchAsync } from '../Either-CM1xSzLl.js';
|
|
2
2
|
import '../Typeable-DiGVtDnq.js';
|
package/dist/either/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{t as Either,m as Left,l as Right,r as TypeCheckLeft,q as TypeCheckRight,o as isLeft,n as isRight,p as tryCatch,s as tryCatchAsync}from'../chunk-
|
|
1
|
+
export{t as Either,m as Left,l as Right,r as TypeCheckLeft,q as TypeCheckRight,o as isLeft,n as isRight,p as tryCatch,s as tryCatchAsync}from'../chunk-LW2YTB56.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-OR6V4TCO.mjs';//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/fpromise/index.d.ts
CHANGED
package/dist/fpromise/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{N as FPromise,M as FPromiseCompanion}from'../chunk-
|
|
1
|
+
export{N as FPromise,M as FPromiseCompanion}from'../chunk-LW2YTB56.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-OR6V4TCO.mjs';//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Brand } from './branded/index.js';
|
|
2
2
|
export { BrandedBoolean, BrandedBoolean as BrandedBooleanType, BrandedNumber, BrandedNumber as BrandedNumberType, BrandedString, BrandedString as BrandedStringType, ExtractBrand, Unwrap, createBrander, hasBrand, unwrap as unwrapBrand } from './branded/index.js';
|
|
3
|
-
import { L as List, O as Option, E as Either, D as DoResult, F as FunctypeBase, a as Extractable, A as AsyncMonad, P as Promisable, b as Doable, T as Try, c as Traversable, M as Matchable } from './Either-
|
|
4
|
-
export { u as Applicative, C as Collection, r as CollectionOps, s as ContainerOps, v as Functor, l as Functype, m as FunctypeCollection, e as Left, n as MatchableUtils, w as Monad, N as None, o as OptionConstructor, R as Right, p as Set, S as Some, d as TestEither, h as TypeCheckLeft, g as TypeCheckRight, q as TypeNames, k as isExtractable, f as isLeft, i as isRight, t as tryCatch, j as tryCatchAsync } from './Either-
|
|
3
|
+
import { L as List, O as Option, E as Either, D as DoResult, F as FunctypeBase, a as Extractable, A as AsyncMonad, P as Promisable, b as Doable, T as Try, c as Traversable, M as Matchable } from './Either-CM1xSzLl.js';
|
|
4
|
+
export { u as Applicative, C as Collection, r as CollectionOps, s as ContainerOps, v as Functor, l as Functype, m as FunctypeCollection, e as Left, n as MatchableUtils, w as Monad, N as None, o as OptionConstructor, R as Right, p as Set, S as Some, d as TestEither, h as TypeCheckLeft, g as TypeCheckRight, q as TypeNames, k as isExtractable, f as isLeft, i as isRight, t as tryCatch, j as tryCatchAsync } from './Either-CM1xSzLl.js';
|
|
5
5
|
import { T as Type, F as Foldable, P as Pipe, S as Serializable, a as Typeable } from './Typeable-DiGVtDnq.js';
|
|
6
6
|
export { E as ExtractTag, b as SerializationMethods, c as TypeableParams, i as isTypeable } from './Typeable-DiGVtDnq.js';
|
|
7
7
|
import { FPromise } from './fpromise/index.js';
|
|
@@ -217,7 +217,7 @@ declare const NonEmptyString: ValidatedBrandCompanion<"NonEmptyString", string>;
|
|
|
217
217
|
* const processEmail = (input: string) => {
|
|
218
218
|
* return EmailAddress.from(input)
|
|
219
219
|
* .map(email => sendWelcomeEmail(email))
|
|
220
|
-
* .
|
|
220
|
+
* .orElse("Invalid email address")
|
|
221
221
|
* }
|
|
222
222
|
*/
|
|
223
223
|
declare const EmailAddress: ValidatedBrandCompanion<"EmailAddress", string>;
|
|
@@ -257,7 +257,7 @@ declare function BoundedString(brand: string, minLength: number, maxLength: numb
|
|
|
257
257
|
* const PhoneNumber = PatternString("PhoneNumber", /^\+?[1-9]\d{1,14}$/)
|
|
258
258
|
* const phone = PhoneNumber.from("+1234567890")
|
|
259
259
|
* .map(p => formatPhoneNumber(p))
|
|
260
|
-
* .
|
|
260
|
+
* .orElse("Invalid phone number")
|
|
261
261
|
*/
|
|
262
262
|
declare function PatternString(brand: string, pattern: RegExp): ValidatedBrandCompanion<string, string>;
|
|
263
263
|
|
|
@@ -325,7 +325,7 @@ type Cond<T extends Type> = {
|
|
|
325
325
|
/**
|
|
326
326
|
* Get the result if a condition was met, throws if no condition met
|
|
327
327
|
*/
|
|
328
|
-
|
|
328
|
+
orThrow: () => T;
|
|
329
329
|
};
|
|
330
330
|
/**
|
|
331
331
|
* Conditional expression builder for functional if/else chains
|
|
@@ -499,7 +499,7 @@ type Match<T extends Type, R extends Type> = {
|
|
|
499
499
|
/**
|
|
500
500
|
* Get result if matched, throws if no match
|
|
501
501
|
*/
|
|
502
|
-
|
|
502
|
+
orThrow: (errorMessage?: string) => R;
|
|
503
503
|
/**
|
|
504
504
|
* Get result wrapped in Option
|
|
505
505
|
*/
|
|
@@ -1387,19 +1387,25 @@ interface Lazy<T extends Type> extends FunctypeBase<T, "Lazy">, Extractable<T>,
|
|
|
1387
1387
|
* @param defaultValue - The value to return if computation fails
|
|
1388
1388
|
* @returns The computed value or defaultValue
|
|
1389
1389
|
*/
|
|
1390
|
-
|
|
1390
|
+
orElse(defaultValue: T): T;
|
|
1391
1391
|
/**
|
|
1392
1392
|
* Returns the computed value or null if computation fails
|
|
1393
1393
|
* @returns The computed value or null
|
|
1394
1394
|
*/
|
|
1395
|
-
|
|
1395
|
+
orNull(): T | null;
|
|
1396
1396
|
/**
|
|
1397
1397
|
* Returns the computed value or throws an error if computation fails
|
|
1398
1398
|
* @param error - Optional custom error to throw. If not provided, throws the computation error or a default error
|
|
1399
1399
|
* @returns The computed value
|
|
1400
1400
|
* @throws The specified error, computation error, or a default error
|
|
1401
1401
|
*/
|
|
1402
|
-
|
|
1402
|
+
orThrow(error?: Error): T;
|
|
1403
|
+
/**
|
|
1404
|
+
* Returns this Lazy if computation succeeds, otherwise returns the alternative Lazy
|
|
1405
|
+
* @param alternative - The alternative Lazy to use if computation fails
|
|
1406
|
+
* @returns This Lazy or the alternative
|
|
1407
|
+
*/
|
|
1408
|
+
or(alternative: Lazy<T>): Lazy<T>;
|
|
1403
1409
|
/**
|
|
1404
1410
|
* Maps the value inside the Lazy using the provided function
|
|
1405
1411
|
* @param f - The mapping function
|
|
@@ -1540,8 +1546,8 @@ interface Lazy<T extends Type> extends FunctypeBase<T, "Lazy">, Extractable<T>,
|
|
|
1540
1546
|
* return 42
|
|
1541
1547
|
* })
|
|
1542
1548
|
* // Nothing printed yet
|
|
1543
|
-
* const result = expensive.
|
|
1544
|
-
* const cached = expensive.
|
|
1549
|
+
* const result = expensive.orThrow() // Prints "Computing..." and returns 42
|
|
1550
|
+
* const cached = expensive.orThrow() // Returns 42 without printing
|
|
1545
1551
|
*
|
|
1546
1552
|
* @example
|
|
1547
1553
|
* // Error handling
|
|
@@ -1549,7 +1555,7 @@ interface Lazy<T extends Type> extends FunctypeBase<T, "Lazy">, Extractable<T>,
|
|
|
1549
1555
|
* if (Math.random() > 0.5) throw new Error("Failed")
|
|
1550
1556
|
* return "Success"
|
|
1551
1557
|
* })
|
|
1552
|
-
* const safe = risky.
|
|
1558
|
+
* const safe = risky.orElse("Default") // Returns "Success" or "Default"
|
|
1553
1559
|
* const option = risky.toOption() // Some("Success") or None
|
|
1554
1560
|
* const either = risky.toEither() // Right("Success") or Left(Error)
|
|
1555
1561
|
*
|
|
@@ -1559,14 +1565,14 @@ interface Lazy<T extends Type> extends FunctypeBase<T, "Lazy">, Extractable<T>,
|
|
|
1559
1565
|
* .map(x => x * 2)
|
|
1560
1566
|
* .flatMap(x => Lazy(() => x + 5))
|
|
1561
1567
|
* .recover(err => 0)
|
|
1562
|
-
* .
|
|
1568
|
+
* .orThrow() // 25
|
|
1563
1569
|
*
|
|
1564
1570
|
* @example
|
|
1565
1571
|
* // Integration with functype
|
|
1566
1572
|
* const userOption = Option({ id: 1, name: "Alice" })
|
|
1567
1573
|
* const userName = Lazy.fromOption(userOption, () => ({ id: 0, name: "Anonymous" }))
|
|
1568
1574
|
* .map(user => user.name)
|
|
1569
|
-
* .
|
|
1575
|
+
* .orThrow() // "Alice"
|
|
1570
1576
|
*/
|
|
1571
1577
|
declare const Lazy: (<T extends Type>(thunk: () => T) => Lazy<T>) & {
|
|
1572
1578
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{X as $,J as Base,E as BoundedNumber,F as BoundedString,H as Cond,T as Do,U as DoAsync,ma as ESMap,t as Either,A as EmailAddress,_ as EmptyListError,P as Err,N as FPromise,M as FPromiseCompanion,$ as FailureError,ia as FoldableUtils,ja as HKT,D as ISO8601Date,ka as Identity,x as IntegerNumber,la as Lazy,g as LazyList,m as Left,Z as LeftError,k as List,na as Map,I as Match,oa as MatchableUtils,K as NAME,z as NonEmptyString,w as NonNegativeNumber,b as None,Y as NoneError,Q as Ok,d as Option,c as OptionConstructor,ea as ParseError,G as PatternString,y as PositiveInteger,v as PositiveNumber,f as Ref,l as Right,e as Set,a as Some,pa as Stack,S as Task,L as Throwable,h as Try,r as TypeCheckLeft,q as TypeCheckRight,i as Typeable,fa as TypedError,C as UUID,B as UrlString,u as ValidatedBrand,ga as Validation,qa as Valuable,R as createCancellationTokenSource,da as createErrorSerializer,ca as formatError,ba as formatStackTrace,V as isDoCapable,ha as isExtractable,o as isLeft,n as isRight,O as isTaggedThrowable,j as isTypeable,aa as safeStringify,p as tryCatch,s as tryCatchAsync,W as unwrap}from'./chunk-
|
|
1
|
+
export{X as $,J as Base,E as BoundedNumber,F as BoundedString,H as Cond,T as Do,U as DoAsync,ma as ESMap,t as Either,A as EmailAddress,_ as EmptyListError,P as Err,N as FPromise,M as FPromiseCompanion,$ as FailureError,ia as FoldableUtils,ja as HKT,D as ISO8601Date,ka as Identity,x as IntegerNumber,la as Lazy,g as LazyList,m as Left,Z as LeftError,k as List,na as Map,I as Match,oa as MatchableUtils,K as NAME,z as NonEmptyString,w as NonNegativeNumber,b as None,Y as NoneError,Q as Ok,d as Option,c as OptionConstructor,ea as ParseError,G as PatternString,y as PositiveInteger,v as PositiveNumber,f as Ref,l as Right,e as Set,a as Some,pa as Stack,S as Task,L as Throwable,h as Try,r as TypeCheckLeft,q as TypeCheckRight,i as Typeable,fa as TypedError,C as UUID,B as UrlString,u as ValidatedBrand,ga as Validation,qa as Valuable,R as createCancellationTokenSource,da as createErrorSerializer,ca as formatError,ba as formatStackTrace,V as isDoCapable,ha as isExtractable,o as isLeft,n as isRight,O as isTaggedThrowable,j as isTypeable,aa as safeStringify,p as tryCatch,s as tryCatchAsync,W as unwrap}from'./chunk-LW2YTB56.mjs';export{a as Companion,b as Tuple}from'./chunk-BQJB6CCW.mjs';export{a as Brand,g as BrandedBoolean,f as BrandedNumber,e as BrandedString,d as createBrander,c as hasBrand,b as unwrapBrand}from'./chunk-OR6V4TCO.mjs';//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/list/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { L as List } from '../Either-
|
|
1
|
+
export { L as List } from '../Either-CM1xSzLl.js';
|
|
2
2
|
import '../Typeable-DiGVtDnq.js';
|
package/dist/list/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{k as List}from'../chunk-
|
|
1
|
+
export{k as List}from'../chunk-LW2YTB56.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-OR6V4TCO.mjs';//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/map/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as Traversable, C as Collection, O as Option } from '../Either-
|
|
1
|
+
import { c as Traversable, C as Collection, O as Option } from '../Either-CM1xSzLl.js';
|
|
2
2
|
import { a as Typeable, S as Serializable, P as Pipe, F as Foldable, T as Type } from '../Typeable-DiGVtDnq.js';
|
|
3
3
|
import { Tuple } from '../tuple/index.js';
|
|
4
4
|
|
package/dist/map/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{na as Map}from'../chunk-
|
|
1
|
+
export{na as Map}from'../chunk-LW2YTB56.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-OR6V4TCO.mjs';//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/option/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { N as None, O as Option, o as OptionConstructor, S as Some } from '../Either-
|
|
1
|
+
export { N as None, O as Option, o as OptionConstructor, S as Some } from '../Either-CM1xSzLl.js';
|
|
2
2
|
import '../Typeable-DiGVtDnq.js';
|
package/dist/option/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{b as None,d as Option,c as OptionConstructor,a as Some}from'../chunk-
|
|
1
|
+
export{b as None,d as Option,c as OptionConstructor,a as Some}from'../chunk-LW2YTB56.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-OR6V4TCO.mjs';//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/set/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { p as Set } from '../Either-
|
|
1
|
+
export { p as Set } from '../Either-CM1xSzLl.js';
|
|
2
2
|
import '../Typeable-DiGVtDnq.js';
|
package/dist/set/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{e as Set}from'../chunk-
|
|
1
|
+
export{e as Set}from'../chunk-LW2YTB56.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-OR6V4TCO.mjs';//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/try/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { T as Try, q as TypeNames } from '../Either-
|
|
1
|
+
export { T as Try, q as TypeNames } from '../Either-CM1xSzLl.js';
|
|
2
2
|
import '../Typeable-DiGVtDnq.js';
|
package/dist/try/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{h as Try}from'../chunk-
|
|
1
|
+
export{h as Try}from'../chunk-LW2YTB56.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-OR6V4TCO.mjs';//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "functype",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A functional programming library for TypeScript, using immutable data structures and type classes",
|
|
6
6
|
"author": "jordan.burke@gmail.com",
|
|
@@ -9,23 +9,23 @@
|
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "git+https://github.com/jordanburke/functype.git"
|
|
11
11
|
},
|
|
12
|
-
"homepage": "https://
|
|
12
|
+
"homepage": "https://functype.org/",
|
|
13
13
|
"url": "https://github.com/jordanburke/functype",
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"@eslint/compat": "^1.4.0",
|
|
16
16
|
"@eslint/eslintrc": "^3.3.1",
|
|
17
|
-
"@eslint/js": "^9.
|
|
17
|
+
"@eslint/js": "^9.38.0",
|
|
18
18
|
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
19
19
|
"@semantic-release/github": "^11.0.6",
|
|
20
20
|
"@semantic-release/npm": "^12.0.2",
|
|
21
21
|
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
22
|
-
"@types/node": "^22.18.
|
|
23
|
-
"@typescript-eslint/eslint-plugin": "^8.46.
|
|
24
|
-
"@typescript-eslint/parser": "^8.46.
|
|
22
|
+
"@types/node": "^22.18.11",
|
|
23
|
+
"@typescript-eslint/eslint-plugin": "^8.46.1",
|
|
24
|
+
"@typescript-eslint/parser": "^8.46.1",
|
|
25
25
|
"@vitest/coverage-v8": "^3.2.4",
|
|
26
26
|
"@vitest/ui": "^3.2.4",
|
|
27
27
|
"cross-env": "^10.1.0",
|
|
28
|
-
"eslint": "^9.
|
|
28
|
+
"eslint": "^9.38.0",
|
|
29
29
|
"eslint-config-functype": "1.3.0",
|
|
30
30
|
"eslint-config-prettier": "^10.1.8",
|
|
31
31
|
"eslint-plugin-functional": "^9.0.2",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"ts-node": "^10.9.2",
|
|
40
40
|
"tsup": "^8.5.0",
|
|
41
41
|
"tsx": "^4.20.6",
|
|
42
|
-
"typedoc": "^0.28.
|
|
42
|
+
"typedoc": "^0.28.14",
|
|
43
43
|
"typescript": "5.9.2",
|
|
44
44
|
"vitest": "^3.2.4"
|
|
45
45
|
},
|
|
@@ -151,7 +151,9 @@
|
|
|
151
151
|
},
|
|
152
152
|
"sideEffects": false,
|
|
153
153
|
"scripts": {
|
|
154
|
-
"validate": "pnpm
|
|
154
|
+
"validate": "pnpm validate:core && pnpm validate:landing",
|
|
155
|
+
"validate:core": "pnpm format && pnpm lint && pnpm test && pnpm build",
|
|
156
|
+
"validate:landing": "cd landing && pnpm validate",
|
|
155
157
|
"format": "prettier --write .",
|
|
156
158
|
"format:check": "prettier --check .",
|
|
157
159
|
"lint": "eslint ./src --fix",
|
|
@@ -172,6 +174,9 @@
|
|
|
172
174
|
"docs:watch": "typedoc --watch",
|
|
173
175
|
"docs:validate": "tsx scripts/validate-docs.ts",
|
|
174
176
|
"postdocs": "node -e \"console.log('Documentation generated in ./typedocs')\"",
|
|
175
|
-
"analyze:size": "pnpm build && node ./scripts/analyze-bundle-size.js"
|
|
177
|
+
"analyze:size": "pnpm build && node ./scripts/analyze-bundle-size.js",
|
|
178
|
+
"landing:dev": "cd landing && pnpm dev",
|
|
179
|
+
"landing:build": "cd landing && pnpm build",
|
|
180
|
+
"landing:preview": "cd landing && pnpm preview"
|
|
176
181
|
}
|
|
177
182
|
}
|
|
@@ -127,14 +127,14 @@ When extracting branded values from Option or Either, you may need to adjust def
|
|
|
127
127
|
|
|
128
128
|
```typescript
|
|
129
129
|
const email = EmailAddress.of(input)
|
|
130
|
-
const value = email.map((e) => e.unbrand()).
|
|
130
|
+
const value = email.map((e) => e.unbrand()).orElse("")
|
|
131
131
|
```
|
|
132
132
|
|
|
133
133
|
**After (Option 1 - Keep branded type):**
|
|
134
134
|
|
|
135
135
|
```typescript
|
|
136
136
|
const email = EmailAddress.of(input)
|
|
137
|
-
const value = email.
|
|
137
|
+
const value = email.orElse("" as Brand<"EmailAddress", string>)
|
|
138
138
|
```
|
|
139
139
|
|
|
140
140
|
**After (Option 2 - Use fold for clean extraction):**
|
package/readme/ai-guide.md
CHANGED
|
@@ -11,9 +11,9 @@ This document provides a concise reference for AI models to understand the patte
|
|
|
11
11
|
const some = Option(42) // Some(42)
|
|
12
12
|
const none = Option(null) // None
|
|
13
13
|
|
|
14
|
-
// Access: .get() or .
|
|
14
|
+
// Access: .get() or .orElse(default)
|
|
15
15
|
some.get() // 42
|
|
16
|
-
none.
|
|
16
|
+
none.orElse("default") // "default"
|
|
17
17
|
|
|
18
18
|
// Transform: .map(), .flatMap(), .filter()
|
|
19
19
|
some.map((x) => x * 2) // Some(84)
|
|
@@ -98,9 +98,9 @@ list.foldLeft(0)((acc, x) => acc + x) // 15
|
|
|
98
98
|
// Create: Map({key: value})
|
|
99
99
|
const map = Map({ a: 1, b: 2, c: 3 })
|
|
100
100
|
|
|
101
|
-
// Access: .get(key), .
|
|
101
|
+
// Access: .get(key), .orElse(key, default)
|
|
102
102
|
map.get("a") // Some(1)
|
|
103
|
-
map.
|
|
103
|
+
map.orElse("d", 0) // 0
|
|
104
104
|
|
|
105
105
|
// Transform: .map(), .filter()
|
|
106
106
|
map.map((v) => v * 2) // Map({a: 2, b: 4, c: 6})
|
|
@@ -233,7 +233,7 @@ parseResult.fold(
|
|
|
233
233
|
const userCity = Option(user)
|
|
234
234
|
.flatMap((u) => Option(u.address))
|
|
235
235
|
.flatMap((a) => Option(a.city))
|
|
236
|
-
.
|
|
236
|
+
.orElse("Unknown")
|
|
237
237
|
|
|
238
238
|
// Either chain
|
|
239
239
|
parseInput(input)
|
|
@@ -295,7 +295,7 @@ const result = pipe(
|
|
|
295
295
|
(opt) => opt.filter((s) => s.length > 0),
|
|
296
296
|
(opt) => opt.map((s) => parseInt(s, 10)),
|
|
297
297
|
(opt) => opt.filter((n) => !isNaN(n)),
|
|
298
|
-
(opt) => opt.
|
|
298
|
+
(opt) => opt.orElse(0),
|
|
299
299
|
)
|
|
300
300
|
|
|
301
301
|
// Converting between types
|
|
@@ -378,13 +378,13 @@ import { right, left } from "functype/either"
|
|
|
378
378
|
// Bad
|
|
379
379
|
const a = option.map((x) => x + 1)
|
|
380
380
|
const b = a.filter((x) => x > 10)
|
|
381
|
-
const c = b.
|
|
381
|
+
const c = b.orElse(0)
|
|
382
382
|
|
|
383
383
|
// Good
|
|
384
384
|
const result = option
|
|
385
385
|
.map((x) => x + 1)
|
|
386
386
|
.filter((x) => x > 10)
|
|
387
|
-
.
|
|
387
|
+
.orElse(0)
|
|
388
388
|
```
|
|
389
389
|
|
|
390
390
|
4. ❌ **Mixing Imperative and Functional Styles**:
|
|
@@ -402,5 +402,5 @@ import { right, left } from "functype/either"
|
|
|
402
402
|
)
|
|
403
403
|
|
|
404
404
|
// Good
|
|
405
|
-
const result = option.
|
|
405
|
+
const result = option.orElse(42)
|
|
406
406
|
```
|
package/readme/examples.md
CHANGED
|
@@ -47,8 +47,8 @@ console.log(withValue.get()) // 42
|
|
|
47
47
|
// console.log(withoutValue.get()) // Would throw error - use getOrElse instead
|
|
48
48
|
|
|
49
49
|
// Default values
|
|
50
|
-
console.log(withValue.
|
|
51
|
-
console.log(withoutValue.
|
|
50
|
+
console.log(withValue.orElse(0)) // 42
|
|
51
|
+
console.log(withoutValue.orElse(0)) // 0
|
|
52
52
|
|
|
53
53
|
// Optional chaining alternative
|
|
54
54
|
const user = Option({ name: "John", address: { city: "New York" } })
|
|
@@ -58,11 +58,11 @@ const noUser = Option(null)
|
|
|
58
58
|
const city1 = user
|
|
59
59
|
.flatMap((u) => Option(u.address))
|
|
60
60
|
.flatMap((a) => Option(a.city))
|
|
61
|
-
.
|
|
61
|
+
.orElse("Unknown")
|
|
62
62
|
const city2 = noUser
|
|
63
63
|
.flatMap((u) => Option(u.address))
|
|
64
64
|
.flatMap((a) => Option(a.city))
|
|
65
|
-
.
|
|
65
|
+
.orElse("Unknown")
|
|
66
66
|
|
|
67
67
|
console.log(city1) // "New York"
|
|
68
68
|
console.log(city2) // "Unknown"
|
|
@@ -169,8 +169,8 @@ console.log(success.get()) // 42
|
|
|
169
169
|
// console.log(failure.get()) // Would throw error - use getOrElse instead
|
|
170
170
|
|
|
171
171
|
// Default values
|
|
172
|
-
console.log(success.
|
|
173
|
-
console.log(failure.
|
|
172
|
+
console.log(success.orElse(0)) // 42
|
|
173
|
+
console.log(failure.orElse(0)) // 0
|
|
174
174
|
|
|
175
175
|
// Get the left value
|
|
176
176
|
console.log(failure.getLeft()) // "error"
|
|
@@ -328,8 +328,8 @@ console.log(success.get()) // 42
|
|
|
328
328
|
// console.log(failure.get()) // Would throw the original error
|
|
329
329
|
|
|
330
330
|
// Default values
|
|
331
|
-
console.log(success.
|
|
332
|
-
console.log(failure.
|
|
331
|
+
console.log(success.orElse(0)) // 42
|
|
332
|
+
console.log(failure.orElse(0)) // 0
|
|
333
333
|
|
|
334
334
|
// Access the error
|
|
335
335
|
console.log(failure.error.message) // "Something went wrong"
|
|
@@ -567,7 +567,7 @@ const scores = Map({
|
|
|
567
567
|
// Access elements
|
|
568
568
|
console.log(scores.get("alice")) // Some(95)
|
|
569
569
|
console.log(scores.get("dave")) // None
|
|
570
|
-
console.log(scores.
|
|
570
|
+
console.log(scores.orElse("dave", 0)) // 0
|
|
571
571
|
|
|
572
572
|
// Check properties
|
|
573
573
|
console.log(scores.isEmpty()) // false
|
|
@@ -1328,7 +1328,7 @@ const processedName = userInput
|
|
|
1328
1328
|
.map((s) => s.trim())
|
|
1329
1329
|
.filter((s) => s.length > 0)
|
|
1330
1330
|
.map((s) => s.toUpperCase())
|
|
1331
|
-
.
|
|
1331
|
+
.orElse("ANONYMOUS")
|
|
1332
1332
|
console.log(processedName) // "JOHN DOE"
|
|
1333
1333
|
|
|
1334
1334
|
// Either chaining
|
|
@@ -1348,8 +1348,8 @@ const processAge = (input: string): Either<string, string> => {
|
|
|
1348
1348
|
.map((age) => `Valid age: ${age}`)
|
|
1349
1349
|
}
|
|
1350
1350
|
|
|
1351
|
-
console.log(processAge("35").
|
|
1352
|
-
console.log(processAge("abc").
|
|
1351
|
+
console.log(processAge("35").orElse("Invalid age")) // "Valid age: 35"
|
|
1352
|
+
console.log(processAge("abc").orElse("Invalid age")) // "Invalid age"
|
|
1353
1353
|
|
|
1354
1354
|
// List chaining
|
|
1355
1355
|
const numbers = List([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
|
@@ -1372,7 +1372,7 @@ const result1 = pipe(
|
|
|
1372
1372
|
Option(5),
|
|
1373
1373
|
(opt) => opt.map((n) => n * 2),
|
|
1374
1374
|
(opt) => opt.filter((n) => n > 5),
|
|
1375
|
-
(opt) => opt.
|
|
1375
|
+
(opt) => opt.orElse(0),
|
|
1376
1376
|
)
|
|
1377
1377
|
console.log(result1) // 10
|
|
1378
1378
|
|
|
@@ -1381,7 +1381,7 @@ const result2 = pipe(
|
|
|
1381
1381
|
Either.right<string, number>(42),
|
|
1382
1382
|
(either) => either.map((n) => n.toString()),
|
|
1383
1383
|
(either) => either.mapLeft((e) => new Error(e)),
|
|
1384
|
-
(either) => either.
|
|
1384
|
+
(either) => either.orElse("error"),
|
|
1385
1385
|
)
|
|
1386
1386
|
console.log(result2) // "42"
|
|
1387
1387
|
|
|
@@ -1389,9 +1389,9 @@ console.log(result2) // "42"
|
|
|
1389
1389
|
const result3 = pipe(
|
|
1390
1390
|
List([1, 2, 3, 4]),
|
|
1391
1391
|
(list) => list.map((n) => n * 2),
|
|
1392
|
-
(list) => Option(list.head().
|
|
1392
|
+
(list) => Option(list.head().orElse(0)),
|
|
1393
1393
|
(opt) => opt.filter((n) => n > 5),
|
|
1394
|
-
(opt) => Either.fromNullable(opt.
|
|
1394
|
+
(opt) => Either.fromNullable(opt.orElse(null), "No valid value"),
|
|
1395
1395
|
(either) =>
|
|
1396
1396
|
either.fold(
|
|
1397
1397
|
(err) => `Error: ${err}`,
|
|
@@ -1419,13 +1419,13 @@ const userId = "user123"
|
|
|
1419
1419
|
const user = findUserById(userId)
|
|
1420
1420
|
|
|
1421
1421
|
// No need for null checks
|
|
1422
|
-
const greet = user.map((u) => `Hello, ${u.name}!`).
|
|
1422
|
+
const greet = user.map((u) => `Hello, ${u.name}!`).orElse("User not found")
|
|
1423
1423
|
|
|
1424
1424
|
// Method chaining without worrying about null
|
|
1425
1425
|
const userCity = user
|
|
1426
1426
|
.flatMap((u) => Option(u.address))
|
|
1427
1427
|
.flatMap((a) => Option(a.city))
|
|
1428
|
-
.
|
|
1428
|
+
.orElse("Unknown location")
|
|
1429
1429
|
```
|
|
1430
1430
|
|
|
1431
1431
|
### Either for Error Handling
|
|
@@ -2085,7 +2085,7 @@ userState.fold(
|
|
|
2085
2085
|
console.log("User:", user.name, user.email)
|
|
2086
2086
|
console.log("Cart items:", user.cart.size())
|
|
2087
2087
|
console.log("Checkout history:", user.checkoutHistory.size(), "orders")
|
|
2088
|
-
console.log("Latest order total:", user.checkoutHistory.head().
|
|
2088
|
+
console.log("Latest order total:", user.checkoutHistory.head().orElse({ total: 0 }).total)
|
|
2089
2089
|
},
|
|
2090
2090
|
)
|
|
2091
2091
|
```
|
|
@@ -20,8 +20,8 @@ option.isEmpty() // true if None, false if Some
|
|
|
20
20
|
|
|
21
21
|
// Accessing
|
|
22
22
|
option.get() // Gets value or throws if None
|
|
23
|
-
option.
|
|
24
|
-
option.
|
|
23
|
+
option.orElse(defaultValue) // Gets value or returns default
|
|
24
|
+
option.orThrow(new Error("No value")) // Gets value or throws custom error
|
|
25
25
|
|
|
26
26
|
// Transforming
|
|
27
27
|
option.map((x) => x * 2) // Transforms inner value
|
|
@@ -58,7 +58,7 @@ either.isLeft() // true if Left, false if Right
|
|
|
58
58
|
|
|
59
59
|
// Accessing
|
|
60
60
|
either.get() // Gets Right value or throws if Left
|
|
61
|
-
either.
|
|
61
|
+
either.orElse(defaultValue) // Gets Right value or returns default
|
|
62
62
|
either.getLeft() // Gets Left value or throws if Right
|
|
63
63
|
|
|
64
64
|
// Transforming
|
|
@@ -104,7 +104,7 @@ tryVal.isFailure() // true if Failure, false if Success
|
|
|
104
104
|
|
|
105
105
|
// Accessing
|
|
106
106
|
tryVal.get() // Gets value or throws original error
|
|
107
|
-
tryVal.
|
|
107
|
+
tryVal.orElse(defaultValue) // Gets value or returns default
|
|
108
108
|
tryVal.error // Gets error for Failure
|
|
109
109
|
|
|
110
110
|
// Error handling
|
|
@@ -200,7 +200,7 @@ map.has("a") // true if key exists
|
|
|
200
200
|
|
|
201
201
|
// Accessing
|
|
202
202
|
map.get("a") // Option.Some with value or None
|
|
203
|
-
map.
|
|
203
|
+
map.orElse("a", 0) // Value or default
|
|
204
204
|
map.keys() // List of keys
|
|
205
205
|
map.values() // List of values
|
|
206
206
|
map.entries() // List of [key, value] tuples
|
|
@@ -496,7 +496,7 @@ const result = pipe(
|
|
|
496
496
|
(opt) => opt.map((s) => parseInt(s, 10)),
|
|
497
497
|
(opt) => opt.filter((n) => !isNaN(n)),
|
|
498
498
|
(opt) => opt.map((n) => n * 2),
|
|
499
|
-
(opt) => opt.
|
|
499
|
+
(opt) => opt.orElse(0),
|
|
500
500
|
) // 84
|
|
501
501
|
|
|
502
502
|
// Cross-type transformations
|