add claude skills
This commit is contained in:
60
.claude/skills/native-monad-option/SKILL.md
Normal file
60
.claude/skills/native-monad-option/SKILL.md
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
---
|
||||||
|
name: native-monad-option
|
||||||
|
description: "Option<T> API reference. ALWAYS invoke when using Some, None, Option, OptionPromise, Option.from, Option.all, Option.partition, option.map, option.flatMap, option.match(2 args), option.filter(NO errorFactory). Do not guess Option methods — consult this skill."
|
||||||
|
---
|
||||||
|
|
||||||
|
# Option<T> Usage Guide
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
| Method | Signature (on Some) | Signature (on None) |
|
||||||
|
|-------------------------|--------------------------------|---------------------|
|
||||||
|
| `isSome()` | `this is Some<T>` | `this is never` |
|
||||||
|
| `isNone()` | `this is never` | `this is None` |
|
||||||
|
| `map(fn)` | `(fn: (v: T) => U) => Some<U>` | `() => None` |
|
||||||
|
| `flatMap(fn)` | `(fn: (v: T) => R) => R` | `() => this` |
|
||||||
|
| `match(onSome, onNone)` | 2 callbacks | 2 callbacks |
|
||||||
|
| `filter(pred)` | NO errorFactory | `() => None` |
|
||||||
|
| `toNullable()` | `T` | `null` |
|
||||||
|
| `toUndefined()` | `T` | `undefined` |
|
||||||
|
| `toString()` | `string` | `string` |
|
||||||
|
|
||||||
|
## Critical Rules
|
||||||
|
|
||||||
|
1. `match()` takes exactly **2 callbacks**: `(onSome, onNone)`.
|
||||||
|
2. `filter()` takes ONLY a predicate — NO `errorFactory` (unlike Result).
|
||||||
|
3. Option has **NO** `mapErr()` or `flatMapErr()` — those are Result/Query only.
|
||||||
|
4. `flatMap` constraint: `R extends Option<any>` — callback must return an Option.
|
||||||
|
5. Type guard: after `isSome()`, access `.value`. None has no `.value`.
|
||||||
|
6. `none()` returns a frozen singleton — do not try to construct `new None()`.
|
||||||
|
7. `Option.from()` treats only `null | undefined` as None. `0`, `false`, `""` become `Some`.
|
||||||
|
|
||||||
|
## Anti-Patterns
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// WRONG — Option.filter does NOT take errorFactory
|
||||||
|
option.filter((v) => v > 0, () => new Error("bad"));
|
||||||
|
|
||||||
|
// CORRECT — just a predicate
|
||||||
|
option.filter((v) => v > 0);
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// WRONG — mapErr does not exist on Option
|
||||||
|
option.mapErr((e) => new Error(e));
|
||||||
|
|
||||||
|
// CORRECT — Option has no error channel. Use Result if you need errors.
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// WRONG — fromNullable does not exist
|
||||||
|
Option.fromNullable(value);
|
||||||
|
|
||||||
|
// CORRECT
|
||||||
|
Option.from(value);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Namespace & Async Methods
|
||||||
|
|
||||||
|
Read `references/api-surface.md` for the complete Option namespace (`.from`, `.all`, `.partition`, `.compact`, `.some`,
|
||||||
|
`.every`) and OptionPromise namespace.
|
||||||
101
.claude/skills/native-monad-option/references/api-surface.md
Normal file
101
.claude/skills/native-monad-option/references/api-surface.md
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
# Option API Surface
|
||||||
|
|
||||||
|
These are ALL available methods for Option. Do not use any method not listed here.
|
||||||
|
|
||||||
|
## Types
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type Option<T> = Some<T> | None
|
||||||
|
type OptionPromise<T> = Promise<Option<T>>
|
||||||
|
type SomePromise<T> = Promise<Some<T>>
|
||||||
|
type NonePromise = Promise<None>
|
||||||
|
type OptionPartitionResult<T> = { values: T[]; noneCount: number }
|
||||||
|
type OptionFromType<T> = /* conditional: Some<NonNullable<T>> if T excludes null|undefined, else Option<NonNullable<T>> */
|
||||||
|
```
|
||||||
|
|
||||||
|
## Factory Functions
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
function some<T>(value: T): Some<T>
|
||||||
|
function none(): None // returns frozen singleton
|
||||||
|
```
|
||||||
|
|
||||||
|
## Some<T> Instance Methods
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class Some<T> {
|
||||||
|
readonly value: T
|
||||||
|
|
||||||
|
isSome(): this is Some<T>
|
||||||
|
isNone(): this is never
|
||||||
|
|
||||||
|
map<U>(fn: (value: T) => U): Some<U>
|
||||||
|
|
||||||
|
flatMap<R extends Option<any>>(fn: (value: T) => R): R
|
||||||
|
|
||||||
|
match<U>(onSome: (value: T) => U, onNone: () => U): U
|
||||||
|
|
||||||
|
// Overload 1: type-narrowing predicate
|
||||||
|
filter<U extends T>(predicate: (value: T) => value is U): Option<U>
|
||||||
|
// Overload 2: boolean predicate
|
||||||
|
filter(predicate: (value: T) => boolean): Option<T>
|
||||||
|
|
||||||
|
toNullable(): T
|
||||||
|
toUndefined(): T
|
||||||
|
toString(): string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## None Instance Methods
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class None {
|
||||||
|
// None has no .value property
|
||||||
|
|
||||||
|
isSome(): this is never
|
||||||
|
isNone(): this is None
|
||||||
|
|
||||||
|
map<U>(): None
|
||||||
|
|
||||||
|
flatMap(): this
|
||||||
|
|
||||||
|
match<U>(onSome: (value: never) => U, onNone: () => U): U
|
||||||
|
|
||||||
|
filter(): None
|
||||||
|
|
||||||
|
toNullable(): null
|
||||||
|
toUndefined(): undefined
|
||||||
|
toString(): string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## NOT available on Option (Result/Query only)
|
||||||
|
|
||||||
|
- `mapErr()` — does not exist
|
||||||
|
- `flatMapErr()` — does not exist
|
||||||
|
|
||||||
|
## Option Namespace (Static Methods)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
Option.from<T>(value: T): OptionFromType<T>
|
||||||
|
Option.from<T>(fn: () => T): OptionFromType<T>
|
||||||
|
Option.isOption<T>(value: unknown): value is Option<T>
|
||||||
|
Option.all<T>(options: Some<T>[]): Some<T[]>
|
||||||
|
Option.all<T>(options: Option<T>[]): Option<T[]>
|
||||||
|
Option.partition<T>(options: Option<T>[]): OptionPartitionResult<T>
|
||||||
|
Option.compact<T>(options: Option<T>[]): T[]
|
||||||
|
Option.some<T>(options: Option<T>[]): boolean
|
||||||
|
Option.every<T>(options: Option<T>[]): boolean
|
||||||
|
```
|
||||||
|
|
||||||
|
## OptionPromise Namespace (Async Methods)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
OptionPromise.from<T>(fn: () => Promise<T>): Promise<OptionFromType<T>>
|
||||||
|
OptionPromise.all<T>(promises: Promise<Some<T>>[]): Promise<Some<T[]>>
|
||||||
|
OptionPromise.all<T>(promises: Promise<Option<T>>[]): Promise<Option<T[]>>
|
||||||
|
OptionPromise.partition<T>(promises: Promise<Option<T>>[]): Promise<OptionPartitionResult<T>>
|
||||||
|
OptionPromise.compact<T>(promises: Promise<Option<T>>[]): Promise<T[]>
|
||||||
|
OptionPromise.some<T>(promises: Promise<Option<T>>[]): Promise<boolean>
|
||||||
|
OptionPromise.every<T>(promises: Promise<Option<T>>[]): Promise<boolean>
|
||||||
|
```
|
||||||
60
.claude/skills/native-monad-query/SKILL.md
Normal file
60
.claude/skills/native-monad-query/SKILL.md
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
---
|
||||||
|
name: native-monad-query
|
||||||
|
description: "Query<T,E> API reference. ALWAYS invoke when using OkSome, OkNone, ErrNone, Query, QueryPromise, Query.from, Query.all, Query.partition, query.match(3 args), query.filter(NO errorFactory). Do not guess Query methods — consult this skill."
|
||||||
|
---
|
||||||
|
|
||||||
|
# Query<T, E> Usage Guide
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
Query is a three-state monad: success-with-value (`OkSome`), success-without-value (`OkNone`), error (`ErrNone`).
|
||||||
|
|
||||||
|
| Method | OkSome | OkNone | ErrNone |
|
||||||
|
|--------|--------|--------|---------|
|
||||||
|
| `isSome()` | `this is OkSome<T>` | `this is never` | `this is never` |
|
||||||
|
| `isNone()` | `this is never` | `this is OkNone` | `this is never` |
|
||||||
|
| `isErr()` | `this is never` | `this is never` | `this is ErrNone<E>` |
|
||||||
|
| `map(fn)` | `(fn: (v: T) => U) => OkSome<U>` | `() => OkNone` | `() => ErrNone<E>` |
|
||||||
|
| `mapErr(fn)` | `() => OkSome<T>` | `() => OkNone` | `(fn: (e: E) => F) => ErrNone<F>` |
|
||||||
|
| `flatMap(fn)` | `(fn: (v: T) => R) => R` | `() => this` | `() => this` |
|
||||||
|
| `flatMapErr(fn)` | `() => this` | `() => this` | `(fn: (e: E) => R) => R` |
|
||||||
|
| `match(a, b, c)` | 3 callbacks | 3 callbacks | 3 callbacks |
|
||||||
|
| `filter(pred)` | NO errorFactory | `() => OkNone` | `() => ErrNone<E>` |
|
||||||
|
| `toNullable()` | `T` | `null` | `null` |
|
||||||
|
| `toUndefined()` | `T` | `undefined` | `undefined` |
|
||||||
|
|
||||||
|
## Critical Rules
|
||||||
|
|
||||||
|
1. `match()` takes exactly **3 callbacks**: `(onSome, onNone, onErr)` — NOT 2.
|
||||||
|
2. `filter()` takes ONLY a predicate — NO `errorFactory` (unlike Result). Failed filter returns `OkNone`, not `ErrNone`.
|
||||||
|
3. `flatMap` constraint: `R extends Query<any, any>` — callback must return a Query.
|
||||||
|
4. `flatMapErr` constraint: `R extends Query<any, any>` — callback must return a Query.
|
||||||
|
5. Type guards: `isSome()` → `.value`, `isErr()` → `.err`. `OkNone` has neither.
|
||||||
|
6. `OkSome` stores `.value`. `ErrNone` stores `.err`. `OkNone` has no data properties.
|
||||||
|
7. `okNone()` returns a frozen singleton.
|
||||||
|
|
||||||
|
## Anti-Patterns
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// WRONG — match with 2 callbacks (that's Result/Option, not Query)
|
||||||
|
query.match(onSome, onErr);
|
||||||
|
|
||||||
|
// CORRECT — Query.match always takes 3
|
||||||
|
query.match(
|
||||||
|
(value) => handleValue(value),
|
||||||
|
() => handleEmpty(),
|
||||||
|
(error) => handleError(error),
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// WRONG — filter with errorFactory (that's Result, not Query)
|
||||||
|
query.filter((v) => v > 0, () => new Error("bad"));
|
||||||
|
|
||||||
|
// CORRECT — Query.filter only takes predicate, returns OkNone on failure
|
||||||
|
query.filter((v) => v > 0);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Namespace & Async Methods
|
||||||
|
|
||||||
|
Read `references/api-surface.md` for the complete Query namespace (`.from`, `.all`, `.partition`, `.compact`, `.some`, `.every`) and QueryPromise namespace.
|
||||||
130
.claude/skills/native-monad-query/references/api-surface.md
Normal file
130
.claude/skills/native-monad-query/references/api-surface.md
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
# Query API Surface
|
||||||
|
|
||||||
|
These are ALL available methods for Query. Do not use any method not listed here.
|
||||||
|
|
||||||
|
## Types
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type Query<T, E> = OkSome<T> | OkNone | ErrNone<E>
|
||||||
|
type QueryPromise<T, E> = Promise<Query<T, E>>
|
||||||
|
type OkSomePromise<T> = Promise<OkSome<T>>
|
||||||
|
type OkNonePromise = Promise<OkNone>
|
||||||
|
type ErrNonePromise<E> = Promise<ErrNone<E>>
|
||||||
|
type QueryPartitionResult<T, E> = { values: T[]; noneCount: number; errors: E[] }
|
||||||
|
type QueryFromType<T> = /* conditional: OkSome<NonNullable<T>> if T excludes null|undefined, else OkSome<NonNullable<T>> | OkNone */
|
||||||
|
```
|
||||||
|
|
||||||
|
## Factory Functions
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
function okSome<T>(value: T): OkSome<T>
|
||||||
|
function okNone(): OkNone // returns frozen singleton
|
||||||
|
function errNone<E>(error: E): ErrNone<E>
|
||||||
|
```
|
||||||
|
|
||||||
|
## OkSome<T> Instance Methods
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class OkSome<T> {
|
||||||
|
readonly value: T
|
||||||
|
|
||||||
|
isSome(): this is OkSome<T>
|
||||||
|
isNone(): this is never
|
||||||
|
isErr(): this is never
|
||||||
|
|
||||||
|
map<U>(fn: (value: T) => U): OkSome<U>
|
||||||
|
mapErr<F>(): OkSome<T>
|
||||||
|
|
||||||
|
flatMap<R extends Query<any, any>>(fn: (value: T) => R): R
|
||||||
|
flatMapErr(): this
|
||||||
|
|
||||||
|
match<U>(onSome: (value: T) => U, onNone: () => U, onErr: (error: never) => U): U
|
||||||
|
|
||||||
|
// Overload 1: type-narrowing predicate
|
||||||
|
filter<U extends T>(predicate: (value: T) => value is U): OkSome<U> | OkNone
|
||||||
|
// Overload 2: boolean predicate
|
||||||
|
filter(predicate: (value: T) => boolean): OkSome<T> | OkNone
|
||||||
|
|
||||||
|
toNullable(): T
|
||||||
|
toUndefined(): T
|
||||||
|
toString(): string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## OkNone Instance Methods
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class OkNone {
|
||||||
|
// OkNone has no .value or .err property
|
||||||
|
|
||||||
|
isSome(): this is never
|
||||||
|
isNone(): this is OkNone
|
||||||
|
isErr(): this is never
|
||||||
|
|
||||||
|
map<U>(): OkNone
|
||||||
|
mapErr<F>(): OkNone
|
||||||
|
|
||||||
|
flatMap(): this
|
||||||
|
flatMapErr(): this
|
||||||
|
|
||||||
|
match<U>(onSome: (value: never) => U, onNone: () => U, onErr: (error: never) => U): U
|
||||||
|
|
||||||
|
filter(): OkNone
|
||||||
|
|
||||||
|
toNullable(): null
|
||||||
|
toUndefined(): undefined
|
||||||
|
toString(): string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ErrNone<E> Instance Methods
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class ErrNone<E> {
|
||||||
|
readonly err: E
|
||||||
|
|
||||||
|
isSome(): this is never
|
||||||
|
isNone(): this is never
|
||||||
|
isErr(): this is ErrNone<E>
|
||||||
|
|
||||||
|
map<U>(): ErrNone<E>
|
||||||
|
mapErr<F>(fn: (error: E) => F): ErrNone<F>
|
||||||
|
|
||||||
|
flatMap(): this
|
||||||
|
flatMapErr<R extends Query<any, any>>(fn: (error: E) => R): R
|
||||||
|
|
||||||
|
match<U>(onSome: (value: never) => U, onNone: () => U, onErr: (error: E) => U): U
|
||||||
|
|
||||||
|
filter(): ErrNone<E>
|
||||||
|
|
||||||
|
toNullable(): null
|
||||||
|
toUndefined(): undefined
|
||||||
|
toString(): string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Query Namespace (Static Methods)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
Query.from<T>(value: T): QueryFromType<T>
|
||||||
|
Query.from<T, E = unknown>(fn: () => T, errorMap?: (error: unknown) => E): QueryFromType<T> | ErrNone<E>
|
||||||
|
Query.isQuery<T, E>(value: unknown): value is Query<T, E>
|
||||||
|
Query.all<T>(queries: OkSome<T>[]): OkSome<T[]>
|
||||||
|
Query.all<T, E>(queries: Query<T, E>[]): Query<T[], E>
|
||||||
|
Query.partition<T, E>(queries: Query<T, E>[]): QueryPartitionResult<T, E>
|
||||||
|
Query.compact<T, E>(queries: Query<T, E>[]): T[]
|
||||||
|
Query.some<T, E>(queries: Query<T, E>[]): boolean
|
||||||
|
Query.every<T, E>(queries: Query<T, E>[]): boolean
|
||||||
|
```
|
||||||
|
|
||||||
|
## QueryPromise Namespace (Async Methods)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
QueryPromise.from<T, E = unknown>(fn: () => Promise<T>, errorMap?: (error: unknown) => E): Promise<QueryFromType<T> | ErrNone<E>>
|
||||||
|
QueryPromise.all<T>(promises: Promise<OkSome<T>>[]): Promise<OkSome<T[]>>
|
||||||
|
QueryPromise.all<T, E>(promises: Promise<Query<T, E>>[]): Promise<Query<T[], E>>
|
||||||
|
QueryPromise.partition<T, E>(promises: Promise<Query<T, E>>[]): Promise<QueryPartitionResult<T, E>>
|
||||||
|
QueryPromise.compact<T, E>(promises: Promise<Query<T, E>>[]): Promise<T[]>
|
||||||
|
QueryPromise.some<T, E>(promises: Promise<Query<T, E>>[]): Promise<boolean>
|
||||||
|
QueryPromise.every<T, E>(promises: Promise<Query<T, E>>[]): Promise<boolean>
|
||||||
|
```
|
||||||
54
.claude/skills/native-monad-result/SKILL.md
Normal file
54
.claude/skills/native-monad-result/SKILL.md
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
name: native-monad-result
|
||||||
|
description: "Result<T,E> API reference. ALWAYS invoke when using Ok, Err, Result, ResultPromise, Result.from, Result.all, Result.partition, result.map, result.flatMap, result.match(2 args), result.filter(needs errorFactory). Do not guess Result methods — consult this skill."
|
||||||
|
---
|
||||||
|
|
||||||
|
# Result<T, E> Usage Guide
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
| Method | Signature (on Ok) | Signature (on Err) |
|
||||||
|
|------------------------------|------------------------------|-------------------------------|
|
||||||
|
| `isOk()` | `this is Ok<T>` | `this is never` |
|
||||||
|
| `isErr()` | `this is never` | `this is Err<E>` |
|
||||||
|
| `map(fn)` | `(fn: (v: T) => U) => Ok<U>` | `() => Err<E>` |
|
||||||
|
| `mapErr(fn)` | `(fn: (e: E) => F) => Ok<T>` | `(fn: (e: E) => F) => Err<F>` |
|
||||||
|
| `flatMap(fn)` | `(fn: (v: T) => R) => R` | `() => this` |
|
||||||
|
| `flatMapErr(fn)` | `() => this` | `(fn: (e: E) => R) => R` |
|
||||||
|
| `match(onOk, onErr)` | 2 callbacks | 2 callbacks |
|
||||||
|
| `filter(pred, errorFactory)` | requires `errorFactory` | `() => Err<E>` |
|
||||||
|
| `toNullable()` | `T` | `null` |
|
||||||
|
| `toUndefined()` | `T` | `undefined` |
|
||||||
|
| `toString()` | `string` | `string` |
|
||||||
|
|
||||||
|
## Critical Rules
|
||||||
|
|
||||||
|
1. `match()` takes exactly **2 callbacks**: `(onOk, onErr)`.
|
||||||
|
2. `filter()` REQUIRES an `errorFactory` parameter — it produces `Err<F>` when the predicate fails.
|
||||||
|
3. `flatMap` constraint: `R extends Result<any, any>` — the callback must return a Result.
|
||||||
|
4. `flatMapErr` constraint: `R extends Result<any, any>` — the callback must return a Result.
|
||||||
|
5. Type guard: after `isOk()`, access `.value`. After `isErr()`, access `.err`.
|
||||||
|
6. `Ok` stores `.value`. `Err` stores `.err` (not `.error`, not `.value`).
|
||||||
|
|
||||||
|
## Anti-Patterns
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// WRONG — filter without errorFactory
|
||||||
|
result.filter((v) => v > 0);
|
||||||
|
|
||||||
|
// CORRECT — filter always needs errorFactory
|
||||||
|
result.filter((v) => v > 0, (v) => new Error(`Invalid: ${v}`));
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// WRONG — match with 3 callbacks (that's Query, not Result)
|
||||||
|
result.match(onOk, onNone, onErr);
|
||||||
|
|
||||||
|
// CORRECT — Result.match takes exactly 2
|
||||||
|
result.match(onOk, onErr);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Namespace & Async Methods
|
||||||
|
|
||||||
|
Read `references/api-surface.md` for the complete Result namespace (`.from`, `.all`, `.partition`, `.compact`, `.some`,
|
||||||
|
`.every`) and ResultPromise namespace.
|
||||||
98
.claude/skills/native-monad-result/references/api-surface.md
Normal file
98
.claude/skills/native-monad-result/references/api-surface.md
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
# Result API Surface
|
||||||
|
|
||||||
|
These are ALL available methods for Result. Do not use any method not listed here.
|
||||||
|
|
||||||
|
## Types
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type Result<T, E> = Ok<T> | Err<E>
|
||||||
|
type ResultPromise<T, E> = Promise<Result<T, E>>
|
||||||
|
type OkPromise<T> = Promise<Ok<T>>
|
||||||
|
type ErrPromise<E> = Promise<Err<E>>
|
||||||
|
type ResultPartitionResult<T, E> = { values: T[]; errors: E[] }
|
||||||
|
```
|
||||||
|
|
||||||
|
## Factory Functions
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
function ok<T>(value: T): Ok<T>
|
||||||
|
function err<E>(error: E): Err<E>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ok<T> Instance Methods
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class Ok<T> {
|
||||||
|
readonly value: T
|
||||||
|
|
||||||
|
isOk(): this is Ok<T>
|
||||||
|
isErr(): this is never
|
||||||
|
|
||||||
|
map<U>(fn: (value: T) => U): Ok<U>
|
||||||
|
mapErr<F>(fn: (error: never) => F): Ok<T>
|
||||||
|
|
||||||
|
flatMap<R extends Result<any, any>>(fn: (value: T) => R): R
|
||||||
|
flatMapErr(): this
|
||||||
|
|
||||||
|
match<U>(onOk: (value: T) => U, onErr: (error: never) => U): U
|
||||||
|
|
||||||
|
// Overload 1: type-narrowing predicate
|
||||||
|
filter<U extends T, F>(predicate: (value: T) => value is U, errorFactory: (value: T) => F): Ok<U> | Err<F>
|
||||||
|
// Overload 2: boolean predicate
|
||||||
|
filter<F>(predicate: (value: T) => boolean, errorFactory: (value: T) => F): Ok<T> | Err<F>
|
||||||
|
|
||||||
|
toNullable(): T
|
||||||
|
toUndefined(): T
|
||||||
|
toString(): string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Err<E> Instance Methods
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class Err<E> {
|
||||||
|
readonly err: E
|
||||||
|
|
||||||
|
isOk(): this is never
|
||||||
|
isErr(): this is Err<E>
|
||||||
|
|
||||||
|
map<U>(): Err<E>
|
||||||
|
mapErr<F>(fn: (error: E) => F): Err<F>
|
||||||
|
|
||||||
|
flatMap(): this
|
||||||
|
flatMapErr<R extends Result<any, any>>(fn: (error: E) => R): R
|
||||||
|
|
||||||
|
match<U>(onOk: (value: never) => U, onErr: (error: E) => U): U
|
||||||
|
|
||||||
|
filter(): Err<E>
|
||||||
|
|
||||||
|
toNullable(): null
|
||||||
|
toUndefined(): undefined
|
||||||
|
toString(): string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Result Namespace (Static Methods)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
Result.from<T, E = unknown>(fn: () => T, errorMap?: (error: unknown) => E): Result<T, E>
|
||||||
|
Result.isResult<T, E>(value: unknown): value is Result<T, E>
|
||||||
|
Result.all<T>(results: Ok<T>[]): Ok<T[]>
|
||||||
|
Result.all<T, E>(results: Result<T, E>[]): Result<T[], E>
|
||||||
|
Result.partition<T, E>(results: Result<T, E>[]): ResultPartitionResult<T, E>
|
||||||
|
Result.compact<T, E>(results: Result<T, E>[]): T[]
|
||||||
|
Result.some<T, E>(results: Result<T, E>[]): boolean
|
||||||
|
Result.every<T, E>(results: Result<T, E>[]): boolean
|
||||||
|
```
|
||||||
|
|
||||||
|
## ResultPromise Namespace (Async Methods)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
ResultPromise.from<T, E = unknown>(fn: () => Promise<T>, errorMap?: (error: unknown) => E): ResultPromise<T, E>
|
||||||
|
ResultPromise.all<T>(promises: Promise<Ok<T>>[]): Promise<Ok<T[]>>
|
||||||
|
ResultPromise.all<T, E>(promises: Promise<Result<T, E>>[]): Promise<Result<T[], E>>
|
||||||
|
ResultPromise.partition<T, E>(promises: Promise<Result<T, E>>[]): Promise<ResultPartitionResult<T, E>>
|
||||||
|
ResultPromise.compact<T, E>(promises: Promise<Result<T, E>>[]): Promise<T[]>
|
||||||
|
ResultPromise.some<T, E>(promises: Promise<Result<T, E>>[]): Promise<boolean>
|
||||||
|
ResultPromise.every<T, E>(promises: Promise<Result<T, E>>[]): Promise<boolean>
|
||||||
|
```
|
||||||
49
.claude/skills/native-monad/SKILL.md
Normal file
49
.claude/skills/native-monad/SKILL.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
name: native-monad
|
||||||
|
description: "@gs-ts/native-monad shared conventions. ALWAYS invoke when importing ok/err/some/none/okSome/okNone/errNone, using ResultPromise/OptionPromise/QueryPromise, or when tempted to write unwrap/orElse/fold/Promise<Result>. Do not write Promise<Result<T,E>> — use ResultPromise<T,E>."
|
||||||
|
---
|
||||||
|
|
||||||
|
# "@gs-ts/native-monad — Shared Conventions
|
||||||
|
|
||||||
|
## Sugar Types (MANDATORY)
|
||||||
|
|
||||||
|
Never wrap monads in raw Promise. Use these sugar types:
|
||||||
|
|
||||||
|
| Wrong | Correct | Import from |
|
||||||
|
|-------------------------|-----------------------|----------------|
|
||||||
|
| `Promise<Result<T, E>>` | `ResultPromise<T, E>` | `native-monad` |
|
||||||
|
| `Promise<Ok<T>>` | `OkPromise<T>` | `native-monad` |
|
||||||
|
| `Promise<Err<E>>` | `ErrPromise<E>` | `native-monad` |
|
||||||
|
| `Promise<Option<T>>` | `OptionPromise<T>` | `native-monad` |
|
||||||
|
| `Promise<Some<T>>` | `SomePromise<T>` | `native-monad` |
|
||||||
|
| `Promise<None>` | `NonePromise` | `native-monad` |
|
||||||
|
| `Promise<Query<T, E>>` | `QueryPromise<T, E>` | `native-monad` |
|
||||||
|
| `Promise<OkSome<T>>` | `OkSomePromise<T>` | `native-monad` |
|
||||||
|
| `Promise<OkNone>` | `OkNonePromise` | `native-monad` |
|
||||||
|
| `Promise<ErrNone<E>>` | `ErrNonePromise<E>` | `native-monad` |
|
||||||
|
|
||||||
|
## Factory Functions
|
||||||
|
|
||||||
|
| Function | Returns | Notes |
|
||||||
|
|------------------|--------------|--------------------------|
|
||||||
|
| `ok(value)` | `Ok<T>` | |
|
||||||
|
| `err(error)` | `Err<E>` | |
|
||||||
|
| `some(value)` | `Some<T>` | |
|
||||||
|
| `none()` | `None` | Returns frozen singleton |
|
||||||
|
| `okSome(value)` | `OkSome<T>` | |
|
||||||
|
| `okNone()` | `OkNone` | Returns frozen singleton |
|
||||||
|
| `errNone(error)` | `ErrNone<E>` | |
|
||||||
|
|
||||||
|
## Critical Rules
|
||||||
|
|
||||||
|
1. Use `match()` for value extraction — never invent `unwrap()` or `getOrElse()`.
|
||||||
|
2. Use `map()`/`flatMap()` for chaining — never invent `andThen()` or `chain()`.
|
||||||
|
3. Use sugar types for async return types — never write `Promise<Result<T,E>>`.
|
||||||
|
4. The three modules (Result, Option, Query) are independent — no cross-type conversions exist.
|
||||||
|
5. `Falsy` means only `null | undefined`. Values like `0`, `false`, `""` are NOT falsy.
|
||||||
|
|
||||||
|
## Anti-Patterns
|
||||||
|
|
||||||
|
Read `references/forbidden-patterns.md` for the exhaustive list of banned methods and wrong patterns.
|
||||||
|
|
||||||
|
Read `references/type-mappings.md` for the full sugar type reference.
|
||||||
74
.claude/skills/native-monad/references/forbidden-patterns.md
Normal file
74
.claude/skills/native-monad/references/forbidden-patterns.md
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# Forbidden Patterns
|
||||||
|
|
||||||
|
## Banned Method Names
|
||||||
|
|
||||||
|
These methods DO NOT EXIST in native-monad. Never suggest, generate, or reference them:
|
||||||
|
|
||||||
|
`unwrap`, `unwrapOr`, `unwrapOrElse`, `expect`, `or`, `orElse`, `and`, `andThen`,
|
||||||
|
`inspect`, `getOrElse`, `fold`, `contains`, `zip`, `unzip`, `transpose`, `chain`,
|
||||||
|
`recover`, `tap`, `peek`, `bimap`, `cata`, `either`, `maybe`, `fromNullable`,
|
||||||
|
`tryCatch`, `encase`.
|
||||||
|
|
||||||
|
## Anti-Pattern Examples
|
||||||
|
|
||||||
|
### Value extraction
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// WRONG — unwrap does not exist
|
||||||
|
const value = result.unwrap();
|
||||||
|
const value = result.unwrapOr(defaultValue);
|
||||||
|
const value = result.expect("should be ok");
|
||||||
|
|
||||||
|
// CORRECT — use match()
|
||||||
|
const value = result.match(
|
||||||
|
(v) => v,
|
||||||
|
(e) => defaultValue,
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Chaining
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// WRONG — orElse/andThen do not exist
|
||||||
|
const next = result.orElse((e) => ok(fallback));
|
||||||
|
const next = result.andThen((v) => ok(v + 1));
|
||||||
|
|
||||||
|
// CORRECT — use flatMap/flatMapErr
|
||||||
|
const next = result.flatMapErr((e) => ok(fallback));
|
||||||
|
const next = result.flatMap((v) => ok(v + 1));
|
||||||
|
```
|
||||||
|
|
||||||
|
### Async return types
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// WRONG — raw Promise wrapping
|
||||||
|
async function fetchUser(id: string): Promise<Result<User, Error>> { ... }
|
||||||
|
async function findItem(id: string): Promise<Option<Item>> { ... }
|
||||||
|
async function query(id: string): Promise<Query<Data, Error>> { ... }
|
||||||
|
|
||||||
|
// CORRECT — sugar types
|
||||||
|
async function fetchUser(id: string): ResultPromise<User, Error> { ... }
|
||||||
|
async function findItem(id: string): OptionPromise<Item> { ... }
|
||||||
|
async function query(id: string): QueryPromise<Data, Error> { ... }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Side-effect inspection
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// WRONG — inspect/tap do not exist
|
||||||
|
result.inspect((v) => console.log(v));
|
||||||
|
option.tap((v) => log(v));
|
||||||
|
|
||||||
|
// CORRECT — use map with side effect + return, or match
|
||||||
|
const logged = result.map((v) => { console.log(v); return v; });
|
||||||
|
```
|
||||||
|
|
||||||
|
### Nullability conversion
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// WRONG — fromNullable does not exist
|
||||||
|
const opt = Option.fromNullable(maybeNull);
|
||||||
|
|
||||||
|
// CORRECT — use Option.from()
|
||||||
|
const opt = Option.from(maybeNull);
|
||||||
|
```
|
||||||
36
.claude/skills/native-monad/references/type-mappings.md
Normal file
36
.claude/skills/native-monad/references/type-mappings.md
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# Type Mappings — Sugar Types
|
||||||
|
|
||||||
|
All sugar types are simple type aliases. They exist to keep signatures clean.
|
||||||
|
|
||||||
|
## Result Sugar Types
|
||||||
|
|
||||||
|
| Sugar Type | Expands To | Use When |
|
||||||
|
|------------|-----------|----------|
|
||||||
|
| `ResultPromise<T, E>` | `Promise<Result<T, E>>` | Async function returning Result |
|
||||||
|
| `OkPromise<T>` | `Promise<Ok<T>>` | Async function guaranteed to succeed |
|
||||||
|
| `ErrPromise<E>` | `Promise<Err<E>>` | Async function guaranteed to fail |
|
||||||
|
|
||||||
|
## Option Sugar Types
|
||||||
|
|
||||||
|
| Sugar Type | Expands To | Use When |
|
||||||
|
|------------|-----------|----------|
|
||||||
|
| `OptionPromise<T>` | `Promise<Option<T>>` | Async function returning Option |
|
||||||
|
| `SomePromise<T>` | `Promise<Some<T>>` | Async function guaranteed to have value |
|
||||||
|
| `NonePromise` | `Promise<None>` | Async function guaranteed to be empty |
|
||||||
|
|
||||||
|
## Query Sugar Types
|
||||||
|
|
||||||
|
| Sugar Type | Expands To | Use When |
|
||||||
|
|------------|-----------|----------|
|
||||||
|
| `QueryPromise<T, E>` | `Promise<Query<T, E>>` | Async function returning Query |
|
||||||
|
| `OkSomePromise<T>` | `Promise<OkSome<T>>` | Async function guaranteed to have value |
|
||||||
|
| `OkNonePromise` | `Promise<OkNone>` | Async function guaranteed empty-success |
|
||||||
|
| `ErrNonePromise<E>` | `Promise<ErrNone<E>>` | Async function guaranteed to error |
|
||||||
|
|
||||||
|
## Partition Result Types
|
||||||
|
|
||||||
|
| Type | Shape | Module |
|
||||||
|
|------|-------|--------|
|
||||||
|
| `ResultPartitionResult<T, E>` | `{ values: T[]; errors: E[] }` | Result |
|
||||||
|
| `OptionPartitionResult<T>` | `{ values: T[]; noneCount: number }` | Option |
|
||||||
|
| `QueryPartitionResult<T, E>` | `{ values: T[]; noneCount: number; errors: E[] }` | Query |
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
# CLAUDE.md
|
# 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
|
## Build & Test Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
11
src/option/CLAUDE.md
Normal file
11
src/option/CLAUDE.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Option conventions
|
||||||
|
|
||||||
|
- `match()` takes **2 callbacks**: `(onSome, onNone)`
|
||||||
|
- `filter()` takes ONLY a predicate — **no errorFactory** (unlike Result)
|
||||||
|
- `mapErr()` and `flatMapErr()` do **NOT exist** on Option
|
||||||
|
- `none()` returns a frozen singleton
|
||||||
|
- `Option.from()` treats only `null | undefined` as None — `0`, `false`, `""` become `Some`
|
||||||
|
- `flatMap` callback must return `Option<any>`
|
||||||
|
- Async return type: `OptionPromise<T>` — never `Promise<Option<T>>`
|
||||||
|
|
||||||
|
See `/native-monad-option` skill for full API reference.
|
||||||
11
src/query/CLAUDE.md
Normal file
11
src/query/CLAUDE.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Query conventions
|
||||||
|
|
||||||
|
- `match()` takes **3 callbacks**: `(onSome, onNone, onErr)` — NOT 2
|
||||||
|
- `filter()` takes ONLY a predicate — **no errorFactory** (unlike Result). Returns `OkNone` on failure.
|
||||||
|
- Three states: `OkSome<T>` (has `.value`), `OkNone` (no data), `ErrNone<E>` (has `.err`)
|
||||||
|
- Has `mapErr()` and `flatMapErr()` (unlike Option)
|
||||||
|
- `okNone()` returns a frozen singleton
|
||||||
|
- `flatMap`/`flatMapErr` callbacks must return `Query<any, any>`
|
||||||
|
- Async return type: `QueryPromise<T, E>` — never `Promise<Query<T, E>>`
|
||||||
|
|
||||||
|
See `/native-monad-query` skill for full API reference.
|
||||||
10
src/result/CLAUDE.md
Normal file
10
src/result/CLAUDE.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Result conventions
|
||||||
|
|
||||||
|
- `match()` takes **2 callbacks**: `(onOk, onErr)`
|
||||||
|
- `filter()` **requires errorFactory** — `filter(pred, errorFactory)` — unlike Option/Query
|
||||||
|
- `Ok` stores `.value`, `Err` stores `.err` (not `.error`)
|
||||||
|
- Has `mapErr()` and `flatMapErr()` (unlike Option)
|
||||||
|
- `flatMap`/`flatMapErr` callbacks must return `Result<any, any>`
|
||||||
|
- Async return type: `ResultPromise<T, E>` — never `Promise<Result<T, E>>`
|
||||||
|
|
||||||
|
See `/native-monad-result` skill for full API reference.
|
||||||
Reference in New Issue
Block a user