rsult 1.4.0 → 2.0.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/src/result.ts CHANGED
@@ -1,395 +1,305 @@
1
1
  import { Option, None, Some } from './option';
2
2
 
3
- export type Result<T, E> =
4
- ResultOk<T, E> | ResultErr<T, E>;
3
+ // ============================================================================
4
+ // Type-Level Utilities
5
+ // ============================================================================
6
+
7
+ /** Unique brand symbols for nominal typing */
8
+ declare const OkBrand: unique symbol;
9
+ declare const ErrBrand: unique symbol;
10
+
11
+ /** Extract the Ok type from a Result */
12
+ export type UnwrapOk<R> = R extends Result<infer T, any> ? T : never;
13
+
14
+ /** Extract the Err type from a Result */
15
+ export type UnwrapErr<R> = R extends Result<any, infer E> ? E : never;
16
+
17
+ /** Unwrap nested Result types for flatten() */
18
+ export type FlattenResult<T, E> = T extends Result<infer U, infer E2>
19
+ ? Result<U, E | E2>
20
+ : Result<T, E>;
21
+
22
+ /** Type-level check for nested Results */
23
+ export type IsNestedResult<T> = T extends Result<any, any> ? true : false;
24
+
25
+ // ============================================================================
26
+ // Result Type Definition
27
+ // ============================================================================
28
+
29
+ /**
30
+ * A discriminated union representing either success (Ok) or failure (Err).
31
+ *
32
+ * @typeParam T - The success value type
33
+ * @typeParam E - The error value type
34
+ */
35
+ export type Result<T, E> = ResultOk<T, E> | ResultErr<T, E>;
36
+
37
+ // ============================================================================
38
+ // Core Interfaces
39
+ // ============================================================================
5
40
 
6
41
  export interface IResultCore<T, E> {
7
42
  /**
8
- * Checks if the result is an instance of `ResultOk`.
9
- * @returns true if the result is `ResultOk`, otherwise false.
43
+ * Returns `true` if the result is `Ok`.
10
44
  *
11
- * Usage Example:
12
- * const result = Ok(5);
13
- * if (result.is_ok()) {
14
- * console.log("Result is Ok");
15
- * }
45
+ * This is a type guard that narrows the type to `ResultOk<T, E>`.
16
46
  */
17
47
  is_ok(): this is ResultOk<T, E>;
18
48
 
19
49
  /**
20
- * Checks if the result is an instance of `ResultErr`.
21
- * @returns true if the result is `ResultErr`, otherwise false.
50
+ * Returns `true` if the result is `Err`.
22
51
  *
23
- * Usage Example:
24
- * const result = Err(new Error("Error"));
25
- * if (result.is_err()) {
26
- * console.log("Result is Err");
27
- * }
52
+ * This is a type guard that narrows the type to `ResultErr<T, E>`.
28
53
  */
29
54
  is_err(): this is ResultErr<T, E>;
30
55
 
31
56
  /**
32
- * Retrieves the value from `ResultOk`, wrapped in an `Option`.
33
- * @returns `Some` containing the value if the result is `ResultOk`, otherwise `None`.
57
+ * Converts from `Result<T, E>` to `Option<T>`.
34
58
  *
35
- * Usage Example:
36
- * const result = Ok(5);
37
- * const value = result.ok();
38
- * if (value.is_some()) {
39
- * console.log("Value:", value.unwrap());
40
- * }
59
+ * Returns `Some(value)` if `Ok`, otherwise `None`.
41
60
  */
42
61
  ok(): Option<T>;
43
62
 
44
63
  /**
45
- * Retrieves the error from `ResultErr`, wrapped in an `Option`.
46
- * @returns `Some` containing the error if the result is `ResultErr`, otherwise `None`.
64
+ * Converts from `Result<T, E>` to `Option<E>`.
47
65
  *
48
- * Usage Example:
49
- * const result = Err(new Error("Error"));
50
- * const error = result.err();
51
- * if (error.is_some()) {
52
- * console.log("Error:", error.unwrap());
53
- * }
66
+ * Returns `Some(error)` if `Err`, otherwise `None`.
54
67
  */
55
68
  err(): Option<E>;
56
69
 
57
70
  /**
58
- * Returns the contained `ResultOk` value, but throws an error with a provided message if
59
- * the result is a `ResultErr`.
60
- * @param msg The message to throw with if the result is an error.
61
- * @returns The contained `ResultOk` value.
71
+ * Returns the contained `Ok` value, or throws with the provided message.
62
72
  *
63
- * Usage Example:
64
- * const result = Ok(5);
65
- * console.log(result.expect("This should not fail"));
73
+ * @throws Error with `msg` if this is `Err`
66
74
  */
67
75
  expect(msg: string): T;
68
76
 
69
77
  /**
70
- * Unwraps a `ResultOk`, yielding the contained value.
71
- * @returns The `ResultOk` value.
72
- * @throws Throws if the result is `ResultErr`.
78
+ * Returns the contained `Ok` value, or throws.
73
79
  *
74
- * Usage Example:
75
- * const result = Ok(5);
76
- * console.log(result.unwrap());
80
+ * @throws Error if this is `Err`
77
81
  */
78
82
  unwrap(): T;
79
83
 
80
84
  /**
81
- * Returns the contained `ResultErr` error, but throws an error with a provided message if
82
- * the result is a `ResultOk`.
83
- * @param msg The message to throw with if the result is Ok.
84
- * @returns The contained `ResultErr` error.
85
+ * Returns the contained `Err` value, or throws with the provided message.
85
86
  *
86
- * Usage Example:
87
- * const result = Err(new Error("Failure"));
88
- * console.log(result.expect_err("Expected an error"));
87
+ * @throws Error with `msg` if this is `Ok`
89
88
  */
90
89
  expect_err(msg: string): E;
91
90
 
92
91
  /**
93
- * Unwraps a `ResultErr`, yielding the contained error.
94
- * @returns The `ResultErr` error.
95
- * @throws Throws if the result is `ResultOk`.
92
+ * Returns the contained `Err` value, or throws.
96
93
  *
97
- * Usage Example:
98
- * const result = Err(new Error("Failure"));
99
- * console.log(result.unwrap_err());
94
+ * @throws Error if this is `Ok`
100
95
  */
101
96
  unwrap_err(): E;
102
97
 
103
98
  /**
104
- * Converts from `IResultCore<T, E>` to `T`.
105
- * @returns The contained `ResultOk` value.
106
- * @throws Throws if the result is `ResultErr`.
99
+ * Returns the contained `Ok` value. Identical to `unwrap()`.
107
100
  *
108
- * Usage Example:
109
- * const result = Ok(5);
110
- * console.log(result.into_ok());
101
+ * @throws Error if this is `Err`
111
102
  */
112
103
  into_ok(): T;
113
104
 
114
105
  /**
115
- * Converts from `IResultCore<T, E>` to `E`.
116
- * @returns The contained `ResultErr` error.
117
- * @throws Throws if the result is `ResultOk`.
106
+ * Returns the contained `Err` value. Identical to `unwrap_err()`.
118
107
  *
119
- * Usage Example:
120
- * const result = Err(new Error("Failure"));
121
- * console.log(result.into_err());
108
+ * @throws Error if this is `Ok`
122
109
  */
123
110
  into_err(): E;
124
-
125
- /**
126
- * Converts between different forms of `Result`, allowing the error type to be widened.
127
- *
128
- * If called on a `ResultOk<T, E>`, it will return a `Result<T, never>`, effectively discarding
129
- * the error type. This is useful when you want to use the `Result` in a context that expects
130
- * a `Result` with a specific error type, but you know that the `Result` is an `Ok` variant.
131
- *
132
- * If called on a `ResultErr<T, E>`, it will return a `Result<never, E>`, effectively discarding
133
- * the value type. This is useful when you want to use the `Result` in a context that expects
134
- * a `Result` with a specific value type, but you know that the `Result` is an `Err` variant.
135
- *
136
- * This is particularly useful when trying to forward a ResultErr returned by a function whose
137
- * error type overlaps with the returned error type of the current function, but whose value type
138
- * does not.
139
- *
140
- * Usage Example:
141
- * const result: Result<number, Error> = Ok<number, Error>(5);
142
- * const transmuted: Result<number, never> = result.transmute();
143
- *
144
- * const result: Result<number, Error> = Err<number, Error>(new Error("Failure"));
145
- * const transmuted: Result<never, Error> = result.transmute();
146
- */
147
- transmute(): Result<T, never> | Result<never, E>;
148
111
  }
