# CLAUDE.md ## Build & Test Commands ```bash # 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 | Err`) - success/failure. Factory functions: `ok(value)`, `err(error)`. - **Option** (`Some | None`) - presence/absence. Factory functions: `some(value)`, `none()`. `none()` returns a frozen singleton. - **Query** (`OkSome | OkNone | ErrNone`) - 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`) 2. **Class implementations** for each variant (e.g. `Ok`, `Err`) 3. A **union type** alias (e.g. `type Result = Ok | Err`) 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()`) 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`) enabling direct `.value`/`.err` access after checking. - The package ships dual ESM/CJS via tsup. Entry point: `src/index.ts`.