Files
native-monad/CLAUDE.md
2026-03-31 12:44:27 +02:00

71 lines
3.5 KiB
Markdown

# CLAUDE.md
## native-monad API
NEVER write `Promise<Result<T,E>>` / `Promise<Option<T>>` / `Promise<Query<T,E>>` — use `ResultPromise<T,E>` / `OptionPromise<T>` / `QueryPromise<T,E>`.
See `/native-monad-result`, `/native-monad-option`, `/native-monad-query` skills for complete API before writing monad code.
## 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<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`.