149
112
 
150
113
  export interface IResultExt<T, E> extends IResultCore<T, E> {
151
114
  /**
152
- * Checks if the result is Ok and the contained value passes a specified condition.
153
- * @param f A predicate to apply to the contained value if the result is Ok.
154
- * @returns true if the result is Ok and the predicate returns true, otherwise false.
155
- *
156
- * Usage Examples:
157
- * const result = Ok(5);
158
- * if (result.is_ok_and(x => x > 3)) {
159
- * console.log("Result is Ok and greater than 3");
160
- * }
161
- *
162
- * const result = Ok(2);
163
- * if (!result.is_ok_and(x => x > 3)) {
164
- * console.log("Result is not Ok or not greater than 3");
165
- * }
115
+ * Returns `true` if `Ok` and the value satisfies the predicate.
166
116
  */
167
117
  is_ok_and(f: (value: T) => boolean): boolean;
168
118
 
169
119
  /**
170
- * Checks if the result is Err and the contained error passes a specified condition.
171
- * @param f A predicate to apply to the contained error if the result is Err.
172
- * @returns true if the result is Err and the predicate returns true, otherwise false.
173
- *
174
- * Usage Examples:
175
- * const result = Err(new Error("Network failure"));
176
- * if (result.is_err_and(e => e.message.includes("Network"))) {
177
- * console.log("Network error occurred");
178
- * }
120
+ * Returns `true` if `Err` and the error satisfies the predicate.
179
121
  */
180
122
  is_err_and(f: (value: E) => boolean): boolean;
181
123
 
182
124
  /**
183
- * Transforms the result via a mapping function if it is Ok.
184
- * @param fn A function to transform the Ok value.
185
- * @returns A new Result where the Ok value has been transformed.
186
- *
187
- * Usage Example:
188
- * const result = Ok(5);
189
- * const mapped = result.map(x => x * 2);
190
- *
191
- * const result = Err("Error");
192
- * const mapped = result.map(x => x * 2); // remains Err
125
+ * Maps a `Result<T, E>` to `Result<U, E>` by applying `fn` to the `Ok` value.
193
126
  */
194
127
  map<U>(fn: (arg: T) => U): Result<U, E>;
195
128
 
196
129
  /**
197
- * Transforms the result via a mapping function if it is Ok, otherwise returns a default value.
198
- * @param defaultVal A default value to return if the result is Err.
199
- * @param f A function to transform the Ok value.
200
- * @returns The transformed Ok value or the default value.
201
- *
202
- * Usage Example:
203
- * const result = Ok(5);
204
- * const value = result.map_or(0, x => x * 2);
205
- *
206
- * const result = Err("Error");
207
- * const value = result.map_or(0, x => x * 2); // 0
130
+ * Returns the provided default (if `Err`), or applies `fn` to the `Ok` value.
208
131
  */
209
132
  map_or<U>(defaultVal: U, f: (arg: T) => U): U;
210
133
 
211
134
  /**
212
- * Transforms the result via a mapping function if it is Ok, otherwise computes a default value using a function.
213
- * @param defaultFunc A function to compute a default value if the result is Err.
214
- * @param f A function to transform the Ok value.
215
- * @returns The transformed Ok value or the computed default value.
216
- *
217
- * Usage Example:
218
- * const result = Ok(5);
219
- * const value = result.map_or_else(() => 0, x => x * 2);
220
- *
221
- * const result = Err("Error");
222
- * const value = result.map_or_else(() => 0, x => x * 2); // 0
135
+ * Computes a default (if `Err`), or applies `fn` to the `Ok` value.
223
136
  */
224
137
  map_or_else<U>(defaultFunc: (err: E) => U, f: (arg: T) => U): U;
225
138
 
226
139
  /**
227
- * Maps a `Result<T, E>` to `Result<T, U>` by applying a function to a contained `Err` value, leaving an `Ok` value untouched.
228
- * @param fn A function to transform the Err value.
229
- * @returns A new Result where the Err has been transformed.
230
- *
231
- * Usage Example:
232
- * const result = Err("Error");
233
- * const mappedErr = result.map_err(e => new Error(e));
140
+ * Maps a `Result<T, E>` to `Result<T, U>` by applying `fn` to the `Err` value.
234
141
  */
235
142
  map_err<U>(fn: (arg: E) => U): Result<T, U>;
236
143
 
237
144
  /**
238
- * Applies a function to the contained value (if Ok), then returns the unmodified Result.
239
- * @param f A function to apply to the Ok value.
240
- * @returns The original Result.
241
- *
242
- * Usage Example:
243
- * const result = Ok(5);
244
- * result.inspect(x => console.log(`Value: ${x}`));
145
+ * Calls `fn` with the `Ok` value if present, then returns the original result.
245
146
  */
246
- inspect(f: (val: T) => void): Result<T, E>;
147
+ inspect(f: (val: T) => void): this;
247
148
 
248
149
  /**
249
- * Applies a function to the contained error (if Err), then returns the unmodified Result.
250
- * @param f A function to apply to the Err value.
251
- * @returns The original Result.
252
- *
253
- * Usage Example:
254
- * const result = Err("Error");
255
- * result.inspect_err(e => console.log(`Error: ${e}`));
150
+ * Calls `fn` with the `Err` value if present, then returns the original result.
256
151
  */
257
- inspect_err(f: (val: E) => void): Result<T, E>;
152
+ inspect_err(f: (val: E) => void): this;
258
153
 
259
154
  /**
260
- * Returns `res` if the result is Ok, otherwise returns the Err value of `self`.
261
- * @param res The result to return if `self` is Ok.
262
- * @returns Either `res` or the original Err.
263
- *
264
- * Usage Example:
265
- * const result = Ok(5);
266
- * const other = Ok("Hello");
267
- * const finalResult = result.and(other); // Ok("Hello")
155
+ * Returns `res` if `Ok`, otherwise returns the `Err` value of `self`.
268
156
  */
269
157
  and<U>(res: Result<U, E>): Result<U, E>;
270
158
 
271
159
  /**
272
- * Calls `fn` if the result is Ok, otherwise returns the Err value of `self`.
273
- * @param fn A function to apply to the Ok value.
274
- * @returns The result of `fn` if the original result is Ok, otherwise the Err.
275
- *
276
- * Usage Example:
277
- * const result = Ok(5);
278
- * const finalResult = result.and_then(x => Ok(x * 2)); // Ok(10)
160
+ * Calls `fn` if `Ok`, otherwise returns the `Err` value of `self`.
161
+ * This is the monadic bind operation (flatMap).
279
162
  */
280
163
  and_then<U>(fn: (arg: T) => Result<U, E>): Result<U, E>;
281
164
 
282
165
  /**
283
- * Returns `res` if the result is Err, otherwise returns the Ok value of `self`.
284
- * @param res The result to return if `self` is Err.
285
- * @returns Either `res` or the original Ok.
286
- *
287
- * Usage Example:
288
- * const result = Err("Error");
289
- * const other = Ok(5);
290
- * const finalResult = result.or(other); // Ok(5)
166
+ * Returns `res` if `Err`, otherwise returns the `Ok` value of `self`.
291
167
  */
292
- or<U>(res: Result<U, E>): Result<U, E>;
168
+ or<F>(res: Result<T, F>): Result<T, F>;
293
169
 
294
170
  /**
295
- * Calls `fn` if the result is Err, otherwise returns the Ok value of `self`.
296
- * @param fn A function to apply to the Err value.
297
- * @returns The result of `fn` if the original result is Err, otherwise the Ok.
298
- *
299
- * Usage Example:
300
- * const result = Err("Error");
301
- * const finalResult = result.or_else(e => Ok(`Handled ${e}`)); // Ok("Handled Error")
171
+ * Calls `fn` if `Err`, otherwise returns the `Ok` value of `self`.
302
172
  */
303
- or_else<U>(fn: (arg: E) => Result<T, U>): Result<T, U>;
173
+ or_else<F>(fn: (arg: E) => Result<T, F>): Result<T, F>;
304
174
 
305
175
  /**
306
- * Returns the contained Ok value or a provided default.
307
- * @param defaultVal The default value to return if the result is Err.
308
- * @returns The Ok value or the default.
309
- *
310
- * Usage Example:
311
- * const result = Ok(5);
312
- * console.log(result.unwrap_or(0)); // 5
313
- *
314
- * const result = Err("Error");
315
- * console.log(result.unwrap_or(0)); // 0
176
+ * Returns the contained `Ok` value or the provided default.
316
177
  */
317
178
  unwrap_or(defaultVal: T): T;
318
179
 
319
180
  /**
320
- * Returns the contained Ok value or computes it from a function.
321
- * @param fn A function to compute the default value if the result is Err.
322
- * @returns The Ok value or the computed one.
323
- *
324
- * Usage Example:
325
- * const result = Err("Error");
326
- * console.log(result.unwrap_or_else(() => 5)); // 5
181
+ * Returns the contained `Ok` value or computes it from `fn`.
327
182
  */
328
183
  unwrap_or_else(fn: (arg: E) => T): T;
329
184
  }
