functype 1.2.2 → 1.3.1
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/Companion-DiOMBHDG.js +1 -0
- package/dist/CompanionTypes-BVqO7Kc2.js +1 -0
- package/dist/CompanionTypes-CAxuM7qS.d.ts +58 -0
- package/dist/cli/exports.d.ts +1 -0
- package/dist/cli/exports.js +1 -1
- package/dist/cli/index.js +5 -5
- package/dist/companion/index.d.ts +2 -0
- package/dist/companion/index.js +1 -0
- package/dist/conditional/index.d.ts +2 -0
- package/dist/conditional/index.js +1 -0
- package/dist/core/task/index.d.ts +2 -0
- package/dist/core/task/index.js +1 -0
- package/dist/decoder/index.d.ts +2 -0
- package/dist/decoder/index.js +1 -0
- package/dist/do/index.d.ts +1 -1
- package/dist/do/index.js +1 -1
- package/dist/either/index.d.ts +1 -1
- package/dist/either/index.js +1 -1
- package/dist/fetch/index.d.ts +2 -0
- package/dist/fetch/index.js +1 -0
- package/dist/{full-interfaces-DMopL9Xt.js → full-interfaces-BO3WRfCs.js} +37 -2
- package/dist/functype/index.d.ts +2 -0
- package/dist/functype/index.js +0 -0
- package/dist/{index-D6Zlkrnf.d.ts → index-2qrljvxu.d.ts} +4656 -4599
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/io/index.d.ts +2 -0
- package/dist/io/index.js +1 -0
- package/dist/lazy/index.d.ts +2 -0
- package/dist/lazy/index.js +1 -0
- package/dist/list/index.d.ts +1 -1
- package/dist/list/index.js +1 -1
- package/dist/logger/index.d.ts +37 -0
- package/dist/logger/index.js +0 -0
- package/dist/map/index.d.ts +1 -1
- package/dist/map/index.js +1 -1
- package/dist/obj/index.d.ts +2 -0
- package/dist/obj/index.js +1 -0
- package/dist/option/index.d.ts +1 -1
- package/dist/option/index.js +1 -1
- package/dist/serialization/index.d.ts +2 -0
- package/dist/serialization/index.js +1 -0
- package/dist/serialization-EQGLX3e3.js +4 -0
- package/dist/set/index.d.ts +1 -1
- package/dist/set/index.js +1 -1
- package/dist/src-CVFuTCru.js +17 -0
- package/dist/try/index.d.ts +1 -1
- package/dist/try/index.js +1 -1
- package/dist/tuple/index.js +1 -1
- package/dist/typeclass/index.d.ts +2 -0
- package/dist/typeclass/index.js +1 -0
- package/dist/typeclass-C61yDVYd.js +1 -0
- package/dist/util/index.d.ts +24 -0
- package/dist/util/index.js +1 -0
- package/package.json +10 -4
- package/dist/Tuple-knEoDiKZ.js +0 -4
- package/dist/src-D3v1n1vv.js +0 -17
- package/readme/BRAND_MIGRATION_GUIDE.md +0 -230
- package/readme/BUNDLE_OPTIMIZATION.md +0 -74
- package/readme/HKT.md +0 -110
- package/readme/ROADMAP.md +0 -113
- package/readme/TASK-TODO.md +0 -33
- package/readme/TUPLE-EXAMPLES.md +0 -76
- package/readme/ai-guide.md +0 -384
- package/readme/examples.md +0 -1883
- package/readme/quick-reference.md +0 -462
- package/readme/task-error-handling.md +0 -283
- package/readme/tasks.md +0 -195
- package/readme/type-index.md +0 -225
package/readme/ROADMAP.md
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
# Functype Roadmap (2025-2026)
|
|
2
|
-
|
|
3
|
-
This roadmap outlines the planned development path for the Functype library, focusing on expanding functionality, improving performance, ensuring API consistency, and enhancing TypeScript integration.
|
|
4
|
-
|
|
5
|
-
## Q2 2025: Core Functional Data Types
|
|
6
|
-
|
|
7
|
-
### Lazy Evaluation
|
|
8
|
-
|
|
9
|
-
- [ ] Implement `LazyList` / `Stream` for efficient processing of potentially infinite sequences
|
|
10
|
-
- [ ] Add common operations: `map`, `filter`, `take`, `drop`, etc.
|
|
11
|
-
- [ ] Implement memoization for evaluated values
|
|
12
|
-
|
|
13
|
-
### Validation Type
|
|
14
|
-
|
|
15
|
-
- [ ] Create `Validation` data type for applicative validation
|
|
16
|
-
- [ ] Support collecting multiple errors (unlike Either which short-circuits)
|
|
17
|
-
- [ ] Add utilities for combining validation results
|
|
18
|
-
|
|
19
|
-
### Performance Foundation
|
|
20
|
-
|
|
21
|
-
- [ ] Add memoization utilities for expensive function calls
|
|
22
|
-
- [ ] Implement a basic benchmarking suite for measuring performance
|
|
23
|
-
- [ ] Standardize performance metrics across data structures
|
|
24
|
-
|
|
25
|
-
## Q3 2025: Advanced Functional Patterns & Optimizations
|
|
26
|
-
|
|
27
|
-
### Type Classes
|
|
28
|
-
|
|
29
|
-
- [x] Implement `Foldable` typeclass with fold, foldLeft, and foldRight methods
|
|
30
|
-
- [x] Implement `Matchable` typeclass for pattern matching
|
|
31
|
-
- [ ] Implement proper `Functor` and `Monad` typeclasses
|
|
32
|
-
- [ ] Add `Applicative` typeclass
|
|
33
|
-
- [ ] Support `Traversable` with comprehensive HKT
|
|
34
|
-
|
|
35
|
-
### Monad Implementations
|
|
36
|
-
|
|
37
|
-
- [ ] Implement `Reader` monad for dependency injection
|
|
38
|
-
- [ ] Add `State` monad for managing state transformations
|
|
39
|
-
- [ ] Create `IO` monad for pure handling of side effects
|
|
40
|
-
- [ ] Add comprehensive documentation and examples
|
|
41
|
-
|
|
42
|
-
### Performance Improvements
|
|
43
|
-
|
|
44
|
-
- [ ] Implement structural sharing for immutable collections
|
|
45
|
-
- [ ] Optimize recursive operations for large data structures
|
|
46
|
-
- [ ] Add performance comparison against other FP libraries
|
|
47
|
-
|
|
48
|
-
### Lenses & Optics
|
|
49
|
-
|
|
50
|
-
- [ ] Implement lens abstraction for immutable updates
|
|
51
|
-
- [ ] Add prism implementation for optional data
|
|
52
|
-
- [ ] Create utilities for composing lenses and prisms
|
|
53
|
-
|
|
54
|
-
## Q4 2025: TypeScript Enhancements & API Consistency
|
|
55
|
-
|
|
56
|
-
### TypeScript Integration
|
|
57
|
-
|
|
58
|
-
- [x] Add support for higher-kinded types
|
|
59
|
-
- [ ] Remove `any` from HKT
|
|
60
|
-
- [x] Implement branded/nominal types for stronger type safety
|
|
61
|
-
- [ ] Add type-level utilities using newer TypeScript features
|
|
62
|
-
- [ ] Leverage const type parameters and tuple manipulation
|
|
63
|
-
|
|
64
|
-
### API Normalization
|
|
65
|
-
|
|
66
|
-
- [ ] Review and standardize API across all modules
|
|
67
|
-
- [ ] Ensure consistent implementation of the Scala-inspired pattern
|
|
68
|
-
- [ ] Standardize import patterns (@imports throughout)
|
|
69
|
-
- [ ] Create migration guides for API changes
|
|
70
|
-
|
|
71
|
-
## Q1 2026: Testing, Documentation & Community Support
|
|
72
|
-
|
|
73
|
-
### Testing Expansion
|
|
74
|
-
|
|
75
|
-
- [ ] Add test coverage metrics and set coverage goals
|
|
76
|
-
- [ ] Expand property-based testing across all modules
|
|
77
|
-
- [ ] Create interoperability tests with popular libraries
|
|
78
|
-
- [ ] Add more specialized test cases for error handling
|
|
79
|
-
|
|
80
|
-
### Documentation & Examples
|
|
81
|
-
|
|
82
|
-
- [ ] Add comprehensive documentation for all modules
|
|
83
|
-
- [ ] Create step-by-step migration guides from imperative to functional
|
|
84
|
-
- [ ] Add real-world examples showcasing practical applications
|
|
85
|
-
- [ ] Create tutorial sections for beginners
|
|
86
|
-
|
|
87
|
-
### Community Engagement
|
|
88
|
-
|
|
89
|
-
- [ ] Create contribution guidelines and templates
|
|
90
|
-
- [ ] Set up automated issue/PR handling
|
|
91
|
-
- [ ] Establish regular release schedule
|
|
92
|
-
- [ ] Add community forum/discussion platform
|
|
93
|
-
|
|
94
|
-
## Ongoing Priorities
|
|
95
|
-
|
|
96
|
-
### Compatibility
|
|
97
|
-
|
|
98
|
-
- [ ] Ensure compatibility with Node.js LTS versions
|
|
99
|
-
- [ ] Maintain browser compatibility
|
|
100
|
-
- [ ] Support for Deno and other runtimes
|
|
101
|
-
- [ ] Test with various bundlers (webpack, esbuild, etc.)
|
|
102
|
-
|
|
103
|
-
### Bundle Size
|
|
104
|
-
|
|
105
|
-
- [x] Optimize tree-shaking
|
|
106
|
-
- [x] Provide guidance on importing only needed modules
|
|
107
|
-
- [x] Add bundle size monitoring to CI/CD
|
|
108
|
-
|
|
109
|
-
### Community Feedback
|
|
110
|
-
|
|
111
|
-
- [ ] Regular review of GitHub issues and feature requests
|
|
112
|
-
- [ ] Prioritization based on community needs
|
|
113
|
-
- [ ] Transparent development process
|
package/readme/TASK-TODO.md
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# Task TODO
|
|
2
|
-
|
|
3
|
-
## Goals
|
|
4
|
-
|
|
5
|
-
- Enhance the Task module as an adapter between promise-based code and functional patterns
|
|
6
|
-
- Improve interoperability with existing JavaScript/TypeScript codebases
|
|
7
|
-
- Allow gradual migration to functional patterns without complete rewrites
|
|
8
|
-
|
|
9
|
-
## Implementation Tasks
|
|
10
|
-
|
|
11
|
-
- [x] Review current Task implementation for completeness of promise integration
|
|
12
|
-
- [x] Ensure robust error handling in sync/async conversions
|
|
13
|
-
- [x] Document explicit try/catch/finally semantics
|
|
14
|
-
- [x] Add examples showing migration from promise-based to functional patterns
|
|
15
|
-
- [x] Add utilities to simplify Task composition with promise-returning functions
|
|
16
|
-
- [x] Create migration guide for converting promise chains to Task operations
|
|
17
|
-
|
|
18
|
-
## Design Considerations
|
|
19
|
-
|
|
20
|
-
- Maintain clear separation between synchronous and promise-based operations
|
|
21
|
-
- Preserve functional error handling patterns while supporting promise interop
|
|
22
|
-
- Keep API consistent with the rest of the library's functional approach
|
|
23
|
-
|
|
24
|
-
## Completed Enhancements
|
|
25
|
-
|
|
26
|
-
- Added `fromPromise` adapter to convert promise-returning functions to Task-compatible functions
|
|
27
|
-
- Added `toPromise` converter to transform Task results back to promises
|
|
28
|
-
- Enhanced documentation with clearer descriptions of functionality
|
|
29
|
-
- Created TaskMigration.md guide showing how to migrate from promises to functional Task patterns
|
|
30
|
-
- Added comprehensive tests for the new adapter methods
|
|
31
|
-
- Improved error handler behavior to ensure handlers are always called, even for TaggedThrowable errors
|
|
32
|
-
- Enhanced error chaining to preserve context while supporting logging in error handlers
|
|
33
|
-
- Added test coverage to verify error handlers are always called for all error types
|
package/readme/TUPLE-EXAMPLES.md
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# Tuple Enhanced with Modern TypeScript Features
|
|
2
|
-
|
|
3
|
-
## What's Improved
|
|
4
|
-
|
|
5
|
-
Our enhanced `Tuple` implementation leverages modern TypeScript features:
|
|
6
|
-
|
|
7
|
-
1. **Const type parameters** (TypeScript 5.0+)
|
|
8
|
-
2. **Variadic tuple types** (TypeScript 4.0+)
|
|
9
|
-
3. **Stronger type inference** for tuple elements
|
|
10
|
-
|
|
11
|
-
## Examples
|
|
12
|
-
|
|
13
|
-
### Basic Usage
|
|
14
|
-
|
|
15
|
-
```typescript
|
|
16
|
-
import { Tuple } from "@/tuple"
|
|
17
|
-
|
|
18
|
-
// Create a tuple with mixed types
|
|
19
|
-
const personTuple = Tuple(["John Doe", 42, true])
|
|
20
|
-
|
|
21
|
-
// Access values with type safety
|
|
22
|
-
const name = personTuple.get(0) // Type is string
|
|
23
|
-
const age = personTuple.get(1) // Type is number
|
|
24
|
-
const active = personTuple.get(2) // Type is boolean
|
|
25
|
-
|
|
26
|
-
// Transform the tuple
|
|
27
|
-
const mapped = personTuple.map((values) => values.map((x) => (typeof x === "number" ? x * 2 : x)))
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### Preserving Literal Types
|
|
31
|
-
|
|
32
|
-
```typescript
|
|
33
|
-
// Using 'as const' with the enhanced implementation
|
|
34
|
-
const literalTuple = Tuple([1, "hello", true] as const)
|
|
35
|
-
|
|
36
|
-
// TypeScript now knows the exact types:
|
|
37
|
-
const first = literalTuple.get(0) // Type is exactly 1 (not just number)
|
|
38
|
-
const second = literalTuple.get(1) // Type is exactly 'hello' (not just string)
|
|
39
|
-
const third = literalTuple.get(2) // Type is exactly true (not just boolean)
|
|
40
|
-
|
|
41
|
-
// Benefits:
|
|
42
|
-
// - Better type checking
|
|
43
|
-
// - Autocomplete shows exact values
|
|
44
|
-
// - Prevents invalid index access
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### Type-Level Utilities (for future improvements)
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
// Example of potential future type utilities
|
|
51
|
-
type FirstElement<T extends Tuple<unknown[]>> = T extends Tuple<[infer F, ...unknown[]]> ? F : never
|
|
52
|
-
|
|
53
|
-
// Extract first element's type
|
|
54
|
-
type First = FirstElement<typeof literalTuple> // Would be 1
|
|
55
|
-
|
|
56
|
-
// Could expand to other utilities like:
|
|
57
|
-
// - LastElement
|
|
58
|
-
// - RemoveFirst
|
|
59
|
-
// - Prepend<T, Item>
|
|
60
|
-
// - etc.
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
## When Is This Useful?
|
|
64
|
-
|
|
65
|
-
1. **Strong typing for heterogeneous collections**:
|
|
66
|
-
- When you need to store different types in a fixed structure
|
|
67
|
-
- When you want type safety beyond what arrays provide
|
|
68
|
-
|
|
69
|
-
2. **APIs returning fixed-length, mixed-type results**:
|
|
70
|
-
- When a function returns multiple values of different types
|
|
71
|
-
|
|
72
|
-
3. **Data transformation pipelines**:
|
|
73
|
-
- When you need to transform data while preserving type information
|
|
74
|
-
|
|
75
|
-
4. **Configuration objects with fixed format**:
|
|
76
|
-
- When config must follow a specific format with specific types at each position
|
package/readme/ai-guide.md
DELETED
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
# AI Guide to Functype
|
|
2
|
-
|
|
3
|
-
This document provides a concise reference for AI models to understand the patterns and usage of the Functype library.
|
|
4
|
-
|
|
5
|
-
## Core Types
|
|
6
|
-
|
|
7
|
-
### Option<T>
|
|
8
|
-
|
|
9
|
-
```typescript
|
|
10
|
-
// Create: Option(value) returns Some(value) or None
|
|
11
|
-
const some = Option(42) // Some(42)
|
|
12
|
-
const none = Option(null) // None
|
|
13
|
-
|
|
14
|
-
// Access: .get() or .orElse(default)
|
|
15
|
-
some.get() // 42
|
|
16
|
-
none.orElse("default") // "default"
|
|
17
|
-
|
|
18
|
-
// Transform: .map(), .flatMap(), .filter()
|
|
19
|
-
some.map((x) => x * 2) // Some(84)
|
|
20
|
-
some.flatMap((x) => Option(x.toString())) // Some("42")
|
|
21
|
-
some.filter((x) => x > 50) // None
|
|
22
|
-
|
|
23
|
-
// Pattern match: .fold() or .match()
|
|
24
|
-
some.fold(
|
|
25
|
-
() => "empty",
|
|
26
|
-
(val) => `value: ${val}`,
|
|
27
|
-
) // "value: 42"
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### Either<L, R>
|
|
31
|
-
|
|
32
|
-
```typescript
|
|
33
|
-
// Create: Right(value) or Left(error)
|
|
34
|
-
const right = Right<string, number>(42)
|
|
35
|
-
const left = Left<string, number>("error")
|
|
36
|
-
|
|
37
|
-
// From functions: Either.tryCatch()
|
|
38
|
-
const result = Either.tryCatch(
|
|
39
|
-
() => JSON.parse('{"key":"value"}'),
|
|
40
|
-
(err) => `Parse error: ${err}`,
|
|
41
|
-
) // Right({key: "value"})
|
|
42
|
-
|
|
43
|
-
// Transform: .map(), .mapLeft(), .flatMap()
|
|
44
|
-
right.map((x) => x * 2) // Right(84)
|
|
45
|
-
left.mapLeft((e) => e.toUpperCase()) // Left("ERROR")
|
|
46
|
-
right.flatMap((x) => Right(x.toString())) // Right("42")
|
|
47
|
-
|
|
48
|
-
// Pattern match: .fold() or .match()
|
|
49
|
-
right.fold(
|
|
50
|
-
(err) => `Error: ${err}`,
|
|
51
|
-
(val) => `Success: ${val}`,
|
|
52
|
-
) // "Success: 42"
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### Try<T>
|
|
56
|
-
|
|
57
|
-
```typescript
|
|
58
|
-
// Create: Try(() => potentially_throwing_function())
|
|
59
|
-
const success = Try(() => 42)
|
|
60
|
-
const failure = Try(() => {
|
|
61
|
-
throw new Error("Failed")
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
// Transform: .map(), .flatMap(), .recover()
|
|
65
|
-
success.map((x) => x * 2) // Success(84)
|
|
66
|
-
failure.recover("default") // Success("default")
|
|
67
|
-
success.flatMap((x) => Try(() => x.toString())) // Success("42")
|
|
68
|
-
|
|
69
|
-
// Pattern match: .fold() or .match()
|
|
70
|
-
success.fold(
|
|
71
|
-
(err) => `Error: ${err.message}`,
|
|
72
|
-
(val) => `Success: ${val}`,
|
|
73
|
-
) // "Success: 42"
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### List<T>
|
|
77
|
-
|
|
78
|
-
```typescript
|
|
79
|
-
// Create: List([...elements])
|
|
80
|
-
const list = List([1, 2, 3, 4, 5])
|
|
81
|
-
|
|
82
|
-
// Access: .head(), .tail(), .at(index)
|
|
83
|
-
list.head() // Some(1)
|
|
84
|
-
list.tail() // List([2, 3, 4, 5])
|
|
85
|
-
|
|
86
|
-
// Transform: .map(), .flatMap(), .filter()
|
|
87
|
-
list.map((x) => x * 2) // List([2, 4, 6, 8, 10])
|
|
88
|
-
list.filter((x) => x % 2 === 0) // List([2, 4])
|
|
89
|
-
list.flatMap((x) => List([x, x])) // List([1, 1, 2, 2, 3, 3, 4, 4, 5, 5])
|
|
90
|
-
|
|
91
|
-
// Reduce: .foldLeft(), .foldRight()
|
|
92
|
-
list.foldLeft(0)((acc, x) => acc + x) // 15
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### Map<K, V>
|
|
96
|
-
|
|
97
|
-
```typescript
|
|
98
|
-
// Create: Map({key: value})
|
|
99
|
-
const map = Map({ a: 1, b: 2, c: 3 })
|
|
100
|
-
|
|
101
|
-
// Access: .get(key), .orElse(key, default)
|
|
102
|
-
map.get("a") // Some(1)
|
|
103
|
-
map.orElse("d", 0) // 0
|
|
104
|
-
|
|
105
|
-
// Transform: .map(), .filter()
|
|
106
|
-
map.map((v) => v * 2) // Map({a: 2, b: 4, c: 6})
|
|
107
|
-
map.filter((v) => v > 1) // Map({b: 2, c: 3})
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### Set<T>
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
// Create: Set([...elements])
|
|
114
|
-
const set = Set([1, 2, 3, 4, 5])
|
|
115
|
-
|
|
116
|
-
// Operations: .add(), .remove(), .has()
|
|
117
|
-
set.add(6) // Set([1, 2, 3, 4, 5, 6])
|
|
118
|
-
set.remove(3) // Set([1, 2, 4, 5])
|
|
119
|
-
set.has(2) // true
|
|
120
|
-
|
|
121
|
-
// Set operations: .union(), .intersect(), .difference()
|
|
122
|
-
const set2 = Set([4, 5, 6, 7])
|
|
123
|
-
set.union(set2) // Set([1, 2, 3, 4, 5, 6, 7])
|
|
124
|
-
set.intersect(set2) // Set([4, 5])
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
### Task
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
// Create: Task().Sync() or Task().Async()
|
|
131
|
-
const syncTask = Task().Sync(
|
|
132
|
-
() => 42,
|
|
133
|
-
(err) => new Error(`Failed: ${err}`),
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
const asyncTask = Task().Async(
|
|
137
|
-
async () => await fetchData(),
|
|
138
|
-
async (err) => new Error(`Fetch failed: ${err}`),
|
|
139
|
-
)
|
|
140
|
-
|
|
141
|
-
// From promise
|
|
142
|
-
const fetchUser = Task({ name: "UserFetch" }).fromPromise(fetchUserAPI)
|
|
143
|
-
|
|
144
|
-
// Usage
|
|
145
|
-
syncTask.then((value) => console.log(value)).catch((error) => console.error(error))
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### Tuple
|
|
149
|
-
|
|
150
|
-
```typescript
|
|
151
|
-
// Create: Tuple(...values)
|
|
152
|
-
const pair = Tuple(42, "hello")
|
|
153
|
-
|
|
154
|
-
// Access: .first(), .second(), etc.
|
|
155
|
-
pair.first() // 42
|
|
156
|
-
pair.second() // "hello"
|
|
157
|
-
|
|
158
|
-
// Transform: .map(), .mapFirst(), .mapSecond()
|
|
159
|
-
pair.mapFirst((x) => x * 2) // Tuple(84, "hello")
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
## Common Patterns
|
|
163
|
-
|
|
164
|
-
### Type Safety
|
|
165
|
-
|
|
166
|
-
```typescript
|
|
167
|
-
// Branded types
|
|
168
|
-
type UserId = Brand<string, "UserId">
|
|
169
|
-
const UserId = (id: string): UserId => {
|
|
170
|
-
if (!/^U\d{6}$/.test(id)) throw new Error("Invalid ID format")
|
|
171
|
-
return id as UserId
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// Type-safe functions
|
|
175
|
-
function getUserById(id: UserId): User {
|
|
176
|
-
/* ... */
|
|
177
|
-
}
|
|
178
|
-
getUserById(UserId("U123456")) // Works
|
|
179
|
-
getUserById("U123456") // Type error
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
### Error Handling
|
|
183
|
-
|
|
184
|
-
```typescript
|
|
185
|
-
// Option for nullable values
|
|
186
|
-
const maybeUser = Option(findUser(id))
|
|
187
|
-
maybeUser.fold(
|
|
188
|
-
() => console.log("User not found"),
|
|
189
|
-
(user) => console.log("User:", user.name),
|
|
190
|
-
)
|
|
191
|
-
|
|
192
|
-
// Either for errors with context
|
|
193
|
-
const validationResult = validateForm(formData)
|
|
194
|
-
validationResult.fold(
|
|
195
|
-
(errors) => handleErrors(errors),
|
|
196
|
-
(data) => processForm(data),
|
|
197
|
-
)
|
|
198
|
-
|
|
199
|
-
// Try for exception safety
|
|
200
|
-
const parseResult = Try(() => JSON.parse(input))
|
|
201
|
-
parseResult.fold(
|
|
202
|
-
(err) => console.error("Parse error:", err.message),
|
|
203
|
-
(data) => console.log("Data:", data),
|
|
204
|
-
)
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
### Chaining Operations
|
|
208
|
-
|
|
209
|
-
```typescript
|
|
210
|
-
// Option chain
|
|
211
|
-
const userCity = Option(user)
|
|
212
|
-
.flatMap((u) => Option(u.address))
|
|
213
|
-
.flatMap((a) => Option(a.city))
|
|
214
|
-
.orElse("Unknown")
|
|
215
|
-
|
|
216
|
-
// Either chain
|
|
217
|
-
parseInput(input)
|
|
218
|
-
.flatMap(validateData)
|
|
219
|
-
.flatMap(transformData)
|
|
220
|
-
.fold(
|
|
221
|
-
(err) => handleError(err),
|
|
222
|
-
(result) => displayResult(result),
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
// List processing
|
|
226
|
-
List([1, 2, 3, 4, 5])
|
|
227
|
-
.filter((n) => n % 2 === 0)
|
|
228
|
-
.map((n) => n * n)
|
|
229
|
-
.foldLeft(0)((acc, n) => acc + n) // 20 (4 + 16)
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
### Pattern Matching
|
|
233
|
-
|
|
234
|
-
```typescript
|
|
235
|
-
// Using match method
|
|
236
|
-
result.match({
|
|
237
|
-
Some: (value) => `Found: ${value}`,
|
|
238
|
-
None: () => "Not found",
|
|
239
|
-
})
|
|
240
|
-
|
|
241
|
-
// Using fold method
|
|
242
|
-
either.fold(
|
|
243
|
-
(left) => `Error: ${left}`,
|
|
244
|
-
(right) => `Success: ${right}`,
|
|
245
|
-
)
|
|
246
|
-
|
|
247
|
-
// Using MatchableUtils
|
|
248
|
-
const isPositive = MatchableUtils.when(
|
|
249
|
-
(n: number) => n > 0,
|
|
250
|
-
(n) => `Positive: ${n}`,
|
|
251
|
-
)
|
|
252
|
-
|
|
253
|
-
const isNegative = MatchableUtils.when(
|
|
254
|
-
(n: number) => n < 0,
|
|
255
|
-
(n) => `Negative: ${n}`,
|
|
256
|
-
)
|
|
257
|
-
|
|
258
|
-
const defaultCase = MatchableUtils.default((n: number) => `Zero: ${n}`)
|
|
259
|
-
|
|
260
|
-
// Usage
|
|
261
|
-
isPositive(42) ?? isNegative(42) ?? defaultCase(42) // "Positive: 42"
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
### Functional Composition
|
|
265
|
-
|
|
266
|
-
```typescript
|
|
267
|
-
// Using pipe for sequential operations
|
|
268
|
-
import { pipe } from "functype"
|
|
269
|
-
|
|
270
|
-
const result = pipe(
|
|
271
|
-
Option(input),
|
|
272
|
-
(opt) => opt.map((s) => s.trim()),
|
|
273
|
-
(opt) => opt.filter((s) => s.length > 0),
|
|
274
|
-
(opt) => opt.map((s) => parseInt(s, 10)),
|
|
275
|
-
(opt) => opt.filter((n) => !isNaN(n)),
|
|
276
|
-
(opt) => opt.orElse(0),
|
|
277
|
-
)
|
|
278
|
-
|
|
279
|
-
// Converting between types
|
|
280
|
-
import { FoldableUtils } from "functype"
|
|
281
|
-
|
|
282
|
-
const optionAsList = FoldableUtils.toList(option)
|
|
283
|
-
const listAsOption = FoldableUtils.toOption(list)
|
|
284
|
-
const tryAsEither = FoldableUtils.toEither(tryVal, "Default error")
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
## Key Principles
|
|
288
|
-
|
|
289
|
-
1. **Immutability**: All data structures return new instances when modified
|
|
290
|
-
2. **Type Safety**: Strong TypeScript typing throughout the library
|
|
291
|
-
3. **Null Safety**: No null/undefined values within containers (Option, Either, etc.)
|
|
292
|
-
4. **Error Handling**: Explicit error handling using functional patterns
|
|
293
|
-
5. **Pattern Matching**: Consistent APIs for inspecting and handling variants
|
|
294
|
-
6. **Composability**: Methods designed for chaining and composition
|
|
295
|
-
7. **Consistency**: Similar patterns across different data structures
|
|
296
|
-
|
|
297
|
-
## Common Imports
|
|
298
|
-
|
|
299
|
-
```typescript
|
|
300
|
-
// Full package import (not recommended for production)
|
|
301
|
-
import { Option, Either, Try, List } from "functype"
|
|
302
|
-
|
|
303
|
-
// Optimized imports for tree-shaking
|
|
304
|
-
import { Option } from "functype/option"
|
|
305
|
-
import { Either } from "functype/either"
|
|
306
|
-
import { List } from "functype/list"
|
|
307
|
-
|
|
308
|
-
// Individual constructor imports
|
|
309
|
-
import { some, none } from "functype/option"
|
|
310
|
-
import { right, left } from "functype/either"
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
## Type Class Hierarchy
|
|
314
|
-
|
|
315
|
-
- **Functor**: `map` - Transform values while preserving structure
|
|
316
|
-
- **Applicative**: Apply functions inside containers
|
|
317
|
-
- **Monad**: `flatMap` - Chain operations that return containerized values
|
|
318
|
-
- **Foldable**: `fold`, `foldLeft`, `foldRight` - Collapse structure
|
|
319
|
-
- **Traversable**: Convert/sequence containers
|
|
320
|
-
|
|
321
|
-
## Anti-Patterns to Avoid
|
|
322
|
-
|
|
323
|
-
1. ❌ **Unnecessary Unwrapping**:
|
|
324
|
-
|
|
325
|
-
```typescript
|
|
326
|
-
// Bad
|
|
327
|
-
if (option.isDefined()) {
|
|
328
|
-
doSomething(option.get())
|
|
329
|
-
} else {
|
|
330
|
-
doSomethingElse()
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// Good
|
|
334
|
-
option.fold(
|
|
335
|
-
() => doSomethingElse(),
|
|
336
|
-
(value) => doSomething(value),
|
|
337
|
-
)
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
2. ❌ **Throwing from Inside Containers**:
|
|
341
|
-
|
|
342
|
-
```typescript
|
|
343
|
-
// Bad
|
|
344
|
-
option.map((value) => {
|
|
345
|
-
if (!isValid(value)) throw new Error("Invalid")
|
|
346
|
-
return transform(value)
|
|
347
|
-
})
|
|
348
|
-
|
|
349
|
-
// Good
|
|
350
|
-
option.flatMap((value) => (isValid(value) ? Option(transform(value)) : Option(null)))
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
3. ❌ **Not Using Composition**:
|
|
354
|
-
|
|
355
|
-
```typescript
|
|
356
|
-
// Bad
|
|
357
|
-
const a = option.map((x) => x + 1)
|
|
358
|
-
const b = a.filter((x) => x > 10)
|
|
359
|
-
const c = b.orElse(0)
|
|
360
|
-
|
|
361
|
-
// Good
|
|
362
|
-
const result = option
|
|
363
|
-
.map((x) => x + 1)
|
|
364
|
-
.filter((x) => x > 10)
|
|
365
|
-
.orElse(0)
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
4. ❌ **Mixing Imperative and Functional Styles**:
|
|
369
|
-
|
|
370
|
-
```typescript
|
|
371
|
-
// Bad
|
|
372
|
-
let result = 0
|
|
373
|
-
option.fold(
|
|
374
|
-
() => {
|
|
375
|
-
result = 42
|
|
376
|
-
},
|
|
377
|
-
(value) => {
|
|
378
|
-
result = value
|
|
379
|
-
},
|
|
380
|
-
)
|
|
381
|
-
|
|
382
|
-
// Good
|
|
383
|
-
const result = option.orElse(42)
|
|
384
|
-
```
|