An educational pure functional programming library in TypeScript
Changelog#
All notable changes to this project will be documented in this file.
[0.1.0-alpha.15] - 2026-04-18#
Fixed#
traverseResult/traverseOptionmutation and early returns — rewritten as purereducefolds overResult<readonly B[], E>/Option<readonly B[]>accumulators, removing the mutable local arrays and multi-return control flow that violated the project's FP rulesapOption/liftA2OptionrawNoneliterals — now use the exportednonesingleton for referential-identity consistency withmapOption/flatMapOption
Changed#
- Exit namespace consolidated — removed the
Exit.succeed/Exit.fail/Exit.interruptaliases; use the canonicalExit.success/Exit.failure/Exit.interruptedinstead. Examples and docs-site updated accordingly.
Documentation#
- Collapsed duplicate "Type Class Interfaces" section headers in
prelude/typeclasses.tsand removed the redundant HKT paragraph already covered by the module docstring
[0.1.0-alpha.14] - 2026-04-03#
Fixed#
- Bracket resource leak on fiber interruption — release handlers now run when a fiber is interrupted during async
usephase, preventing resource leaks - Unsafe
toResultnon-null assertion —invalid()now requires at least one error (readonly [E, ...E[]]), eliminating theerrors[0]!assertion that could produceundefined matchValidationerror type —onInvalidcallback now receivesreadonly [E, ...E[]]matching theInvalidtype
Removed#
- Duplicate
eachTraversalfrom bridges module — useeach()from the traversal module instead
Added#
- 35 new tests (414 total)
- Bracket + fiber interruption tests verifying release runs and exit is
Interrupted yieldNowandfiberIdtest coverage- 8 additional optics
composeoverload tests (prism+lens, prism+prism, lens+optional, optional+lens, optional+optional, lens+traversal, traversal+lens, prism+optional) - Optional algebraic law tests (getOption-set, set-getOption)
- Traversal algebraic law tests (identity, composition)
- Bracket + fiber interruption tests verifying release runs and exit is
[0.1.0-alpha.13] - 2026-03-19#
Added#
- Optics module (
src/optics/) — composable, law-abiding immutable data accessors- Lens — focus on a value that always exists (
view,set,over,prop) - Prism — focus on a sum type variant (
preview,review) - Optional — focus that may be absent (
getOption,setOptional,modifyOptional,index) - Traversal — focus on many values (
getAll,modifyTraversal,each) - Type-safe
compose— 16 overloads enforcing composition rules (Lens+Lens=Lens, Lens+Prism=Optional, etc.) - Bridges — pre-built optics for Result (
okPrism,errPrism), Option (somePrism), Validation (validPrism) - 44 law-based tests verifying get-set, set-get, set-set, preview-review, and review-preview laws
- Lens — focus on a value that always exists (
[0.1.0-alpha.12] - 2026-02-28#
Fixed#
ifElseinverted arguments —onTruewas called when predicate was false and vice versa; swapped parameter order and ternary to match namingmatchLiteralsoundness gap — Split into exhaustivematchLiteral(requires all cases) and partialmatchLiteralOr(with default fallback)- Fiber interrupt doesn't cancel async — Interrupt now calls cleanup on in-flight async operations and force-resolves blocked promises
zipfiber leak — When the second effect fails, the first fiber is now interrupted instead of being abandonedtraverseResultunnecessary cast — Removed redundantas unknown asdouble-cast; TypeScript narrows correctly- Generic guards missing type predicates — Added explicit
: x is Tannotations toisDefined,isNotNull,isNotNullish(TS 5.5 inference doesn't apply to generics) - Interpreter null assertion — Replaced
result!with null guard in Blocked handler's next thunk - Documentation:
race()array syntax — Fixedrace([fast, slow])torace(fast, slow)in testing strategies - Documentation: timeout test — Fixed test to expect
Success(null)instead ofFailureon timeout - Documentation:
yield*pseudo-code — Replaced generator syntax with actualpipe/flatMapin fiber example - Documentation:
all()return type — Corrected type comment from tuple to union array - Documentation: dead link — Fixed
/concepts/01-branded-types-and-refinements/to/concepts/02-branded-types/ - Examples: comma-expression patterns — Replaced
(sideEffect, expr)with explicit block bodies in http-client and task-queue - Examples: redundant
ascasts — Removed unnecessaryas MessageErrorcasts in forest-election story - Documentation: task-queue key concepts — Updated from
fork/jointoallSequential/timeout/retry - Documentation: unused imports — Removed unused
fork/joinfrom forest-election story
Added#
- 39 new tests (261 → 300 total) covering:
ifElse,matchLiteral,matchLiteralOr,mapErr,isOk/isErr,toNullable,flatMapOptionedge cases,accessEff,tapEff,repeatEff,interruptFiber,matchExit,liftA2Optionboth-None, Option Functor laws, Option Monad laws
[0.1.0-alpha.11] - 2026-02-28#
Added#
tapEffect— Effectful success tap: observe a success value with an effect-returning side-effect, discard the result, return the original value. Errors from the side-effect propagate into the error union.tapError— Effectful error tap: observe an error with an effect-returning side-effect, discard the result, re-raise the original error.tapBoth— Effectful dual tap: observe both success and failure with independent effectful handlers. Each handler can have its own error and requirement types.
Changed#
tapBothhandlers have independent type params —onSuccessandonFailurecan use different error (E2/E3) and requirement (R2/R3) types, enabling different effect types per branch.
[0.1.0-alpha.10] - 2026-02-28#
Fixed#
- Type errors in examples (stories, task-queue, user-registration)
isSet/isMapguards now returnReadonlySet/ReadonlyMapfor stricter type safetyandguard combinator returns intersection type (B & C) instead of requiringC extends B
Changed#
- Expanded guard tests (137+ assertions covering edge cases)
- Added
tsconfig.test.jsonpath mappings
[0.1.0-alpha.9] - 2026-02-07#
Added#
- Emptiness predicates —
isEmpty/isNonEmptyfor strings, arrays, Sets, Maps, and objects - Uses FP naming convention (
isNonEmptymirrors theNonEmptytype from Haskell/Scala/PureScript)
[0.1.0-alpha.8] - 2026-02-07#
Added#
- Docs site — Astro Starlight documentation site with tutorials, concepts, stories, and examples
- Nullability guards —
isDefined,isNotNull,isNotNullishfor piping and filtering hasPropertiesguard — Multi-property object checking:hasProperties("id", "name", "email")(data)- Recursion over loops concept article — Why pure functional code avoids loops and how to replace them with expressions
Changed#
- TS 5.5+ inferred type predicates — Removed redundant
: x is Tannotations from simple guards where TypeScript infers them automatically - Stricter tsconfig — Added
exactOptionalPropertyTypesandnoPropertyAccessFromIndexSignature - Replaced all
forEach/imperative loops in docs and examples withmap+join,reduce, andtest.each - Replaced
switchstatements withmatch()in story examples - Replaced manual null/undefined checks with library guards (
isDefined,isObject,hasProperties) in docs and examples
[0.1.0-alpha.7] - 2026-02-07#
Added#
- flatMap error/requirement widening —
flatMapnow automatically unions error and requirement types across composed effects, removing the need for manual type annotations - matchOn / matchOnOr — Pattern matching on custom discriminant fields (not just
_tag), useful for third-party types or domain events - zip / zipWith / zip3 — Typed parallel effect composition returning tuples with automatic error union
- ensure — Predicate-based failure combinator for guarding success values in pipelines
- tapErr — Error observation side effect (symmetric with
tapEff), error still propagates - traverseResult / sequenceResult — Apply a fallible function to each element and collect results, short-circuiting on first error
- traverseOption / sequenceOption — Apply an Option-returning function to each element, short-circuiting on first None
- orElseResult / orElseOption — Recover from errors or None via a fallback function
- fromNullableResult — Convert nullable values to Result with a custom error
- validate2 / validate3 / validate4 — Ergonomic combinators for combining 2-4 validations with error accumulation
- bracket — Guaranteed resource cleanup pattern (acquire/use/release) where release always runs
Changed#
flatMapsignature changed from<A, B, E, R>to split generics<A, B, E2, R2>+<E, R>for automatic widening
[0.1.0-alpha.6] - 2026-02-07#
Added#
- Beaver's Big System story trilogy teaching Branded Types, Typestate, ADTs, and Tracked Arrays
- Forest Election story trilogy teaching Validation, Result, and Effects
- Concept documentation for typestate, effects, fibers, DI, and testing
- Pattern matching examples and O(n) array documentation
[0.1.0-alpha.5] - 2026-02-06#
Added#
- Tutorial guide chapters 1-10
- Concept deep-dive articles
- Side-by-side examples (http-client, workflow-engine, task-queue)
[0.1.0-alpha.4] - 2026-02-05#
Added#
- Multi-file architecture (prelude, effect, data modules)
- Validation type with error accumulation
- Entity helpers and type guards
[0.1.0-alpha.3] - 2026-02-04#
Added#
- Effect combinators (race, all, timeout, retry, repeat)
- Fiber-based concurrency with cancellation
[0.1.0-alpha.2] - 2026-02-03#
Added#
- Effect system with typed errors and dependency injection
- Fork/join concurrency model
[0.1.0-alpha.1] - 2026-02-02#
Added#
- Initial release with Result, Option, branded types, refinements, pattern matching, tracked arrays, units, and typestate