330
185
 
331
- type UnwrapResult<T> = T extends Result<infer U, any> ? U : T;
332
-
333
186
  export interface IResultIteration<T, E> extends IResultCore<T, E> {
334
187
  /**
335
- * Returns an iterator over the potentially contained value.
336
- * @returns An iterator which yields the contained value if it is `ResultOk<T, E>`.
337
- *
338
- * Usage Example:
339
- * const okResult = Ok(5);
340
- * for (const value of okResult.iter()) {
341
- * console.log(value); // prints 5
342
- * }
343
- *
344
- * const errResult = Err(new Error("error"));
345
- * for (const value of errResult.iter()) {
346
- * // This block will not be executed.
347
- * }
188
+ * Returns an iterator over the possibly contained `Ok` value.
189
+ * Yields one element if `Ok`, zero if `Err`.
348
190
  */
349
191
  iter(): IterableIterator<T>;
350
192
 
351
193
  /**
352
- * Flattens a nested `Result` if the contained value is itself a `Result`.
353
- * @returns A single-layer `Result`, by stripping one layer of `Result` container.
194
+ * Flattens a `Result<Result<U, E2>, E>` into `Result<U, E | E2>`.
354
195
  *
355
- * Usage Example:
356
- * const nestedOk = Ok(Ok(5));
357
- * const flattened = nestedOk.flatten(); // Results in Ok(5)
196
+ * If `T` is not a `Result`, returns `Result<T, E>` unchanged.
197
+ */
198
+ flatten(): FlattenResult<T, E>;
199
+
200
+ /**
201
+ * Transposes a `Result` of an `Option` into an `Option` of a `Result`.
202
+ *
203
+ * - `Ok(None)` → `None`
204
+ * - `Ok(Some(v))` → `Some(Ok(v))`
205
+ * - `Err(e)` → `Some(Err(e))`
206
+ *
207
+ * @example
208
+ * ```typescript
209
+ * Ok(Some(5)).transpose() // Some(Ok(5))
210
+ * Ok(None()).transpose() // None
211
+ * Err("e").transpose() // Some(Err("e"))
212
+ * ```
213
+ */
214
+ transpose(): T extends { _tag: 'Some'; value: infer U }
215
+ ? { _tag: 'Some'; value: Result<U, E> }
216
+ : T extends { _tag: 'None' }
217
+ ? { _tag: 'None' }
218
+ : { _tag: 'Some' | 'None'; value?: Result<unknown, E> };
219
+ }
220
+
221
+ /**
222
+ * Methods specific to `ResultOk` that provide more precise types.
223
+ */
224
+ export interface IResultOkSpecific<T, E> {
225
+ /**
226
+ * Type-safe transmute that narrows the error type to `never`.
358
227
  *
359
- * const nestedErr = Ok(Err(new Error("error")));
360
- * const flattenedError = nestedErr.flatten(); // Results in Err(new Error("error"))
228
+ * Since this is `Ok`, there's no error, so `E` can safely become `never`.
361
229
  */
362
- flatten(): Result<UnwrapResult<T>, E>;
230
+ transmute(): ResultOk<T, never>;
231
+ }
232
+
233
+ /**
234
+ * Methods specific to `ResultErr` that provide more precise types.
235
+ */
236
+ export interface IResultErrSpecific<T, E> {
237
+ /**
238
+ * Type-safe transmute that narrows the value type to `never`.
239
+ *
240
+ * Since this is `Err`, there's no value, so `T` can safely become `never`.
241
+ */
242
+ transmute(): ResultErr<never, E>;
363
243
  }
