nalloc 0.0.1

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.
Files changed (58) hide show
  1. package/README.md +282 -0
  2. package/build/devtools.cjs +79 -0
  3. package/build/devtools.cjs.map +1 -0
  4. package/build/devtools.d.ts +82 -0
  5. package/build/devtools.js +43 -0
  6. package/build/devtools.js.map +1 -0
  7. package/build/index.cjs +76 -0
  8. package/build/index.cjs.map +1 -0
  9. package/build/index.d.ts +4 -0
  10. package/build/index.js +5 -0
  11. package/build/index.js.map +1 -0
  12. package/build/option.cjs +279 -0
  13. package/build/option.cjs.map +1 -0
  14. package/build/option.d.ts +356 -0
  15. package/build/option.js +157 -0
  16. package/build/option.js.map +1 -0
  17. package/build/result.cjs +381 -0
  18. package/build/result.cjs.map +1 -0
  19. package/build/result.d.ts +442 -0
  20. package/build/result.js +229 -0
  21. package/build/result.js.map +1 -0
  22. package/build/safe.cjs +88 -0
  23. package/build/safe.cjs.map +1 -0
  24. package/build/safe.d.ts +29 -0
  25. package/build/safe.js +18 -0
  26. package/build/safe.js.map +1 -0
  27. package/build/testing.cjs +111 -0
  28. package/build/testing.cjs.map +1 -0
  29. package/build/testing.d.ts +85 -0
  30. package/build/testing.js +81 -0
  31. package/build/testing.js.map +1 -0
  32. package/build/types.cjs +78 -0
  33. package/build/types.cjs.map +1 -0
  34. package/build/types.d.ts +137 -0
  35. package/build/types.js +36 -0
  36. package/build/types.js.map +1 -0
  37. package/build/unsafe.cjs +82 -0
  38. package/build/unsafe.cjs.map +1 -0
  39. package/build/unsafe.d.ts +27 -0
  40. package/build/unsafe.js +11 -0
  41. package/build/unsafe.js.map +1 -0
  42. package/package.json +93 -0
  43. package/src/__tests__/index.ts +13 -0
  44. package/src/__tests__/option.ts +610 -0
  45. package/src/__tests__/option.types.ts +120 -0
  46. package/src/__tests__/result.ts +721 -0
  47. package/src/__tests__/result.types.ts +249 -0
  48. package/src/__tests__/safe.ts +24 -0
  49. package/src/__tests__/tooling.ts +86 -0
  50. package/src/__tests__/unsafe.ts +24 -0
  51. package/src/devtools.ts +97 -0
  52. package/src/index.ts +18 -0
  53. package/src/option.ts +510 -0
  54. package/src/result.ts +676 -0
  55. package/src/safe.ts +58 -0
  56. package/src/testing.ts +159 -0
  57. package/src/types.ts +201 -0
  58. package/src/unsafe.ts +47 -0
