Files
native-monad/CLAUDE.md

3.2 KiB

CLAUDE.md

Build & Test Commands

# Build (dual ESM/CJS via tsup)
pnpm build

# Test (Vitest runtime tests)
pnpm test

# Run a single test file
pnpm test -- src/option/spec/map.spec.ts

# Type-level tests (vitest typecheck, runs *.type-spec.ts files)
pnpm test:types

# Watch mode
pnpm test:watch

# Type-check without emitting
pnpm typecheck

# Lint
pnpm lint

# Format
pnpm format
pnpm format:check

Architecture

native-monad is a monad library for TypeScript that uses native JS/TS idioms (Array.prototype.map, Array.isArray, Promise.all patterns). Do not use Rust/FP naming conventions (no unwrap, orElse, inspect, getOrElse, etc.). It provides three monadic types with class-based implementations:

  • Result (Ok<T> | Err<E>) - success/failure. Factory functions: ok(value), err(error).
  • Option (Some<T> | None) - presence/absence. Factory functions: some(value), none(). none() returns a frozen singleton.
  • Query (OkSome<T> | OkNone | ErrNone<E>) - three-state monad combining Result and Option (success-with-value, success-without-value, error). Factory functions: okSome(value), okNone(), errNone(error). okNone() returns a frozen singleton.

Each module (src/result/, src/option/, src/query/) follows the same pattern:

  1. An interface defining the API contract (e.g. ResultInterface<T, E>)
  2. Class implementations for each variant (e.g. Ok<T>, Err<E>)
  3. A union type alias (e.g. type Result<T, E> = Ok<T> | Err<E>)
  4. Factory functions as lowercase creators (e.g. ok(), err())
  5. A namespace object with static collection operations (Result.all(), Result.from(), Result.partition(), Result.compact(), etc.)
  6. A Promise namespace wrapping collection operations for async usage (ResultPromise, OptionPromise, QueryPromise)

The three types are independent modules with no cross-type conversions. Users convert via match() if needed.

IMPORTANT: Banned method names. Never suggest, generate, or reference these Rust/Haskell/FP idioms — they do not exist in this library and must not be proposed as additions: unwrap, unwrapOr, unwrapOrElse, expect, or, orElse, and, andThen, inspect, getOrElse, fold, contains, zip, unzip, transpose. Use match() for value extraction and map()/flatMap() for chaining. Only use methods defined in the interfaces.

Test Conventions

There are two parallel test systems:

  • *.spec.ts - Runtime behavior tests using Vitest with Arrange/Act/Assert pattern
  • *.type-spec.ts - Compile-time type tests using vitest typecheck with expect-type (expectTypeOf(x).toEqualTypeOf<T>())

Tests are colocated in spec/ directories next to the module they test, organized by operation (e.g. map.spec.ts, filter.spec.ts, is.spec.ts).

Key Design Details

  • Falsy is defined as only null | undefined in src/util/index.ts. Values like 0, false, and "" are not considered falsy. Option.from() and Query.from() use this definition.
  • Type narrowing is central: isOk()/isErr() are type guards (this is Ok<T>) enabling direct .value/.err access after checking.
  • The package ships dual ESM/CJS via tsup. Entry point: src/index.ts.