364
244
 
365
245
  export interface IResult<T, E> extends
366
246
  IResultCore<T, E>,
367
247
  IResultExt<T, E>,
368
- IResultIteration<T, E> {}
248
+ IResultIteration<T, E> {
249
+ /**
250
+ * Converts between different Result types by narrowing phantom types.
251
+ *
252
+ * - On `Ok<T, E>`: returns `Ok<T, never>` (error type becomes `never`)
253
+ * - On `Err<T, E>`: returns `Err<never, E>` (value type becomes `never`)
254
+ */
255
+ transmute(): ResultOk<T, never> | ResultErr<never, E>;
256
+ }
369
257
 
370
- export const isResultOk = <T, E>(val: any): val is ResultOk<T, E> => {
258
+ // ============================================================================
259
+ // Type Guards
260
+ // ============================================================================
261
+
262
+ /**
263
+ * Type guard to check if a value is `ResultOk`.
264
+ */
265
+ export const isResultOk = <T, E>(val: Result<T, E>): val is ResultOk<T, E> => {
371
266
  return val instanceof ResultOk;
372
- }
267
+ };
373
268
 
374
- export const isResultErr = <T, E>(val: any): val is ResultErr<T, E> => {
269
+ /**
270
+ * Type guard to check if a value is `ResultErr`.
271
+ */
272
+ export const isResultErr = <T, E>(val: Result<T, E>): val is ResultErr<T, E> => {
375
273
  return val instanceof ResultErr;
376
- }
274
+ };
377
275
 