package/src/option.ts ADDED
@@ -0,0 +1,510 @@
1
+ import { NONE, isSome, isNone, optionOf as of, err, isOk, isErr } from './types.js';
2
+ import type { Some, None, Option, NoneValueType, ValueType, Result, Ok, Widen } from './types.js';
3
+
4
+ export type { Some, None, Option };
5
+ export { isSome, isNone, of };
6
+
7
+ /**
8
+ * Creates an Option from a nullable value with widened types.
9
+ * @param value - The value to wrap
10
+ * @returns Some(value) if non-null, None otherwise
11
+ * @example
12
+ * fromNullable(42) // Some(42) with type Option<number>
13
+ * fromNullable(null) // None
14
+ */
15
+ export function fromNullable(value: null): None;
16
+ export function fromNullable(value: undefined): None;
17
+ export function fromNullable<T>(value: T | NoneValueType): Option<Widen<T>>;
18
+ export function fromNullable<T>(value: T | NoneValueType): Option<Widen<T>> {
19
+ return of(value) as Option<Widen<T>>;
20
+ }
21
+
22
+ /**
23
+ * Creates an Option from a Promise. Resolves to Some if successful, None on rejection.
24
+ * @param promise - The promise to convert
25
+ * @param onRejected - Optional handler for rejected promises
26
+ * @returns Promise resolving to Some(value) or None
27
+ * @example
28
+ * await fromPromise(Promise.resolve(42)) // Some(42)
29
+ * await fromPromise(Promise.reject('error')) // None
30
+ */
31
+ export async function fromPromise<T>(promise: Promise<T | NoneValueType>, onRejected?: (error: unknown) => T | NoneValueType): Promise<Option<T>> {
32
+ try {
33
+ const value = await promise;
34
+ return of(value as T);
35
+ } catch (error) {
36
+ if (!onRejected) {
37
+ return NONE;
38
+ }
39
+ return of(onRejected(error));
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Unwraps an Option or returns a computed value if None.
45
+ * @param opt - The Option to unwrap
46
+ * @param onNone - Function called if opt is None
47
+ * @returns The value if Some, or the result of onNone()
48
+ * @example
49
+ * unwrapOrReturn(some(42), () => 0) // 42
50
+ * unwrapOrReturn(none, () => 0) // 0
51
+ */
52
+ export function unwrapOrReturn<T, R>(opt: Option<T>, onNone: () => R): Widen<T> | R {
53
+ return isSome(opt) ? (opt as Widen<T>) : onNone();
54
+ }
55
+
56
+ /**
57
+ * Asserts that an Option is Some, throwing if None.
58
+ * @param opt - The Option to assert
59
+ * @param message - Custom error message
60
+ * @throws Error if opt is None
61
+ * @example
62
+ * assertSome(some(42)) // passes
63
+ * assertSome(none) // throws Error
64
+ */
65
+ export function assertSome<T>(opt: Option<T>, message?: string): asserts opt is Some<ValueType<T>> {
66
+ if (isNone(opt)) {
67
+ throw new Error(message ?? 'Expected Option to contain a value');
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Compile-time type assertion helper to satisfy Option type constraints.
73
+ *
74
+ * WARNING: This function performs NO runtime validation. It is a no-op at
75
+ * runtime to preserve zero-allocation semantics. Use assertSome() if you
76
+ * need runtime validation that a value is Some.
77
+ *
78
+ * @param _ - The value to assert as Option (not validated at runtime)
79
+ * @example
80
+ * const value: number | null = getValue();
81
+ * satisfiesOption(value); // Compiles, but no runtime check
82
+ * // value is now typed as Option<number>
83
+ */
84
+ export function satisfiesOption<T>(_: Option<T> | T): asserts _ is Option<T> {
85
+ // Compile-time only - no runtime validation to preserve zero-allocation semantics.
86
+ }
87
+
88
+ /**
89
+ * Maps and filters an iterable, collecting only Some values.
90
+ * @param values - The iterable to process
91
+ * @param fn - Function that returns Option for each value
92
+ * @returns Array of unwrapped Some values
93
+ * @example
94
+ * filterMap([1, 2, 3], n => n > 1 ? some(n * 2) : none) // [4, 6]
95
+ */
96
+ export function filterMap<T, U>(values: Iterable<T>, fn: (value: T) => Option<U>): U[] {
97
+ const collected: U[] = [];
98
+ for (const value of values) {
99
+ const mapped = fn(value);
100
+ if (isSome(mapped)) {
101
+ collected.push(mapped);
102
+ }
103
+ }
104
+ return collected;
105
+ }
106
+
107
+ /**
108
+ * Transforms the value inside a Some, or returns None.
109
+ * @param opt - The Option to map
110
+ * @param fn - Transform function
111
+ * @returns Some(fn(value)) if Some, None otherwise
112
+ * @example
113
+ * map(some(2), x => x * 2) // Some(4)
114
+ * map(none, x => x * 2) // None
115
+ */
116
+ export function map<T, U>(opt: None, fn: (value: T) => U): None;
117
+ export function map<T, U>(opt: Option<T>, fn: (value: T) => U | NoneValueType): Option<U>;
118
+ export function map<T, U>(opt: Option<T>, fn: (value: T) => U | NoneValueType): Option<U> {
119
+ if (isNone(opt)) return NONE;
120
+ const result = fn(opt);
121
+ return result === null || result === undefined ? NONE : (result as Some<ValueType<U>>);
122
+ }
123
+
124
+ /**
125
+ * Chains Option-returning functions. Returns None if the input is None.
126
+ * @param opt - The Option to chain
127
+ * @param fn - Function returning an Option
128
+ * @returns The result of fn(value) if Some, None otherwise
129
+ * @example
130
+ * flatMap(some(2), x => some(x * 2)) // Some(4)
131
+ * flatMap(some(2), x => none) // None
132
+ * flatMap(none, x => some(x * 2)) // None
133
+ */
134
+ export function flatMap<T, U>(opt: None, fn: (value: T) => Option<U>): None;
135
+ export function flatMap<T, U>(opt: Option<T>, fn: (value: T) => Option<U>): Option<U>;
136
+ export function flatMap<T, U>(opt: Option<T>, fn: (value: T) => Option<U>): Option<U> {
137
+ return isNone(opt) ? NONE : fn(opt);
138
+ }
139
+
140
+ /**
141
+ * Alias for flatMap. Chains Option-returning functions.
142
+ * @param opt - The Option to chain
143
+ * @param fn - Function returning an Option
144
+ * @returns The result of fn(value) if Some, None otherwise
145
+ */
146
+ export function andThen<T, U>(opt: None, fn: (value: T) => Option<U>): None;
147
+ export function andThen<T, U>(opt: Option<T>, fn: (value: T) => Option<U>): Option<U>;
148
+ export function andThen<T, U>(opt: Option<T>, fn: (value: T) => Option<U>): Option<U> {
149
+ return flatMap(opt, fn);
150
+ }
151
+
152
+ /**
153
+ * Executes a side effect if Some, then returns the original Option.
154
+ * @param opt - The Option to tap
155
+ * @param fn - Side effect function
156
+ * @returns The original Option unchanged
157
+ * @example
158
+ * tap(some(42), x => console.log(x)) // logs 42, returns Some(42)
159
+ */
160
+ export function tap<T>(opt: None, fn: (value: T) => void): None;
161
+ export function tap<T>(opt: Some<T>, fn: (value: T) => void): Some<T>;
162
+ export function tap<T>(opt: Option<T>, fn: (value: T) => void): Option<T>;
163
+ export function tap<T>(opt: Option<T>, fn: (value: T) => void): Option<T> {
164
+ if (isSome(opt)) {
165
+ fn(opt);
166
+ }
167
+ return opt;
168
+ }
169
+
170
+ /**
171
+ * Returns Some if the value passes the predicate, None otherwise.
172
+ * @param opt - The Option to filter
173
+ * @param predicate - Test function
174
+ * @returns Some if predicate returns true, None otherwise
175
+ * @example
176
+ * filter(some(4), x => x > 2) // Some(4)
177
+ * filter(some(1), x => x > 2) // None
178
+ */
179
+ export function filter<T>(opt: None, predicate: (value: T) => boolean): None;
180
+ export function filter<T>(opt: Option<T>, predicate: (value: T) => boolean): Option<T>;
181
+ export function filter<T>(opt: Option<T>, predicate: (value: T) => boolean): Option<T> {
182
+ return isSome(opt) && predicate(opt) ? opt : NONE;
183
+ }
184
+
185
+ /**
186
+ * Extracts the value from Some, throws if None.
187
+ * @param opt - The Option to unwrap
188
+ * @returns The contained value
189
+ * @throws Error if opt is None
190
+ * @example
191
+ * unwrap(some(42)) // 42
192
+ * unwrap(none) // throws Error
193
+ */
194
+ export function unwrap<T>(opt: Option<T>): T {
195
+ if (isNone(opt)) {
196
+ throw new Error('Called unwrap on None');
197
+ }
198
+ return opt;
199
+ }
200
+
201
+ /**
202
+ * Extracts the value from Some, or returns a default value.
203
+ * @param opt - The Option to unwrap
204
+ * @param defaultValue - Value to return if None
205
+ * @returns The contained value or defaultValue
206
+ * @example
207
+ * unwrapOr(some(42), 0) // 42
208
+ * unwrapOr(none, 0) // 0
209
+ */
210
+ export function unwrapOr<T>(opt: Option<T>, defaultValue: T): T {
211
+ return isSome(opt) ? opt : defaultValue;
212
+ }
213
+
214
+ /**
215
+ * Extracts the value from Some, or computes a default.
216
+ * @param opt - The Option to unwrap
217
+ * @param fn - Function to compute default value
218
+ * @returns The contained value or fn()
219
+ * @example
220
+ * unwrapOrElse(some(42), () => 0) // 42
221
+ * unwrapOrElse(none, () => 0) // 0
222
+ */
223
+ export function unwrapOrElse<T>(opt: Option<T>, fn: () => T): T {
224
+ return isSome(opt) ? opt : fn();
225
+ }
226
+
227
+ /**
228
+ * Extracts the value from Some, throws with custom message if None.
229
+ * @param opt - The Option to unwrap
230
+ * @param message - Error message if None
231
+ * @returns The contained value
232
+ * @throws Error with message if opt is None
233
+ * @example
234
+ * expect(some(42), 'missing value') // 42
235
+ * expect(none, 'missing value') // throws Error('missing value')
236
+ */
237
+ export function expect<T>(opt: Option<T>, message: string): T {
238
+ if (isNone(opt)) {
239
+ throw new Error(message);
240
+ }
241
+ return opt;
242
+ }
243
+
244
+ /**
245
+ * Returns the first Some, or the second Option if the first is None.
246
+ * @param opt - First Option
247
+ * @param optb - Fallback Option
248
+ * @returns opt if Some, optb otherwise
249
+ * @example
250
+ * or(some(1), some(2)) // Some(1)
251
+ * or(none, some(2)) // Some(2)
252
+ */
253
+ export function or<T>(opt: Some<T>, optb: Option<T>): Some<T>;
254
+ export function or<T>(opt: Option<T>, optb: Option<T>): Option<T>;
255
+ export function or<T>(opt: Option<T>, optb: Option<T>): Option<T> {
256
+ return isSome(opt) ? opt : optb;
257
+ }
258
+
259
+ /**
260
+ * Returns opt if Some, otherwise computes a fallback Option.
261
+ * @param opt - First Option
262
+ * @param fn - Function to compute fallback
263
+ * @returns opt if Some, fn() otherwise
264
+ * @example
265
+ * orElse(some(1), () => some(2)) // Some(1)
266
+ * orElse(none, () => some(2)) // Some(2)
267
+ */
268
+ export function orElse<T>(opt: Some<T>, fn: () => Option<T>): Some<T>;
269
+ export function orElse<T>(opt: Option<T>, fn: () => Option<T>): Option<T>;
270
+ export function orElse<T>(opt: Option<T>, fn: () => Option<T>): Option<T> {
271
+ return isSome(opt) ? opt : fn();
272
+ }
273
+
274
+ /**
275
+ * Returns Some if exactly one of the Options is Some.
276
+ * @param opt - First Option
277
+ * @param optb - Second Option
278
+ * @returns Some if exactly one is Some, None otherwise
279
+ * @example
280
+ * xor(some(1), none) // Some(1)
281
+ * xor(none, some(2)) // Some(2)
282
+ * xor(some(1), some(2)) // None
283
+ * xor(none, none) // None
284
+ */
285
+ export function xor<T>(opt: Option<T>, optb: Option<T>): Option<T> {
286
+ if (isSome(opt) && isNone(optb)) return opt;
287
+ if (isNone(opt) && isSome(optb)) return optb;
288
+ return NONE;
289
+ }
290
+
291
+ /**
292
+ * Returns optb if opt is Some, None otherwise.
293
+ * @param opt - First Option
294
+ * @param optb - Second Option
295
+ * @returns optb if opt is Some, None otherwise
296
+ * @example
297
+ * and(some(1), some(2)) // Some(2)
298
+ * and(none, some(2)) // None
299
+ */
300
+ export function and<U>(opt: None, optb: Option<U>): None;
301
+ export function and<T, U>(opt: Option<T>, optb: Option<U>): Option<U>;
302
+ export function and<T, U>(opt: Option<T>, optb: Option<U>): Option<U> {
303
+ return isSome(opt) ? optb : NONE;
304
+ }
305
+
306
+ /**
307
+ * Combines two Options into an Option of a tuple.
308
+ * @param opt - First Option
309
+ * @param other - Second Option
310
+ * @returns Some([a, b]) if both are Some, None otherwise
311
+ * @example
312
+ * zip(some(1), some('a')) // Some([1, 'a'])
313
+ * zip(some(1), none) // None
314
+ */
315
+ export function zip<T, U>(opt: Option<T>, other: Option<U>): Option<[T, U]> {
316
+ return isSome(opt) && isSome(other) ? ([opt, other] as Some<[T, U]>) : NONE;
317
+ }
318
+
319
+ /**
320
+ * Splits an Option of a tuple into a tuple of Options.
321
+ * @param opt - Option containing a tuple
322
+ * @returns Tuple of Options
323
+ * @example
324
+ * unzip(some([1, 'a'])) // [Some(1), Some('a')]
325
+ * unzip(none) // [None, None]
326
+ */
327
+ export function unzip<T, U>(opt: Option<[T, U]>): [Option<T>, Option<U>] {
328
+ if (isNone(opt)) return [NONE, NONE];
329
+ const [a, b] = opt;
330
+ return [of(a), of(b)];
331
+ }
332
+
333
+ /**
334
+ * Maps the value and returns it, or returns a default.
335
+ * @param opt - The Option to map
336
+ * @param defaultValue - Value if None
337
+ * @param fn - Transform function
338
+ * @returns fn(value) if Some, defaultValue otherwise
339
+ * @example
340
+ * mapOr(some(2), 0, x => x * 2) // 4
341
+ * mapOr(none, 0, x => x * 2) // 0
342
+ */
343
+ export function mapOr<T, U>(opt: Option<T>, defaultValue: U, fn: (value: T) => U): U {
344
+ return isSome(opt) ? fn(opt) : defaultValue;
345
+ }
346
+
347
+ /**
348
+ * Maps the value and returns it, or computes a default.
349
+ * @param opt - The Option to map
350
+ * @param defaultFn - Function to compute default
351
+ * @param fn - Transform function
352
+ * @returns fn(value) if Some, defaultFn() otherwise
353
+ * @example
354
+ * mapOrElse(some(2), () => 0, x => x * 2) // 4
355
+ * mapOrElse(none, () => 0, x => x * 2) // 0
356
+ */
357
+ export function mapOrElse<T, U>(opt: Option<T>, defaultFn: () => U, fn: (value: T) => U): U {
358
+ return isSome(opt) ? fn(opt) : defaultFn();
359
+ }
360
+
361
+ /**
362
+ * Flattens a nested Option.
363
+ * @param opt - Option containing an Option
364
+ * @returns The inner Option
365
+ * @example
366
+ * flatten(some(some(42))) // Some(42)
367
+ * flatten(some(none)) // None
368
+ * flatten(none) // None
369
+ */
370
+ export function flatten<T>(opt: Option<Option<T>>): Option<T> {
371
+ return isNone(opt) ? NONE : (opt as Option<T>);
372
+ }
373
+
374
+ /**
375
+ * Checks if the Option contains a specific value (using ===).
376
+ * @param opt - The Option to check
377
+ * @param value - The value to compare
378
+ * @returns true if Some and value matches
379
+ * @example
380
+ * contains(some(42), 42) // true
381
+ * contains(some(42), 0) // false
382
+ * contains(none, 42) // false
383
+ */
384
+ export function contains<T>(opt: Option<T>, value: T): boolean {
385
+ return isSome(opt) && opt === value;
386
+ }
387
+
388
+ /**
389
+ * Checks if Some and the value satisfies a predicate.
390
+ * @param opt - The Option to check
391
+ * @param predicate - Test function
392
+ * @returns true if Some and predicate returns true
393
+ * @example
394
+ * isSomeAnd(some(4), x => x > 2) // true
395
+ * isSomeAnd(some(1), x => x > 2) // false
396
+ * isSomeAnd(none, x => x > 2) // false
397
+ */
398
+ export function isSomeAnd<T>(opt: Option<T>, predicate: (value: T) => boolean): boolean {
399
+ return isSome(opt) && predicate(opt);
400
+ }
401
+
402
+ /**
403
+ * Converts an Option to an array.
404
+ * @param opt - The Option to convert
405
+ * @returns [value] if Some, [] if None
406
+ * @example
407
+ * toArray(some(42)) // [42]
408
+ * toArray(none) // []
409
+ */
410
+ export function toArray<T>(opt: Option<T>): T[] {
411
+ return isSome(opt) ? [opt] : [];
412
+ }
413
+
414
+ /**
415
+ * Converts an Option to a nullable value.
416
+ * @param opt - The Option to convert
417
+ * @returns The value if Some, null if None
418
+ * @example
419
+ * toNullable(some(42)) // 42
420
+ * toNullable(none) // null
421
+ */
422
+ export function toNullable<T>(opt: Option<T>): T | null {
423
+ return isSome(opt) ? opt : null;
424
+ }
425
+
426
+ /**
427
+ * Converts an Option to an undefined-able value.
428
+ * @param opt - The Option to convert
429
+ * @returns The value if Some, undefined if None
430
+ * @example
431
+ * toUndefined(some(42)) // 42
432
+ * toUndefined(none) // undefined
433
+ */
434
+ export function toUndefined<T>(opt: Option<T>): T | undefined {
435
+ return isSome(opt) ? opt : undefined;
436
+ }
437
+
438
+ /**
439
+ * Pattern matches on an Option, handling both Some and None cases.
440
+ * @param opt - The Option to match
441
+ * @param onSome - Handler for Some case
442
+ * @param onNone - Handler for None case
443
+ * @returns Result of the matching handler
444
+ * @example
445
+ * match(some(42), x => x * 2, () => 0) // 84
446
+ * match(none, x => x * 2, () => 0) // 0
447
+ */
448
+ export function match<T, U>(opt: Option<T>, onSome: (value: T) => U, onNone: () => U): U {
449
+ return isSome(opt) ? onSome(opt) : onNone();
450
+ }
451
+
452
+ /**
453
+ * Converts an Option to a Result, using a provided error if None.
454
+ * @param opt - The Option to convert
455
+ * @param error - Error value if None
456
+ * @returns Ok(value) if Some, Err(error) if None
457
+ * @example
458
+ * okOr(some(42), 'missing') // Ok(42)
459
+ * okOr(none, 'missing') // Err('missing')
460
+ */
461
+ export function okOr<T, E>(opt: Option<T>, error: E): Result<T, E> {
462
+ return isSome(opt) ? (opt as unknown as Ok<T>) : err(error);
463
+ }
464
+
465
+ /**
466
+ * Converts an Option to a Result, computing the error if None.
467
+ * @param opt - The Option to convert
468
+ * @param fn - Function to compute error
469
+ * @returns Ok(value) if Some, Err(fn()) if None
470
+ * @example
471
+ * okOrElse(some(42), () => 'missing') // Ok(42)
472
+ * okOrElse(none, () => 'missing') // Err('missing')
473
+ */
474
+ export function okOrElse<T, E>(opt: Option<T>, fn: () => E): Result<T, E> {
475
+ return isSome(opt) ? (opt as unknown as Ok<T>) : err(fn());
476
+ }
477
+
478
+ /**
479
+ * Extracts the Ok value from a Result as an Option.
480
+ * @param result - The Result to convert
481
+ * @returns Some(value) if Ok, None if Err
482
+ * @example
483
+ * ofOk(ok(42)) // Some(42)
484
+ * ofOk(err('failed')) // None
485
+ */
486
+ export function ofOk<T, E>(result: Result<T, E>): Option<T> {
487
+ if (!isOk(result) || !isSome(result)) {
488
+ return NONE;
489
+ }
490
+ return result as Some<T>;
491
+ }
492
+
493
+ /**
494
+ * Extracts the Err value from a Result as an Option.
495
+ * @param result - The Result to convert
496
+ * @returns Some(error) if Err, None if Ok
497
+ * @example
498
+ * ofErr(err('failed')) // Some('failed')
499
+ * ofErr(ok(42)) // None
500
+ */
501
+ export function ofErr<T, E>(result: Result<T, E>): Option<E> {
502
+ if (!isErr(result)) {
503
+ return NONE;
504
+ }
505
+ const error = (result as { error: E }).error;
506
+ if (!isSome(error)) {
507
+ return NONE;
508
+ }
509
+ return error as Some<E>;
510
+ }