@nlozgachev/pipekit 0.1.7 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,253 +1,76 @@
1
1
  # @nlozgachev/pipekit
2
2
 
3
- [![npm](https://img.shields.io/npm/v/@nlozgachev/pipekit?style=for-the-badge&color=000&logo=npm&label&logoColor=fff)](https://www.npmjs.com/package/@nlozgachev/pipekit)[![JSR Version](https://img.shields.io/jsr/v/@nlozgachev/pipekit?style=for-the-badge&color=000&logo=jsr&label&logoColor=fff)](https://jsr.io/@nlozgachev/pipekit)[![TypeScript](https://img.shields.io/badge/-0?style=for-the-badge&color=000&logo=typescript&label&logoColor=fff)](https://www.typescriptlang.org)[![Deno](https://img.shields.io/badge/-0?style=for-the-badge&color=000&logo=Deno&label&logoColor=fff)](https://deno.com)
3
+ [![npm](https://img.shields.io/npm/v/@nlozgachev/pipekit?style=for-the-badge&color=000&logo=npm&label&logoColor=fff)](https://www.npmjs.com/package/@nlozgachev/pipekit)[![JSR Version](https://img.shields.io/jsr/v/@nlozgachev/pipekit?style=for-the-badge&color=000&logo=jsr&label&logoColor=fff)](https://jsr.io/@nlozgachev/pipekit)![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/nlozgachev/pipekit/publish.yml?style=for-the-badge&color=000&logo=githubactions&label&logoColor=fff)![Codecov](https://img.shields.io/codecov/c/github/nlozgachev/pipekit?style=for-the-badge&color=000&logo=codecov&label&logoColor=fff)[![TypeScript](https://img.shields.io/badge/-0?style=for-the-badge&color=000&logo=typescript&label&logoColor=fff)](https://www.typescriptlang.org)[![Deno](https://img.shields.io/badge/-0?style=for-the-badge&color=000&logo=Deno&label&logoColor=fff)](https://deno.com)
4
4
 
5
5
  A TypeScript toolkit for writing code that means exactly what it says.
6
6
 
7
- ## What is this?
8
-
9
- A TypeScript toolkit for expressing uncertainty precisely — absent values, fallible operations,
10
- async workflows, loading states — with types that carry their own intent and operations that
11
- compose.
12
-
13
- Most TypeScript code encodes state as flags and nullable fields: `data | null`,
14
- `error: Error | null`, `loading: boolean`. This works at small scale, but it pushes the burden of
15
- knowing which combinations are valid onto every consumer. Nothing in the type system tells you that
16
- `data` is only meaningful when `loading` is false and `error` is null — you just have to know, and
17
- check.
18
-
19
- This library takes a different approach: represent the state space precisely, then provide a small,
20
- consistent set of operations to work with it. `Option` doesn't let you access a value that might not
21
- exist without deciding what to do when it doesn't. `Result` makes it impossible to forget the error
22
- case. `RemoteData` replaces a trio of booleans with four named, mutually exclusive states. Each type
23
- comes with a module of functions — constructors, transformations, extractors — that follow the same
24
- conventions (`map`, `chain`, `match`, `getOrElse`) and work with `pipe`.
25
-
26
- The consistency means knowledge transfers: once you know `Option`, picking up `Result` or
27
- `TaskResult` is mostly recognising the same operations in a new context. The composition means logic
28
- reads in the order it executes. And precise types mean the compiler tracks what's possible — so you
29
- don't have to.
7
+ ```sh
8
+ # npm / pnpm / yarn / bun
9
+ npm add @nlozgachev/pipekit
30
10
 
31
- ## Do I need to know functional programming to use this?
11
+ # Deno
12
+ deno add jsr:@nlozgachev/pipekit
13
+ ```
32
14
 
33
- No. The library avoids FP-specific jargon wherever possible. You won't find `Monad`, `Functor`, or
34
- `Applicative` in the API. Instead, you'll work with names that describe what they do:
15
+ ## What is this?
35
16
 
36
- - `Option` a value that might not exist
37
- - `Result` — an operation that can succeed or fail
38
- - `map` — transform a value inside a container
39
- - `chain` — sequence operations that might fail
40
- - `match` — handle each case explicitly
17
+ A toolkit for expressing uncertainty precisely. Instead of `T | null`, `try/catch`, and loading state flag soup, you get types that name every possible state and make invalid ones unrepresentable. Each type comes with a consistent set of operations — `map`, `chain`, `match`, `getOrElse` — that compose with `pipe` and `flow`.
41
18
 
42
- You can start using these right away and learn the underlying concepts as you go.
19
+ No FP jargon required. You won't find `Monad`, `Functor`, or `Applicative` in the API.
43
20
 
44
21
  ## What's included?
45
22
 
46
23
  ### pipekit/Core
47
24
 
48
- Each of these is both a TypeScript type and a module of functions for working with values of that
49
- type — constructors, transformations, and ways to extract a value back out.
50
-
51
- - **`Option<A>`** — a value that might not exist. Replaces `T | null | undefined`. Key operations:
52
- `fromNullable`, `map`, `chain`, `filter`, `match`, `getOrElse`, `recover`.
53
- - **`Result<E, A>`** — an operation that succeeds with `A` or fails with `E`. Replaces `try/catch`.
54
- Key operations: `tryCatch`, `map`, `mapError`, `chain`, `match`, `getOrElse`, `recover`.
55
- - **`Validation<E, A>`** — like `Result`, but accumulates **all** errors instead of stopping at the
56
- first. Built for form validation. Key operations: `combine`, `combineAll`, `ap`, `map`, `match`.
57
- - **`Task<A>`**a lazy async operation that doesn't run until called. Key operations: `from`,
58
- `map`, `chain`, `all`, `delay`.
59
- - **`TaskResult<E, A>`** — a lazy async operation that can fail. `Task` + `Result` combined. Key
60
- operations: `tryCatch`, `map`, `mapError`, `chain`, `match`, `recover`.
61
- - **`TaskOption<A>`** — a lazy async operation that may return nothing. `Task` + `Option` combined.
62
- Replaces `Promise<T | null>`. Key operations: `tryCatch`, `map`, `chain`, `filter`, `match`,
63
- `getOrElse`, `toTaskResult`.
64
- - **`TaskValidation<E, A>`** — a lazy async operation that accumulates errors. `Task` + `Validation`
65
- combined. Use for async form validation or parallel async checks that all need to run. Key
66
- operations: `tryCatch`, `map`, `chain`, `ap`, `match`, `recover`.
67
- - **`These<E, A>`** — an inclusive-OR: holds an error, a success value, or both simultaneously.
68
- Unlike `Result` which is one or the other, `Both` carries a warning alongside a valid result — use
69
- it when partial success with diagnostics matters. Key operations: `toErr`, `toOk`, `toBoth`,
70
- `map`, `mapErr`, `bimap`, `chain`, `match`, `swap`, `toResult`.
71
- - **`RemoteData<E, A>`** — models the four states of a data fetch: `NotAsked`, `Loading`, `Failure`,
72
- `Success`. Replaces `{ data, loading, error }` flag soup. Key operations: `notAsked`, `loading`,
73
- `failure`, `success`, `map`, `match`, `toResult`.
74
- - **`Arr`** — array operations that return `Option` instead of throwing or returning `undefined`.
75
- Operations: `head`, `last`, `findFirst`, `findLast`, `partition`, `groupBy`, `zip`, `traverse`,
76
- and more.
77
- - **`Rec`** — record/object operations. Operations: `lookup`, `map`, `filter`, `pick`, `omit`,
78
- `merge`, and more.
25
+ - **`Option<A>`** a value that might not exist. Replaces `T | null | undefined`.
26
+ - **`Result<E, A>`** an operation that succeeds or fails. Replaces `try/catch`.
27
+ - **`Validation<E, A>`** — like `Result`, but accumulates all errors instead of stopping at the first.
28
+ - **`Task<A>`** — a lazy async operation that doesn't run until called.
29
+ - **`TaskResult<E, A>`** `Task` + `Result`. A lazy async operation that can fail.
30
+ - **`TaskOption<A>`** — `Task` + `Option`. Replaces `Promise<T | null>`.
31
+ - **`TaskValidation<E, A>`** `Task` + `Validation`. For async checks that all need to run.
32
+ - **`These<E, A>`** — an inclusive OR: holds an error, a value, or both at once.
33
+ - **`RemoteData<E, A>`** the four states of a data fetch: `NotAsked`, `Loading`, `Failure`, `Success`.
34
+ - **`Arr`**array utilities that return `Option` instead of `undefined`.
35
+ - **`Rec`** record/object utilities.
79
36
 
80
37
  ### pipekit/Types
81
38
 
82
- - **`Brand<K, T>`** — nominal typing for values that share the same underlying type. Prevents
83
- passing a `CustomerId` where a `UserId` is expected, even though both are `string`. The brand
84
- exists only at compile time — zero runtime cost. Key operations: `make`, `unwrap`.
39
+ - **`Brand<K, T>`** — nominal typing at compile time, zero runtime cost.
85
40
  - **`NonEmptyList<A>`** — an array guaranteed to have at least one element.
86
41
 
87
42
  ### pipekit/Composition
88
43
 
89
- - **`pipe`** — pass a value through a series of functions, left to right.
90
- - **`flow`** compose functions into a reusable pipeline (like `pipe` without an initial value).
91
- - **`compose`** — compose functions right to left (traditional mathematical composition).
92
- - **`curry` / `uncurry`** — convert between multi-argument and single-argument functions.
93
- - **`tap`** — run a side effect (like logging) without breaking the pipeline.
94
- - **`memoize`** — cache function results.
95
- - **`identity`**, **`constant`**, **`not`**, **`and`**, **`or`**, **`once`**, **`flip`** — common
96
- function utilities.
44
+ - **`pipe`**, **`flow`**, **`compose`** — function composition.
45
+ - **`curry`** / **`uncurry`**, **`tap`**, **`memoize`**, and other function utilities.
97
46
 
98
- ## What does "composition-centric" mean?
99
-
100
- Everything in the library is designed to work with `pipe` — a function that passes a value through a
101
- series of transformations, top to bottom. The alternative is nesting calls inside each other, which
102
- reads inside-out:
47
+ ## Example
103
48
 
104
49
  ```ts
105
- import { Option } from "@nlozgachev/pipekit/Core";
50
+ import { Option, Result } from "@nlozgachev/pipekit/Core";
106
51
  import { pipe } from "@nlozgachev/pipekit/Composition";
107
52
 
108
- // Without pipe: execution order is the reverse of reading order
109
- const userName = Option.getOrElse(
110
- Option.map(
111
- Option.fromNullable(users.get("123")),
112
- (u) => u.name,
113
- ),
114
- "Anonymous",
115
- );
116
-
117
- // With pipe: reads top to bottom, matches execution order
118
- const userName = pipe(
119
- users.get("123"), // User | undefined
120
- Option.fromNullable, // Option<User>
121
- Option.map((u) => u.name), // Option<string>
122
- Option.getOrElse("Anonymous"), // string
53
+ // Chain nullable lookups without nested null checks
54
+ const city = pipe(
55
+ getUser(userId), // User | null
56
+ Option.fromNullable, // Option<User>
57
+ Option.chain((u) => Option.fromNullable(u.address)),// Option<Address>
58
+ Option.chain((a) => Option.fromNullable(a.city)), // Option<string>
59
+ Option.map((c) => c.toUpperCase()), // Option<string>
60
+ Option.getOrElse("UNKNOWN"), // string
123
61
  );
124
- ```
125
-
126
- No method chaining, no class hierarchies. Just functions that connect together.
127
-
128
- ## What does "data-last" mean and why should I care?
129
-
130
- Every operation takes the data it operates on as the **last** argument. This means you can partially
131
- apply them — get a function back without providing data yet — which makes `flow` work naturally.
132
-
133
- ```ts
134
- import { Option } from "@nlozgachev/pipekit/Core";
135
- import { flow } from "@nlozgachev/pipekit/Composition";
136
-
137
- // Data-first: can't partially apply, so you're stuck writing wrapper functions
138
- function formatName(user: User | null): string {
139
- const opt = Option.fromNullable(user);
140
- const name = Option.map(opt, (u) => u.name);
141
- return Option.getOrElse(name, "Anonymous");
142
- }
143
-
144
- users.map((u) => formatName(u)); // needs an arrow function wrapper
145
-
146
- // Data-last: operations are curried, so flow connects them directly
147
- const formatName = flow(
148
- Option.fromNullable<User>,
149
- Option.map((u) => u.name),
150
- Option.getOrElse("Anonymous"),
151
- );
152
-
153
- users.map(formatName); // no wrapper — it's already a function of User
154
- ```
155
-
156
- ## How does this help me write safer code?
157
-
158
- The core types make invalid states unrepresentable. Instead of stacking null checks and hoping you
159
- handled every branch, the shape of the code reflects the shape of the data:
160
-
161
- ```ts
162
- // Before: null handling that doesn't scale
163
- function getDisplayCity(userId: string): string {
164
- const user = getUser(userId);
165
- if (user === null) return "UNKNOWN";
166
- if (user.address === null) return "UNKNOWN";
167
- if (user.address.city === null) return "UNKNOWN";
168
- return user.address.city.toUpperCase();
169
- }
170
-
171
- // After: flat, readable, same guarantees
172
- function getDisplayCity(userId: string): string {
173
- return pipe(
174
- getUser(userId), // User | null
175
- Option.fromNullable, // Option<User>
176
- Option.chain((u) => Option.fromNullable(u.address)), // Option<Address>
177
- Option.chain((a) => Option.fromNullable(a.city)), // Option<string>
178
- Option.map((c) => c.toUpperCase()), // Option<string>
179
- Option.getOrElse("UNKNOWN"), // string
180
- );
181
- }
182
- ```
183
-
184
- `Brand` applies the same idea at the type level. When `userId` and `customerId` are both `string`,
185
- nothing stops you from passing one where the other is expected — until you brand them:
186
62
 
187
- ```ts
188
- import { Brand } from "@nlozgachev/pipekit/Types";
189
-
190
- type UserId = Brand<"UserId", string>;
191
- type CustomerId = Brand<"CustomerId", string>;
192
-
193
- const toUserId = Brand.make<"UserId", string>();
194
- const toCustomerId = Brand.make<"CustomerId", string>();
195
-
196
- function getUser(id: UserId): User {/* ... */}
197
-
198
- const cid = toCustomerId("c-99");
199
- getUser(cid); // TypeError: Argument of type 'CustomerId' is not assignable to parameter of type 'UserId'
200
- getUser(toUserId("u-42")); // ✓
201
- ```
202
-
203
- The same idea applies to error handling with `Result`, form validation with `Validation`, async
204
- operations with `Task`, `TaskResult`, `TaskOption`, and `TaskValidation`, and loading states with
205
- `RemoteData`.
206
-
207
- ## How do I install it?
208
-
209
- ```sh
210
- # Deno
211
- deno add jsr:@nlozgachev/pipekit
212
-
213
- # npm / pnpm / yarn / bun
214
- npm add @nlozgachev/pipekit
215
- ```
216
-
217
- ## How do I get started?
218
-
219
- Start with `pipe` and `Option`. These two cover the most common pain point — dealing with values
220
- that might not exist:
221
-
222
- ```ts
223
- import { Option } from "@nlozgachev/pipekit/Core";
224
- import { pipe } from "@nlozgachev/pipekit/Composition";
225
-
226
- // Read a user's preferred language from their settings, fall back to the app default
227
- const language = pipe(
228
- userSettings.get(userId), // UserSettings | undefined
229
- Option.fromNullable, // Option<UserSettings>
230
- Option.map((s) => s.language), // Option<string>
231
- Option.getOrElse(DEFAULT_LANGUAGE), // string
232
- );
233
- ```
234
-
235
- Once that feels natural, reach for `Result` when operations can fail with a meaningful error —
236
- parsing, network calls, database lookups:
237
-
238
- ```ts
239
- import { Result } from "@nlozgachev/pipekit/Core";
240
-
241
- // Parse user input and look up the record — both steps can fail
63
+ // Parse input and look up a record — both steps can fail
242
64
  const record = pipe(
243
- parseId(rawInput), // Result<ParseError, number>
244
- Result.chain((id) => db.find(id)), // Result<ParseError | NotFoundError, Record>
245
- Result.map((r) => r.name), // Result<ParseError | NotFoundError, string>
65
+ parseId(rawInput), // Result<ParseError, number>
66
+ Result.chain((id) => db.find(id)), // Result<ParseError | NotFoundError, Record>
67
+ Result.map((r) => r.name), // Result<ParseError | NotFoundError, string>
246
68
  );
247
69
  ```
248
70
 
249
- And `Validation` when you need to collect multiple errors at once, like form validation. For async
250
- equivalents of all three, reach for `TaskOption`, `TaskResult`, and `TaskValidation`.
71
+ ## Documentation
72
+
73
+ Full guides and API reference at **[pipekit.lozgachev.dev](https://pipekit.lozgachev.dev)**.
251
74
 
252
75
  ## License
253
76
 
@@ -28,7 +28,7 @@ export var Arr;
28
28
  * Arr.head([]); // None
29
29
  * ```
30
30
  */
31
- Arr.head = (data) => data.length > 0 ? Option.toSome(data[0]) : Option.toNone();
31
+ Arr.head = (data) => data.length > 0 ? Option.some(data[0]) : Option.none();
32
32
  /**
33
33
  * Returns the last element of an array, or None if the array is empty.
34
34
  *
@@ -38,7 +38,7 @@ export var Arr;
38
38
  * Arr.last([]); // None
39
39
  * ```
40
40
  */
41
- Arr.last = (data) => data.length > 0 ? Option.toSome(data[data.length - 1]) : Option.toNone();
41
+ Arr.last = (data) => data.length > 0 ? Option.some(data[data.length - 1]) : Option.none();
42
42
  /**
43
43
  * Returns all elements except the first, or None if the array is empty.
44
44
  *
@@ -48,7 +48,7 @@ export var Arr;
48
48
  * Arr.tail([]); // None
49
49
  * ```
50
50
  */
51
- Arr.tail = (data) => data.length > 0 ? Option.toSome(data.slice(1)) : Option.toNone();
51
+ Arr.tail = (data) => data.length > 0 ? Option.some(data.slice(1)) : Option.none();
52
52
  /**
53
53
  * Returns all elements except the last, or None if the array is empty.
54
54
  *
@@ -58,7 +58,7 @@ export var Arr;
58
58
  * Arr.init([]); // None
59
59
  * ```
60
60
  */
61
- Arr.init = (data) => data.length > 0 ? Option.toSome(data.slice(0, -1)) : Option.toNone();
61
+ Arr.init = (data) => data.length > 0 ? Option.some(data.slice(0, -1)) : Option.none();
62
62
  // --- Search ---
63
63
  /**
64
64
  * Returns the first element matching the predicate, or None.
@@ -70,7 +70,7 @@ export var Arr;
70
70
  */
71
71
  Arr.findFirst = (predicate) => (data) => {
72
72
  const idx = data.findIndex(predicate);
73
- return idx >= 0 ? Option.toSome(data[idx]) : Option.toNone();
73
+ return idx >= 0 ? Option.some(data[idx]) : Option.none();
74
74
  };
75
75
  /**
76
76
  * Returns the last element matching the predicate, or None.
@@ -83,9 +83,9 @@ export var Arr;
83
83
  Arr.findLast = (predicate) => (data) => {
84
84
  for (let i = data.length - 1; i >= 0; i--) {
85
85
  if (predicate(data[i]))
86
- return Option.toSome(data[i]);
86
+ return Option.some(data[i]);
87
87
  }
88
- return Option.toNone();
88
+ return Option.none();
89
89
  };
90
90
  /**
91
91
  * Returns the index of the first element matching the predicate, or None.
@@ -97,7 +97,7 @@ export var Arr;
97
97
  */
98
98
  Arr.findIndex = (predicate) => (data) => {
99
99
  const idx = data.findIndex(predicate);
100
- return idx >= 0 ? Option.toSome(idx) : Option.toNone();
100
+ return idx >= 0 ? Option.some(idx) : Option.none();
101
101
  };
102
102
  // --- Transform ---
103
103
  /**
@@ -303,7 +303,7 @@ export var Arr;
303
303
  * ```ts
304
304
  * const parseNum = (s: string): Option<number> => {
305
305
  * const n = Number(s);
306
- * return isNaN(n) ? Option.toNone() : Option.of(n);
306
+ * return isNaN(n) ? Option.none() : Option.of(n);
307
307
  * };
308
308
  *
309
309
  * pipe(["1", "2", "3"], Arr.traverse(parseNum)); // Some([1, 2, 3])
@@ -315,10 +315,10 @@ export var Arr;
315
315
  for (const a of data) {
316
316
  const mapped = f(a);
317
317
  if (Option.isNone(mapped))
318
- return Option.toNone();
318
+ return Option.none();
319
319
  result.push(mapped.value);
320
320
  }
321
- return Option.toSome(result);
321
+ return Option.some(result);
322
322
  };
323
323
  /**
324
324
  * Maps each element to a Result and collects the results.
@@ -328,7 +328,7 @@ export var Arr;
328
328
  * ```ts
329
329
  * pipe(
330
330
  * [1, 2, 3],
331
- * Arr.traverseResult(n => n > 0 ? Result.toOk(n) : Result.toErr("negative"))
331
+ * Arr.traverseResult(n => n > 0 ? Result.ok(n) : Result.err("negative"))
332
332
  * ); // Ok([1, 2, 3])
333
333
  * ```
334
334
  */
@@ -340,7 +340,7 @@ export var Arr;
340
340
  return mapped;
341
341
  result.push(mapped.value);
342
342
  }
343
- return Result.toOk(result);
343
+ return Result.ok(result);
344
344
  };
345
345
  /**
346
346
  * Maps each element to a Task and runs all in parallel.
@@ -361,7 +361,7 @@ export var Arr;
361
361
  * @example
362
362
  * ```ts
363
363
  * Arr.sequence([Option.of(1), Option.of(2)]); // Some([1, 2])
364
- * Arr.sequence([Option.of(1), Option.toNone()]); // None
364
+ * Arr.sequence([Option.of(1), Option.none()]); // None
365
365
  * ```
366
366
  */
367
367
  Arr.sequence = (data) => Arr.traverse((a) => a)(data);
@@ -9,11 +9,11 @@ export var Option;
9
9
  * Option.of(42); // Some(42)
10
10
  * ```
11
11
  */
12
- Option.of = (value) => Option.toSome(value);
12
+ Option.of = (value) => Option.some(value);
13
13
  /**
14
14
  * Creates a Some containing the given value.
15
15
  */
16
- Option.toSome = (value) => ({ kind: "Some", value });
16
+ Option.some = (value) => ({ kind: "Some", value });
17
17
  /**
18
18
  * Type guard that checks if a Option is Some.
19
19
  */
@@ -21,7 +21,7 @@ export var Option;
21
21
  /**
22
22
  * Creates a None (empty Option).
23
23
  */
24
- Option.toNone = () => ({ kind: "None" });
24
+ Option.none = () => ({ kind: "None" });
25
25
  /**
26
26
  * Type guard that checks if a Option is None.
27
27
  */
@@ -36,7 +36,7 @@ export var Option;
36
36
  * Option.fromNullable(42); // Some(42)
37
37
  * ```
38
38
  */
39
- Option.fromNullable = (value) => value === null || value === undefined ? Option.toNone() : Option.toSome(value);
39
+ Option.fromNullable = (value) => value === null || value === undefined ? Option.none() : Option.some(value);
40
40
  /**
41
41
  * Extracts the value from a Option, returning null if None.
42
42
  */
@@ -49,7 +49,7 @@ export var Option;
49
49
  * Creates a Option from a possibly undefined value.
50
50
  * Returns None if undefined, Some otherwise.
51
51
  */
52
- Option.fromUndefined = (value) => value === undefined ? Option.toNone() : Option.toSome(value);
52
+ Option.fromUndefined = (value) => value === undefined ? Option.none() : Option.some(value);
53
53
  /**
54
54
  * Converts an Option to a Result.
55
55
  * Some becomes Ok, None becomes Err with the provided error.
@@ -62,33 +62,33 @@ export var Option;
62
62
  * ); // Ok(42)
63
63
  *
64
64
  * pipe(
65
- * Option.toNone(),
65
+ * Option.none(),
66
66
  * Option.toResult(() => "Value was missing")
67
67
  * ); // Err("Value was missing")
68
68
  * ```
69
69
  */
70
- Option.toResult = (onNone) => (data) => Option.isSome(data) ? Result.toOk(data.value) : Result.toErr(onNone());
70
+ Option.toResult = (onNone) => (data) => Option.isSome(data) ? Result.ok(data.value) : Result.err(onNone());
71
71
  /**
72
72
  * Creates an Option from a Result.
73
73
  * Ok becomes Some, Err becomes None (the error is discarded).
74
74
  *
75
75
  * @example
76
76
  * ```ts
77
- * Option.fromResult(Result.toOk(42)); // Some(42)
78
- * Option.fromResult(Result.toErr("oops")); // None
77
+ * Option.fromResult(Result.ok(42)); // Some(42)
78
+ * Option.fromResult(Result.err("oops")); // None
79
79
  * ```
80
80
  */
81
- Option.fromResult = (data) => Result.isOk(data) ? Option.toSome(data.value) : Option.toNone();
81
+ Option.fromResult = (data) => Result.isOk(data) ? Option.some(data.value) : Option.none();
82
82
  /**
83
83
  * Transforms the value inside a Option if it exists.
84
84
  *
85
85
  * @example
86
86
  * ```ts
87
87
  * pipe(Option.of(5), Option.map(n => n * 2)); // Some(10)
88
- * pipe(Option.toNone(), Option.map(n => n * 2)); // None
88
+ * pipe(Option.none(), Option.map(n => n * 2)); // None
89
89
  * ```
90
90
  */
91
- Option.map = (f) => (data) => Option.isSome(data) ? Option.toSome(f(data.value)) : data;
91
+ Option.map = (f) => (data) => Option.isSome(data) ? Option.some(f(data.value)) : data;
92
92
  /**
93
93
  * Chains Option computations. If the first is Some, passes the value to f.
94
94
  * If the first is None, propagates None.
@@ -97,7 +97,7 @@ export var Option;
97
97
  * ```ts
98
98
  * const parseNumber = (s: string): Option<number> => {
99
99
  * const n = parseInt(s, 10);
100
- * return isNaN(n) ? Option.toNone() : Option.of(n);
100
+ * return isNaN(n) ? Option.none() : Option.of(n);
101
101
  * };
102
102
  *
103
103
  * pipe(Option.of("42"), Option.chain(parseNumber)); // Some(42)
@@ -141,7 +141,7 @@ export var Option;
141
141
  * @example
142
142
  * ```ts
143
143
  * pipe(Option.of(5), Option.getOrElse(0)); // 5
144
- * pipe(Option.toNone(), Option.getOrElse(0)); // 0
144
+ * pipe(Option.none(), Option.getOrElse(0)); // 0
145
145
  * ```
146
146
  */
147
147
  Option.getOrElse = (defaultValue) => (data) => Option.isSome(data) ? data.value : defaultValue;
@@ -173,7 +173,7 @@ export var Option;
173
173
  * pipe(Option.of(2), Option.filter(n => n > 3)); // None
174
174
  * ```
175
175
  */
176
- Option.filter = (predicate) => (data) => Option.isSome(data) && predicate(data.value) ? data : Option.toNone();
176
+ Option.filter = (predicate) => (data) => Option.isSome(data) && predicate(data.value) ? data : Option.none();
177
177
  /**
178
178
  * Recovers from a None by providing a fallback Option.
179
179
  */
@@ -191,5 +191,5 @@ export var Option;
191
191
  * ); // Some(8)
192
192
  * ```
193
193
  */
194
- Option.ap = (arg) => (data) => Option.isSome(data) && Option.isSome(arg) ? Option.toSome(data.value(arg.value)) : Option.toNone();
194
+ Option.ap = (arg) => (data) => Option.isSome(data) && Option.isSome(arg) ? Option.some(data.value(arg.value)) : Option.none();
195
195
  })(Option || (Option = {}));
@@ -87,7 +87,7 @@ export var Rec;
87
87
  * pipe({ a: 1, b: 2 }, Rec.lookup("c")); // None
88
88
  * ```
89
89
  */
90
- Rec.lookup = (key) => (data) => Object.prototype.hasOwnProperty.call(data, key) ? Option.toSome(data[key]) : Option.toNone();
90
+ Rec.lookup = (key) => (data) => Object.prototype.hasOwnProperty.call(data, key) ? Option.some(data[key]) : Option.none();
91
91
  /**
92
92
  * Returns all keys of a record.
93
93
  */
@@ -8,15 +8,15 @@ export var Result;
8
8
  * Result.of(42); // Ok(42)
9
9
  * ```
10
10
  */
11
- Result.of = (value) => Result.toOk(value);
11
+ Result.of = (value) => Result.ok(value);
12
12
  /**
13
13
  * Creates a failed Result with the given error.
14
14
  */
15
- Result.toErr = (error) => ({ kind: "Error", error });
15
+ Result.err = (error) => ({ kind: "Error", error });
16
16
  /**
17
17
  * Creates a successful Result with the given value.
18
18
  */
19
- Result.toOk = (value) => ({ kind: "Ok", value });
19
+ Result.ok = (value) => ({ kind: "Ok", value });
20
20
  /**
21
21
  * Type guard that checks if an Result is Ok.
22
22
  */
@@ -40,10 +40,10 @@ export var Result;
40
40
  */
41
41
  Result.tryCatch = (f, onError) => {
42
42
  try {
43
- return Result.toOk(f());
43
+ return Result.ok(f());
44
44
  }
45
45
  catch (e) {
46
- return Result.toErr(onError(e));
46
+ return Result.err(onError(e));
47
47
  }
48
48
  };
49
49
  /**
@@ -52,19 +52,19 @@ export var Result;
52
52
  * @example
53
53
  * ```ts
54
54
  * pipe(Result.of(5), Result.map(n => n * 2)); // Ok(10)
55
- * pipe(Result.toErr("error"), Result.map(n => n * 2)); // Err("error")
55
+ * pipe(Result.err("error"), Result.map(n => n * 2)); // Err("error")
56
56
  * ```
57
57
  */
58
- Result.map = (f) => (data) => Result.isOk(data) ? Result.toOk(f(data.value)) : data;
58
+ Result.map = (f) => (data) => Result.isOk(data) ? Result.ok(f(data.value)) : data;
59
59
  /**
60
60
  * Transforms the error value inside an Result.
61
61
  *
62
62
  * @example
63
63
  * ```ts
64
- * pipe(Result.toErr("oops"), Result.mapError(e => e.toUpperCase())); // Err("OOPS")
64
+ * pipe(Result.err("oops"), Result.mapError(e => e.toUpperCase())); // Err("OOPS")
65
65
  * ```
66
66
  */
67
- Result.mapError = (f) => (data) => Result.isErr(data) ? Result.toErr(f(data.error)) : data;
67
+ Result.mapError = (f) => (data) => Result.isErr(data) ? Result.err(f(data.error)) : data;
68
68
  /**
69
69
  * Chains Result computations. If the first is Ok, passes the value to f.
70
70
  * If the first is Err, propagates the error.
@@ -72,7 +72,7 @@ export var Result;
72
72
  * @example
73
73
  * ```ts
74
74
  * const validatePositive = (n: number): Result<string, number> =>
75
- * n > 0 ? Result.of(n) : Result.toErr("Must be positive");
75
+ * n > 0 ? Result.of(n) : Result.err("Must be positive");
76
76
  *
77
77
  * pipe(Result.of(5), Result.chain(validatePositive)); // Ok(5)
78
78
  * pipe(Result.of(-1), Result.chain(validatePositive)); // Err("Must be positive")
@@ -115,7 +115,7 @@ export var Result;
115
115
  * @example
116
116
  * ```ts
117
117
  * pipe(Result.of(5), Result.getOrElse(0)); // 5
118
- * pipe(Result.toErr("error"), Result.getOrElse(0)); // 0
118
+ * pipe(Result.err("error"), Result.getOrElse(0)); // 0
119
119
  * ```
120
120
  */
121
121
  Result.getOrElse = (defaultValue) => (data) => Result.isOk(data) ? data.value : defaultValue;
@@ -151,8 +151,8 @@ export var Result;
151
151
  *
152
152
  * @example
153
153
  * ```ts
154
- * Result.toOption(Result.toOk(42)); // Some(42)
155
- * Result.toOption(Result.toErr("oops")); // None
154
+ * Result.toOption(Result.ok(42)); // Some(42)
155
+ * Result.toOption(Result.err("oops")); // None
156
156
  * ```
157
157
  */
158
158
  Result.toOption = (data) => Result.isOk(data) ? { kind: "Some", value: data.value } : { kind: "None" };
@@ -169,5 +169,5 @@ export var Result;
169
169
  * ); // Ok(8)
170
170
  * ```
171
171
  */
172
- Result.ap = (arg) => (data) => Result.isOk(data) && Result.isOk(arg) ? Result.toOk(data.value(arg.value)) : Result.isErr(data) ? data : arg;
172
+ Result.ap = (arg) => (data) => Result.isOk(data) && Result.isOk(arg) ? Result.ok(data.value(arg.value)) : Result.isErr(data) ? data : arg;
173
173
  })(Result || (Result = {}));