378
- export class ResultOk<T, E> implements IResult<T, E> {
379
- private readonly _tag = 'Ok' as const;
380
- // @ts-ignore
381
- private readonly _T: T;
382
- // @ts-ignore
383
- private readonly _E: E;
276
+ // ============================================================================
277
+ // ResultOk Implementation
278
+ // ============================================================================
384
279
 
385
- constructor(readonly value: T) {
386
- }
280
+ /**
281
+ * The `Ok` variant of `Result<T, E>`, representing success with a value of type `T`.
282
+ *
283
+ * Uses branded typing for nominal type safety.
284
+ *
285
+ * @typeParam T - The success value type
286
+ * @typeParam E - The error type (phantom - not used at runtime in Ok)
287
+ */
288
+ export class ResultOk<out T, out E = never> implements IResult<T, E>, IResultOkSpecific<T, E> {
289
+ /** Brand for nominal typing - ensures ResultOk is distinct from ResultErr */
290
+ declare readonly [OkBrand]: T;
291
+
292
+ /** Discriminant tag for runtime type checking */
293
+ readonly _tag = 'Ok' as const;
387
294
 
295
+ constructor(readonly value: T) {}
296
+
297
+ // Type guards
388
298
  is_ok(): this is ResultOk<T, E> {
389
299
  return true;
390
300
  }
391
301
 
392
- is_err(): this is never {
302
+ is_err(): this is ResultErr<T, E> {
393
303
  return false;
394
304
  }
395
305
 
@@ -397,10 +307,11 @@ export class ResultOk<T, E> implements IResult<T, E> {
397
307
  return f(this.value);
398
308
  }
399
309
 
400
- is_err_and(_f: (value: E) => boolean): boolean {
310
+ is_err_and(_f: (value: E) => boolean): false {
401
311
  return false;
402
312
  }
403
313
 
314
+ // Conversion to Option
404
315
  ok(): Option<T> {
405
316
  return Some(this.value);
406
317
  }
@@ -409,8 +320,9 @@ export class ResultOk<T, E> implements IResult<T, E> {
409
320
  return None();
410
321
  }
411
322
 
412
- map<U>(fn: (arg: T) => U): Result<U, E> {
413
- return new ResultOk<U, E>(fn(this.value));
323
+ // Transformations
324
+ map<U>(fn: (arg: T) => U): ResultOk<U, E> {
325
+ return new ResultOk(fn(this.value));
414
326
  }
415
327
 
416
328
  map_or<U>(_d: U, f: (arg: T) => U): U {
@@ -421,24 +333,31 @@ export class ResultOk<T, E> implements IResult<T, E> {
421
333
  return f(this.value);
422
334
  }
423
335
 
424
- map_err<U>(_fn: (arg: E) => U): Result<T, U> {
425
- return this as any;
336
+ /**
337
+ * On Ok, map_err is a no-op that changes only the error type parameter.
338
+ * We construct a new ResultOk with the same value but updated type parameter.
339
+ */
340
+ map_err<U>(_fn: (arg: E) => U): ResultOk<T, U> {
341
+ // Type-safe: we're Ok, so E is phantom. Creating new instance preserves type safety.
342
+ return new ResultOk<T, U>(this.value);
426
343
  }
427
344
 
428
- inspect(f: (val: T) => void): Result<T, E> {
345
+ // Inspection
346
+ inspect(f: (val: T) => void): this {
429
347
  f(this.value);
430
-
431
348
  return this;
432
349
  }
433
350
 
434
- inspect_err(_f: (val: E) => void): Result<T, E> {
351
+ inspect_err(_f: (val: E) => void): this {
435
352
  return this;
436
353
  }
437
354
 
355
+ // Iteration
438
356
  iter(): IterableIterator<T> {
439
357
  return [this.value][Symbol.iterator]();
440
358
  }
441
359
 
360
+ // Unwrapping
442
361
  expect(_msg: string): T {
443
362
  return this.value;
444
363
  }
@@ -447,11 +366,7 @@ export class ResultOk<T, E> implements IResult<T, E> {
447
366
  return this.value;
448
367
  }
449
368
 
450
- //unwrap_or_default(): T {
451
- // ! not implemented
452
- //}
453
-
454
- expect_err(msg: string): E {
369
+ expect_err(msg: string): never {
455
370
  throw new Error(msg);
456
371
  }
457
372
 
@@ -459,6 +374,7 @@ export class ResultOk<T, E> implements IResult<T, E> {
459
374
  throw new Error('Called Result.unwrap_err() on an Ok value: ' + this.value);
460
375
  }
461
376
 
377
+ // Combinators
462
378
  and<U>(res: Result<U, E>): Result<U, E> {
463
379
  return res;
464
380
  }
@@ -467,14 +383,21 @@ export class ResultOk<T, E> implements IResult<T, E> {
467
383
  return fn(this.value);
468
384
  }
469
385
 
470
- or<U>(_res: Result<U, E>): Result<U, E> {
471
- return this as any;
386
+ /**
387
+ * On Ok, `or` returns self. We construct a new ResultOk with updated error type.
388
+ */
389
+ or<F>(_res: Result<T, F>): ResultOk<T, F> {
390
+ return new ResultOk<T, F>(this.value);
472
391
  }
473
392
 
474
- or_else<U>(fn: (arg: E) => Result<T, U>): Result<T, U> {
475
- return this as any;
393
+ /**
394
+ * On Ok, `or_else` returns self. We construct a new ResultOk with updated error type.
395
+ */
396
+ or_else<F>(_fn: (arg: E) => Result<T, F>): ResultOk<T, F> {
397
+ return new ResultOk<T, F>(this.value);
476
398
  }
477
399
 
400
+ // Default values
478
401
  unwrap_or(_optb: T): T {
479
402
  return this.value;
480
403
  }
@@ -483,16 +406,16 @@ export class ResultOk<T, E> implements IResult<T, E> {
483
406
  return this.value;
484
407
  }
485
408
 
486
- flatten(): Result<UnwrapResult<T>, E> {
487
- if (this.value instanceof ResultOk || this.value instanceof ResultErr) {
488
- return this.value;
489
- } else {
490
- // This case should not happen if T is always a Result,
491
- // but it's here to satisfy TypeScript's type checker.
492
- return new ResultOk<UnwrapResult<T>, E>(this.value as UnwrapResult<T>);
409
+ // Flattening
410
+ flatten(): FlattenResult<T, E> {
411
+ const val = this.value;
412
+ if (val instanceof ResultOk || val instanceof ResultErr) {
413
+ return val as FlattenResult<T, E>;
493
414
  }
415
+ return this as unknown as FlattenResult<T, E>;
494
416
  }
495
417
 
418
+ // Type narrowing
496
419
  into_ok(): T {
497
420
  return this.value;
498
421
  }
@@ -501,22 +424,49 @@ export class ResultOk<T, E> implements IResult<T, E> {
501
424
  throw new Error('Called Result.into_err() on an Ok value: ' + this.value);
502
425
  }
503
426
 
504
- transmute(): Result<T, never> {
505
- return this as any;
427
+ /**
428
+ * Transmutes to Ok<T, never>, proving there's no error.
429
+ */
430
+ transmute(): ResultOk<T, never> {
431
+ return new ResultOk<T, never>(this.value);
432
+ }
433
+
434
+ /**
435
+ * Transposes Ok(Option<U>) into Option<Result<U, E>>.
436
+ */
437
+ transpose(): any {
438
+ const option = this.value as { _tag: 'Some' | 'None'; value?: unknown; is_some?(): boolean };
439
+ if (option._tag === 'Some' || (option.is_some && option.is_some())) {
440
+ return Some(new ResultOk(option.value));
441
+ } else {
442
+ return None();
443
+ }
506
444
  }
507
445
  }
508
446
 
509
- export class ResultErr<T, E> implements IResult<T, E> {
510
- private readonly _tag: 'Err' = 'Err';
511
- // @ts-ignore
512
- private readonly _T: T;
513
- // @ts-ignore
514
- private readonly _E: E;
447
+ // ============================================================================
448
+ // ResultErr Implementation
449
+ // ============================================================================
515
450
 
516
- constructor(readonly value: E) {
517
- }
451
+ /**
452
+ * The `Err` variant of `Result<T, E>`, representing failure with an error of type `E`.
453
+ *
454
+ * Uses branded typing for nominal type safety.
455
+ *
456
+ * @typeParam T - The success type (phantom - not used at runtime in Err)
457
+ * @typeParam E - The error value type
458
+ */
459
+ export class ResultErr<out T = never, out E = unknown> implements IResult<T, E>, IResultErrSpecific<T, E> {
460
+ /** Brand for nominal typing - ensures ResultErr is distinct from ResultOk */
461
+ declare readonly [ErrBrand]: E;
518
462
 
519
- is_ok(): this is never {
463
+ /** Discriminant tag for runtime type checking */
464
+ readonly _tag = 'Err' as const;
465
+
466
+ constructor(readonly value: E) {}
467
+
468
+ // Type guards
469
+ is_ok(): this is ResultOk<T, E> {
520
470
  return false;
521
471
  }
522
472
 
@@ -524,7 +474,7 @@ export class ResultErr<T, E> implements IResult<T, E> {
524
474
  return true;
525
475
  }
526
476
 
527
- is_ok_and(_f: (value: T) => boolean): boolean {
477
+ is_ok_and(_f: (value: T) => boolean): false {
528
478
  return false;
529
479
  }
530
480
 
@@ -532,6 +482,7 @@ export class ResultErr<T, E> implements IResult<T, E> {
532
482
  return f(this.value);
533
483
  }
534
484
 
485
+ // Conversion to Option
535
486
  ok(): Option<T> {
536
487
  return None();
537
488
  }
@@ -540,8 +491,12 @@ export class ResultErr<T, E> implements IResult<T, E> {
540
491
  return Some(this.value);
541
492
  }
542
493
 
543
- map<U>(_fn: (arg: T) => U): Result<U, E> {
544
- return this as any;
494
+ // Transformations
495
+ /**
496
+ * On Err, map is a no-op that changes only the value type parameter.
497
+ */
498
+ map<U>(_fn: (arg: T) => U): ResultErr<U, E> {
499
+ return new ResultErr<U, E>(this.value);
545
500
  }
546
501
 
547
502
  map_or<U>(d: U, _f: (arg: T) => U): U {
@@ -552,23 +507,26 @@ export class ResultErr<T, E> implements IResult<T, E> {
552
507
  return d(this.value);
553
508
  }
554
509
 
555
- map_err<U>(fn: (arg: E) => U): Result<T, U> {
556
- return new ResultErr<T, U>(fn(this.value));
510
+ map_err<U>(fn: (arg: E) => U): ResultErr<T, U> {
511
+ return new ResultErr(fn(this.value));
557
512
  }
558
513
 
559
- inspect(_f: (val: T) => void): Result<T, E> {
514
+ // Inspection
515
+ inspect(_f: (val: T) => void): this {
560
516
  return this;
561
517
  }
562
518
 
563
- inspect_err(f: (val: E) => void): Result<T, E> {
519
+ inspect_err(f: (val: E) => void): this {
564
520
  f(this.value);
565
521
  return this;
566
522
  }
567
523
 
524
+ // Iteration
568
525
  iter(): IterableIterator<T> {
569
526
  return [][Symbol.iterator]();
570
527
  }
571
528
 
529
+ // Unwrapping
572
530
  expect(msg: string): never {
573
531
  throw new Error(msg);
574
532
  }
@@ -577,10 +535,6 @@ export class ResultErr<T, E> implements IResult<T, E> {
577
535
  throw new Error('Called Result.unwrap() on an Err value: ' + this.value);
578
536
  }
579
537
 
580
- //unwrap_or_default(): never {
581
- // // ! not implemented
582
- //}
583
-
584
538
  expect_err(_msg: string): E {
585
539
  return this.value;
586
540
  }
@@ -589,22 +543,30 @@ export class ResultErr<T, E> implements IResult<T, E> {
589
543
  return this.value;
590
544
  }
591
545
 
592
- and<U>(_res: Result<U, E>): Result<U, E> {
593
- return this as any;
546
+ // Combinators
547
+ /**
548
+ * On Err, `and` returns self. We construct a new ResultErr with updated value type.
549
+ */
550
+ and<U>(_res: Result<U, E>): ResultErr<U, E> {
551
+ return new ResultErr<U, E>(this.value);
594
552
  }
595
553
 
596
- and_then<U>(_fn: (arg: T) => Result<U, E>): Result<U, E> {
597
- return this as any;
554
+ /**
555
+ * On Err, `and_then` returns self. We construct a new ResultErr with updated value type.
556
+ */
557
+ and_then<U>(_fn: (arg: T) => Result<U, E>): ResultErr<U, E> {
558
+ return new ResultErr<U, E>(this.value);
598
559
  }
599
560
 
600
- or<U>(res: Result<U, E>): Result<U, E> {
561
+ or<F>(res: Result<T, F>): Result<T, F> {
601
562
  return res;
602
563
  }
603
564
 
604
- or_else<U>(fn: (arg: E) => Result<T, U>): Result<T, U> {
565
+ or_else<F>(fn: (arg: E) => Result<T, F>): Result<T, F> {
605
566
  return fn(this.value);
606
567
  }
607
568
 
569
+ // Default values
608
570
  unwrap_or(optb: T): T {
609
571
  return optb;
610
572
  }
@@ -613,11 +575,13 @@ export class ResultErr<T, E> implements IResult<T, E> {
613
575
  return fn(this.value);
614
576
  }
615
577
 
616
- flatten(): Result<UnwrapResult<T>, E> {
617
- return new ResultErr(this.value) as Result<never, E>;
578
+ // Flattening
579
+ flatten(): FlattenResult<T, E> {
580
+ return new ResultErr<UnwrapOk<T>, E>(this.value) as FlattenResult<T, E>;
618
581
  }
619
582
 
620
- into_ok(): T {
583
+ // Type narrowing
584
+ into_ok(): never {
621
585
  throw new Error('Called Result.into_ok() on an Err value: ' + this.value);
622
586
  }
623
587
 
@@ -625,37 +589,151 @@ export class ResultErr<T, E> implements IResult<T, E> {
625
589
  return this.value;
626
590
  }
627
591
 
628
- transmute(): Result<never, E> {
629
- return this as any;
592
+ /**
593
+ * Transmutes to Err<never, E>, proving there's no value.
594
+ */
595
+ transmute(): ResultErr<never, E> {
596
+ return new ResultErr<never, E>(this.value);
597
+ }
598
+
599
+ /**
600
+ * Transposes Err(e) into Some(Err(e)).
601
+ * For Err, we always return Some(Err(e)) regardless of the expected Option type.
602
+ */
603
+ transpose(): any {
604
+ return Some(new ResultErr(this.value));
630
605
  }
631
606
  }
632
- export const Ok = <T, E>(val: T): Result<T, never> => {
633
- return new ResultOk<T, E>(val) as Result<T, never>;
607
+
608
+ // ============================================================================
609
+ // Factory Functions
610
+ // ============================================================================
611
+
612
+ /**
613
+ * Creates an `Ok` result containing the given value.
614
+ *
615
+ * The error type defaults to `never`, indicating this Result cannot be an Err.
616
+ * This enables type inference to work correctly in chains.
617
+ *
618
+ * @example
619
+ * const result = Ok(42); // Result<number, never>
620
+ * const mapped = result.map(x => x * 2); // Result<number, never>
621
+ */
622
+ export const Ok = <T>(val: T): ResultOk<T, never> => {
623
+ return new ResultOk<T, never>(val);
634
624
  };
635
625
 
636
- export const Err = <T, E>(val: E): Result<never, E> => {
637
- return new ResultErr<T, E>(val) as Result<never, E>;
626
+ /**
627
+ * Creates an `Err` result containing the given error.
628
+ *
629
+ * The value type defaults to `never`, indicating this Result cannot be Ok.
630
+ * This enables type inference to work correctly in chains.
631
+ *
632
+ * @example
633
+ * const result = Err(new Error("failed")); // Result<never, Error>
634
+ * const handled = result.or(Ok(0)); // Result<number, never>
635
+ */
636
+ export const Err = <E>(val: E): ResultErr<never, E> => {
637
+ return new ResultErr<never, E>(val);
638
638
  };
639
639
 
640
- export const try_catch =
641
- <T, E = Error>(
642
- fn: () => T,
643
- ): Result<T, E> => {
644
- try {
645
- return Ok(fn());
646
- // @ts-ignore (error is nominally of type any / unknown, not Error)
647
- } catch (error: Error) {
648
- return Err(error);
649
- }
650
- };
651
-
652
- export const result_from_promise =
653
- async <T, E = Error>(
654
- val: Promise<T>,
655
- ): Promise<Result<T, E>> => {
656
- try {
657
- return new ResultOk<T, never>(await val);
658
- } catch (error: unknown) {
659
- return new ResultErr<never, E>(error as E);
640
+ // ============================================================================
641
+ // Utility Functions
642
+ // ============================================================================
643
+
644
+ /**
645
+ * Executes a function and wraps its result in a `Result`.
646
+ *
647
+ * If the function succeeds, returns `Ok(value)`.
648
+ * If it throws, returns `Err(error)`.
649
+ *
650
+ * @typeParam T - The return type of the function
651
+ * @typeParam E - The error type (defaults to Error)
652
+ *
653
+ * @example
654
+ * const result = try_catch(() => JSON.parse(jsonString));
655
+ * // Result<unknown, Error>
656
+ */
657
+ export const try_catch = <T, E = Error>(fn: () => T): Result<T, E> => {
658
+ try {
659
+ return Ok(fn()) as Result<T, E>;
660
+ } catch (error: unknown) {
661
+ return Err(error as E) as Result<T, E>;
662
+ }
663
+ };
664
+
665
+ /**
666
+ * Converts a Promise to a Result wrapped in a Promise.
667
+ *
668
+ * If the promise resolves, returns `Ok(value)`.
669
+ * If it rejects, returns `Err(error)`.
670
+ *
671
+ * @typeParam T - The resolved value type
672
+ * @typeParam E - The error type (defaults to Error)
673
+ *
674
+ * @example
675
+ * const result = await result_from_promise(fetch('/api/data'));
676
+ * // Result<Response, Error>
677
+ */
678
+ export const result_from_promise = async <T, E = Error>(
679
+ val: Promise<T>,
680
+ ): Promise<Result<T, E>> => {
681
+ try {
682
+ return Ok(await val) as Result<T, E>;
683
+ } catch (error: unknown) {
684
+ return Err(error as E) as Result<T, E>;
685
+ }
686
+ };
687
+
688
+ // ============================================================================
689
+ // Advanced Type Utilities
690
+ // ============================================================================
691
+
692
+ /**
693
+ * Combines multiple Results into a single Result containing an array.
694
+ *
695
+ * If all Results are Ok, returns Ok with array of values.
696
+ * If any Result is Err, returns the first Err encountered.
697
+ *
698
+ * @example
699
+ * const results = collect([Ok(1), Ok(2), Ok(3)]);
700
+ * // Result<[number, number, number], never>
701
+ */
702
+ export function collect<T extends readonly Result<any, any>[]>(
703
+ results: T
704
+ ): Result<
705
+ { [K in keyof T]: T[K] extends Result<infer U, any> ? U : never },
706
+ { [K in keyof T]: T[K] extends Result<any, infer E> ? E : never }[number]
707
+ > {
708
+ const values: any[] = [];
709
+ for (const result of results) {
710
+ if (result.is_err()) {
711
+ return result as any;
660
712
  }
661
- };
713
+ values.push(result.value);
714
+ }
715
+ return Ok(values) as any;
716
+ }
717
+
718
+ /**
719
+ * Type-safe match expression for Result.
720
+ *
721
+ * @example
722
+ * const message = matchResult(result, {
723
+ * Ok: (value) => `Success: ${value}`,
724
+ * Err: (error) => `Failed: ${error.message}`,
725
+ * });
726
+ */
727
+ export function matchResult<T, E, R>(
728
+ result: Result<T, E>,
729
+ handlers: {
730
+ Ok: (value: T) => R;
731
+ Err: (error: E) => R;
732
+ }
733
+ ): R {
734
+ if (result.is_ok()) {
735
+ return handlers.Ok(result.value);
736
+ } else {
737
+ return handlers.Err(result.value);
738
+ }
739
+ }