UNPKG

40.6 kBTypeScriptView Raw
1/**
2 [[include:doc/result.md]]
3
4 @module
5 */
6import Unit from './unit.js';
7/**
8 Discriminant for {@linkcode Ok} and {@linkcode Err} variants of the
9 {@linkcode Result} type.
10
11 You can use the discriminant via the `variant` property of `Result` instances
12 if you need to match explicitly on it.
13 */
14export declare const Variant: {
15 readonly Ok: "Ok";
16 readonly Err: "Err";
17};
18export type Variant = keyof typeof Variant;
19export interface OkJSON<T> {
20 variant: 'Ok';
21 value: T;
22}
23export interface ErrJSON<E> {
24 variant: 'Err';
25 error: E;
26}
27export type ResultJSON<T, E> = OkJSON<T> | ErrJSON<E>;
28declare class ResultImpl<T, E> {
29 private repr;
30 private constructor();
31 /**
32 Create an instance of {@linkcode Ok}.
33
34 Note: While you *may* create the {@linkcode Result} type via normal
35 JavaScript class construction, it is not recommended for the functional
36 style for which the library is intended. Instead, use {@linkcode ok}.
37
38 ```ts
39 // Avoid:
40 const aString = new Result.Ok('characters');
41
42 // Prefer:
43 const aString = Result.ok('characters);
44 ```
45
46 Note that you may explicitly pass {@linkcode Unit} to the {@linkcode Ok}
47 constructor to create a `Result<Unit, E>`. However, you may *not* call the
48 `Ok` constructor with `null` or `undefined` to get that result (the type
49 system won't allow you to construct it that way). Instead, for convenience,
50 you can simply call {@linkcode ok}, which will construct the type correctly.
51 */
52 static ok<T extends {}, E = never>(): Result<Unit, E>;
53 /**
54 Create an instance of {@linkcode Ok}.
55
56 Note: While you *may* create the {@linkcode Result} type via normal
57 JavaScript class construction, it is not recommended for the functional
58 style for which the library is intended. Instead, use {@linkcode ok}.
59
60 ```ts
61 // Avoid:
62 const aString = new Result.Ok('characters');
63
64 // Prefer:
65 const aString = Result.ok('characters);
66 ```
67
68 Note that you may explicitly pass {@linkcode Unit} to the {@linkcode Ok}
69 constructor to create a `Result<Unit, E>`. However, you may *not* call the
70 `Ok` constructor with `null` or `undefined` to get that result (the type
71 system won't allow you to construct it that way). Instead, for convenience,
72 you can simply call {@linkcode ok}, which will construct the type correctly.
73
74 @param value The value to wrap in an `Ok`.
75 */
76 static ok<T, E = never>(value: T): Result<T, E>;
77 /**
78 Create an instance of {@linkcode Err}.
79
80 Note: While you *may* create the {@linkcode Result} type via normal
81 JavaScript class construction, it is not recommended for the functional
82 style for which the library is intended. Instead, use {@linkcode err}.
83
84 ```ts
85 // Avoid:
86 const anErr = new Result.Err('alas, failure');
87
88 // Prefer:
89 const anErr = Result.err('alas, failure');
90 ```
91 */
92 static err<T = never, E = never>(): Result<T, Unit>;
93 /**
94 Create an instance of {@linkcode Err}.
95
96 Note: While you *may* create the {@linkcode Result} type via normal
97 JavaScript class construction, it is not recommended for the functional
98 style for which the library is intended. Instead, use {@linkcode err}.
99
100 ```ts
101 // Avoid:
102 const anErr = new Result.Err('alas, failure');
103
104 // Prefer:
105 const anErr = Result.err('alas, failure');
106 ```
107
108 @param error The value to wrap in an `Err`.
109 */
110 static err<T = never, E = never>(error: E): Result<T, E>;
111 /** Distinguish between the {@linkcode Variant.Ok} and {@linkcode Variant.Err} {@linkcode Variant variants}. */
112 get variant(): Variant;
113 /**
114 The wrapped value.
115
116 @throws if you access when the {@linkcode Result} is not {@linkcode Ok}
117 */
118 get value(): T | never;
119 /**
120 The wrapped error value.
121
122 @throws if you access when the {@linkcode Result} is not {@linkcode Err}
123 */
124 get error(): E | never;
125 /** Is the {@linkcode Result} an {@linkcode Ok}? */
126 get isOk(): boolean;
127 /** Is the `Result` an `Err`? */
128 get isErr(): boolean;
129 /** Method variant for {@linkcode map} */
130 map<U>(mapFn: (t: T) => U): Result<U, E>;
131 /** Method variant for {@linkcode mapOr} */
132 mapOr<U>(orU: U, mapFn: (t: T) => U): U;
133 /** Method variant for {@linkcode mapOrElse} */
134 mapOrElse<U>(orElseFn: (err: E) => U, mapFn: (t: T) => U): U;
135 /** Method variant for {@linkcode match} */
136 match<U>(matcher: Matcher<T, E, U>): U;
137 /** Method variant for {@linkcode mapErr} */
138 mapErr<F>(mapErrFn: (e: E) => F): Result<T, F>;
139 /** Method variant for {@linkcode or} */
140 or<F>(orResult: Result<T, F>): Result<T, F>;
141 /** Method variant for {@linkcode orElse} */
142 orElse<F>(orElseFn: (err: E) => Result<T, F>): Result<T, F>;
143 /** Method variant for {@linkcode and} */
144 and<U>(mAnd: Result<U, E>): Result<U, E>;
145 /** Method variant for {@linkcode andThen} */
146 andThen<U>(andThenFn: (t: T) => Result<U, E>): Result<U, E>;
147 /** Method variant for {@linkcode unwrapOr} */
148 unwrapOr<U = T>(defaultValue: U): T | U;
149 /** Method variant for {@linkcode unwrapOrElse} */
150 unwrapOrElse<U>(elseFn: (error: E) => U): T | U;
151 /** Method variant for {@linkcode toString} */
152 toString(): string;
153 /** Method variant for {@linkcode toJSON} */
154 toJSON(): ResultJSON<T, E>;
155 /** Method variant for {@linkcode equals} */
156 equals(comparison: Result<T, E>): boolean;
157 /** Method variant for {@linkcode ap} */
158 ap<A, B>(this: Result<(a: A) => B, E>, r: Result<A, E>): Result<B, E>;
159 cast(): this;
160}
161/**
162 An `Ok` instance is the *successful* variant instance of the
163 {@linkcode Result} type, representing a successful outcome from an operation
164 which may fail. For a full discussion, see the module docs.
165
166 @template T The type wrapped in this `Ok` variant of `Result`.
167 @template E The type which would be wrapped in an `Err` variant of `Result`.
168 */
169export interface Ok<T, E> extends Omit<ResultImpl<T, E>, 'error' | 'cast'> {
170 /** `Ok` is always `Variant.Ok`. */
171 readonly variant: 'Ok';
172 isOk: true;
173 isErr: false;
174 /** The wrapped value */
175 value: T;
176 cast<F>(): Result<T, F>;
177}
178/**
179 An `Err` instance is the *failure* variant instance of the {@linkcode Result}
180 type, representing a failure outcome from an operation which may fail. For a
181 full discussion, see the module docs.
182
183 @template T The type which would be wrapped in an `Ok` variant of `Result`.
184 @template E The type wrapped in this `Err` variant of `Result`.
185 */
186export interface Err<T, E> extends Omit<ResultImpl<T, E>, 'value' | 'cast'> {
187 /** `Err` is always `Variant.Err`. */
188 readonly variant: 'Err';
189 isOk: false;
190 isErr: true;
191 /** The wrapped error value. */
192 error: E;
193 cast<U>(): Result<U, E>;
194}
195/**
196 Execute the provided callback, wrapping the return value in {@linkcode Ok} or
197 {@linkcode Err Err(error)} if there is an exception.
198
199 ```ts
200 const aSuccessfulOperation = () => 2 + 2;
201
202 const anOkResult = Result.tryOr('Oh noes!!1', () => {
203 aSuccessfulOperation()
204 }); // => Ok(4)
205
206 const thisOperationThrows = () => throw new Error('Bummer');
207
208 const anErrResult = Result.tryOr('Oh noes!!1', () => {
209 thisOperationThrows();
210 }); // => Err('Oh noes!!1')
211 ```
212
213 @param error The error value in case of an exception
214 @param callback The callback to try executing
215 */
216export declare function tryOr<T, E>(error: E, callback: () => T): Result<T, E>;
217export declare function tryOr<T, E>(error: E): (callback: () => T) => Result<T, E>;
218/**
219 Create an instance of {@linkcode Ok}.
220
221 If you need to create an instance with a specific type (as you do whenever you
222 are not constructing immediately for a function return or as an argument to a
223 function), you can use a type parameter:
224
225 ```ts
226 const yayNumber = Result.ok<number, string>(12);
227 ```
228
229 Note: passing nothing, or passing `null` or `undefined` explicitly, will
230 produce a `Result<Unit, E>`, rather than producing the nonsensical and in
231 practice quite annoying `Result<null, string>` etc. See {@linkcode Unit} for
232 more.
233
234 ```ts
235 const normalResult = Result.ok<number, string>(42);
236 const explicitUnit = Result.ok<Unit, string>(Unit);
237 const implicitUnit = Result.ok<Unit, string>();
238 ```
239
240 In the context of an immediate function return, or an arrow function with a
241 single expression value, you do not have to specify the types, so this can be
242 quite convenient.
243
244 ```ts
245 type SomeData = {
246 //...
247 };
248
249 const isValid = (data: SomeData): boolean => {
250 // true or false...
251 }
252
253 const arrowValidate = (data: SomeData): Result<Unit, string> =>
254 isValid(data) ? Result.ok() : Result.err('something was wrong!');
255
256 function fnValidate(data: someData): Result<Unit, string> {
257 return isValid(data) ? Result.ok() : Result.err('something was wrong');
258 }
259 ```
260
261 @template T The type of the item contained in the `Result`.
262 @param value The value to wrap in a `Result.Ok`.
263 */
264export declare const ok: typeof ResultImpl.ok;
265/**
266 Is the {@linkcode Result} an {@linkcode Ok}?
267
268 @template T The type of the item contained in the `Result`.
269 @param result The `Result` to check.
270 @returns A type guarded `Ok`.
271 */
272export declare function isOk<T, E>(result: Result<T, E>): result is Ok<T, E>;
273/**
274 Is the {@linkcode Result} an {@linkcode Err}?
275
276 @template T The type of the item contained in the `Result`.
277 @param result The `Result` to check.
278 @returns A type guarded `Err`.
279*/
280export declare function isErr<T, E>(result: Result<T, E>): result is Err<T, E>;
281/**
282 Create an instance of {@linkcode Err}.
283
284 If you need to create an instance with a specific type (as you do whenever you
285 are not constructing immediately for a function return or as an argument to a
286 function), you can use a type parameter:
287
288 ```ts
289 const notString = Result.err<number, string>('something went wrong');
290 ```
291
292 Note: passing nothing, or passing `null` or `undefined` explicitly, will
293 produce a `Result<T, Unit>`, rather than producing the nonsensical and in
294 practice quite annoying `Result<null, string>` etc. See {@linkcode Unit} for
295 more.
296
297 ```ts
298 const normalResult = Result.err<number, string>('oh no');
299 const explicitUnit = Result.err<number, Unit>(Unit);
300 const implicitUnit = Result.err<number, Unit>();
301 ```
302
303 In the context of an immediate function return, or an arrow function with a
304 single expression value, you do not have to specify the types, so this can be
305 quite convenient.
306
307 ```ts
308 type SomeData = {
309 //...
310 };
311
312 const isValid = (data: SomeData): boolean => {
313 // true or false...
314 }
315
316 const arrowValidate = (data: SomeData): Result<number, Unit> =>
317 isValid(data) ? Result.ok(42) : Result.err();
318
319 function fnValidate(data: someData): Result<number, Unit> {
320 return isValid(data) ? Result.ok(42) : Result.err();
321 }
322 ```
323
324 @template T The type of the item contained in the `Result`.
325 @param E The error value to wrap in a `Result.Err`.
326 */
327export declare const err: typeof ResultImpl.err;
328/**
329 Execute the provided callback, wrapping the return value in {@linkcode Ok}.
330 If there is an exception, return a {@linkcode Err} of whatever the `onError`
331 function returns.
332
333 ```ts
334 const aSuccessfulOperation = () => 2 + 2;
335
336 const anOkResult = Result.tryOrElse(
337 (e) => e,
338 aSuccessfulOperation
339 ); // => Ok(4)
340
341 const thisOperationThrows = () => throw 'Bummer'
342
343 const anErrResult = Result.tryOrElse((e) => e, () => {
344 thisOperationThrows();
345 }); // => Err('Bummer')
346 ```
347
348 @param onError A function that takes `e` exception and returns what will
349 be wrapped in a `Result.Err`
350 @param callback The callback to try executing
351 */
352export declare function tryOrElse<T, E>(onError: (e: unknown) => E, callback: () => T): Result<T, E>;
353export declare function tryOrElse<T, E>(onError: (e: unknown) => E): (callback: () => T) => Result<T, E>;
354/**
355 Map over a {@linkcode Result} instance: apply the function to the wrapped
356 value if the instance is {@linkcode Ok}, and return the wrapped error value
357 wrapped as a new {@linkcode Err} of the correct type (`Result<U, E>`) if the
358 instance is `Err`.
359
360 `map` works a lot like `Array.prototype.map`, but with one important
361 difference. Both `Result` and `Array` are containers for other kinds of items,
362 but where `Array.prototype.map` has 0 to _n_ items, a `Result` always has
363 exactly one item, which is *either* a success or an error instance.
364
365 Where `Array.prototype.map` will apply the mapping function to every item in
366 the array (if there are any), `Result.map` will only apply the mapping
367 function to the (single) element if an `Ok` instance, if there is one.
368
369 If you have no items in an array of numbers named `foo` and call `foo.map(x =>
370 x + 1)`, you'll still some have an array with nothing in it. But if you have
371 any items in the array (`[2, 3]`), and you call `foo.map(x => x + 1)` on it,
372 you'll get a new array with each of those items inside the array "container"
373 transformed (`[3, 4]`).
374
375 With this `map`, the `Err` variant is treated *by the `map` function* kind of
376 the same way as the empty array case: it's just ignored, and you get back a
377 new `Result` that is still just the same `Err` instance. But if you have an
378 `Ok` variant, the map function is applied to it, and you get back a new
379 `Result` with the value transformed, and still wrapped in an `Ok`.
380
381 #### Examples
382
383 ```ts
384 import { ok, err, map, toString } from 'true-myth/result';
385 const double = n => n * 2;
386
387 const anOk = ok(12);
388 const mappedOk = map(double, anOk);
389 console.log(toString(mappedOk)); // Ok(24)
390
391 const anErr = err("nothing here!");
392 const mappedErr = map(double, anErr);
393 console.log(toString(mappedOk)); // Err(nothing here!)
394 ```
395
396 @template T The type of the value wrapped in an `Ok` instance, and taken as
397 the argument to the `mapFn`.
398 @template U The type of the value wrapped in the new `Ok` instance after
399 applying `mapFn`, that is, the type returned by `mapFn`.
400 @template E The type of the value wrapped in an `Err` instance.
401 @param mapFn The function to apply the value to if `result` is `Ok`.
402 @param result The `Result` instance to map over.
403 @returns A new `Result` with the result of applying `mapFn` to the value
404 in an `Ok`, or else the original `Err` value wrapped in the new
405 instance.
406 */
407export declare function map<T, U, E>(mapFn: (t: T) => U, result: Result<T, E>): Result<U, E>;
408export declare function map<T, U, E>(mapFn: (t: T) => U): (result: Result<T, E>) => Result<U, E>;
409/**
410 Map over a {@linkcode Result} instance as in [`map`](#map) and get out the
411 value if `result` is an {@linkcode Ok}, or return a default value if `result`
412 is an {@linkcode Err}.
413
414 #### Examples
415
416 ```ts
417 import { ok, err, mapOr } from 'true-myth/result';
418
419 const length = (s: string) => s.length;
420
421 const anOkString = ok('a string');
422 const theStringLength = mapOr(0, anOkString);
423 console.log(theStringLength); // 8
424
425 const anErr = err('uh oh');
426 const anErrMapped = mapOr(0, anErr);
427 console.log(anErrMapped); // 0
428 ```
429
430 @param orU The default value to use if `result` is an `Err`.
431 @param mapFn The function to apply the value to if `result` is an `Ok`.
432 @param result The `Result` instance to map over.
433 */
434export declare function mapOr<T, U, E>(orU: U, mapFn: (t: T) => U, result: Result<T, E>): U;
435export declare function mapOr<T, U, E>(orU: U, mapFn: (t: T) => U): (result: Result<T, E>) => U;
436export declare function mapOr<T, U, E>(orU: U): (mapFn: (t: T) => U) => (result: Result<T, E>) => U;
437/**
438 Map over a {@linkcode Result} instance as in {@linkcode map} and get out the
439 value if `result` is {@linkcode Ok}, or apply a function (`orElseFn`) to the
440 value wrapped in the {@linkcode Err} to get a default value.
441
442 Like {@linkcode mapOr} but using a function to transform the error into a
443 usable value instead of simply using a default value.
444
445 #### Examples
446
447 ```ts
448 import { ok, err, mapOrElse } from 'true-myth/result';
449
450 const summarize = (s: string) => `The response was: '${s}'`;
451 const getReason = (err: { code: number, reason: string }) => err.reason;
452
453 const okResponse = ok("Things are grand here.");
454 const mappedOkAndUnwrapped = mapOrElse(getReason, summarize, okResponse);
455 console.log(mappedOkAndUnwrapped); // The response was: 'Things are grand here.'
456
457 const errResponse = err({ code: 500, reason: 'Nothing at this endpoint!' });
458 const mappedErrAndUnwrapped = mapOrElse(getReason, summarize, errResponse);
459 console.log(mappedErrAndUnwrapped); // Nothing at this endpoint!
460 ```
461
462 @template T The type of the wrapped `Ok` value.
463 @template U The type of the resulting value from applying `mapFn` to the
464 `Ok` value or `orElseFn` to the `Err` value.
465 @template E The type of the wrapped `Err` value.
466 @param orElseFn The function to apply to the wrapped `Err` value to get a
467 usable value if `result` is an `Err`.
468 @param mapFn The function to apply to the wrapped `Ok` value if `result` is
469 an `Ok`.
470 @param result The `Result` instance to map over.
471 */
472export declare function mapOrElse<T, U, E>(orElseFn: (err: E) => U, mapFn: (t: T) => U, result: Result<T, E>): U;
473export declare function mapOrElse<T, U, E>(orElseFn: (err: E) => U, mapFn: (t: T) => U): (result: Result<T, E>) => U;
474export declare function mapOrElse<T, U, E>(orElseFn: (err: E) => U): (mapFn: (t: T) => U) => (result: Result<T, E>) => U;
475/**
476 Map over a {@linkcode Ok}, exactly as in {@linkcode map}, but operating on the
477 value wrapped in an {@linkcode Err} instead of the value wrapped in the
478 {@linkcode Ok}. This is handy for when you need to line up a bunch of
479 different types of errors, or if you need an error of one shape to be in a
480 different shape to use somewhere else in your codebase.
481
482 #### Examples
483
484 ```ts
485 import { ok, err, mapErr, toString } from 'true-myth/result';
486
487 const reason = (err: { code: number, reason: string }) => err.reason;
488
489 const anOk = ok(12);
490 const mappedOk = mapErr(reason, anOk);
491 console.log(toString(mappedOk)); // Ok(12)
492
493 const anErr = err({ code: 101, reason: 'bad file' });
494 const mappedErr = mapErr(reason, anErr);
495 console.log(toString(mappedErr)); // Err(bad file)
496 ```
497
498 @template T The type of the value wrapped in the `Ok` of the `Result`.
499 @template E The type of the value wrapped in the `Err` of the `Result`.
500 @template F The type of the value wrapped in the `Err` of a new `Result`,
501 returned by the `mapErrFn`.
502 @param mapErrFn The function to apply to the value wrapped in `Err` if
503 `result` is an `Err`.
504 @param result The `Result` instance to map over an error case for.
505 */
506export declare function mapErr<T, E, F>(mapErrFn: (e: E) => F, result: Result<T, E>): Result<T, F>;
507export declare function mapErr<T, E, F>(mapErrFn: (e: E) => F): (result: Result<T, E>) => Result<T, F>;
508/**
509 You can think of this like a short-circuiting logical "and" operation on a
510 {@linkcode Result} type. If `result` is {@linkcode Ok}, then the result is the
511 `andResult`. If `result` is {@linkcode Err}, the result is the `Err`.
512
513 This is useful when you have another `Result` value you want to provide if and
514 *only if* you have an `Ok` – that is, when you need to make sure that if you
515 `Err`, whatever else you're handing a `Result` to *also* gets that `Err`.
516
517 Notice that, unlike in [`map`](#map) or its variants, the original `result` is
518 not involved in constructing the new `Result`.
519
520 #### Examples
521
522 ```ts
523 import { and, ok, err, toString } from 'true-myth/result';
524
525 const okA = ok('A');
526 const okB = ok('B');
527 const anErr = err({ so: 'bad' });
528
529 console.log(toString(and(okB, okA))); // Ok(B)
530 console.log(toString(and(okB, anErr))); // Err([object Object])
531 console.log(toString(and(anErr, okA))); // Err([object Object])
532 console.log(toString(and(anErr, anErr))); // Err([object Object])
533 ```
534
535 @template T The type of the value wrapped in the `Ok` of the `Result`.
536 @template U The type of the value wrapped in the `Ok` of the `andResult`,
537 i.e. the success type of the `Result` present if the checked
538 `Result` is `Ok`.
539 @template E The type of the value wrapped in the `Err` of the `Result`.
540 @param andResult The `Result` instance to return if `result` is `Err`.
541 @param result The `Result` instance to check.
542 */
543export declare function and<T, U, E>(andResult: Result<U, E>, result: Result<T, E>): Result<U, E>;
544export declare function and<T, U, E>(andResult: Result<U, E>): (result: Result<T, E>) => Result<U, E>;
545/**
546 Apply a function to the wrapped value if {@linkcode Ok} and return a new `Ok`
547 containing the resulting value; or if it is {@linkcode Err} return it
548 unmodified.
549
550 This differs from `map` in that `thenFn` returns another {@linkcode Result}.
551 You can use `andThen` to combine two functions which *both* create a `Result`
552 from an unwrapped type.
553
554 You may find the `.then` method on an ES6 `Promise` helpful for comparison: if
555 you have a `Promise`, you can pass its `then` method a callback which returns
556 another `Promise`, and the result will not be a *nested* promise, but a single
557 `Promise`. The difference is that `Promise#then` unwraps *all* layers to only
558 ever return a single `Promise` value, whereas `Result.andThen` will not unwrap
559 nested `Result`s.
560
561 This is is sometimes also known as `bind`, but *not* aliased as such because
562 [`bind` already means something in JavaScript][bind].
563
564 [bind]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
565
566 #### Examples
567
568 ```ts
569 import { ok, err, andThen, toString } from 'true-myth/result';
570
571 const toLengthAsResult = (s: string) => ok(s.length);
572
573 const anOk = ok('just a string');
574 const lengthAsResult = andThen(toLengthAsResult, anOk);
575 console.log(toString(lengthAsResult)); // Ok(13)
576
577 const anErr = err(['srsly', 'whatever']);
578 const notLengthAsResult = andThen(toLengthAsResult, anErr);
579 console.log(toString(notLengthAsResult)); // Err(srsly,whatever)
580 ```
581
582 @template T The type of the value wrapped in the `Ok` of the `Result`.
583 @template U The type of the value wrapped in the `Ok` of the `Result`
584 returned by the `thenFn`.
585 @template E The type of the value wrapped in the `Err` of the `Result`.
586 @param thenFn The function to apply to the wrapped `T` if `maybe` is `Just`.
587 @param result The `Maybe` to evaluate and possibly apply a function to.
588 */
589export declare function andThen<T, U, E>(thenFn: (t: T) => Result<U, E>, result: Result<T, E>): Result<U, E>;
590export declare function andThen<T, U, E>(thenFn: (t: T) => Result<U, E>): (result: Result<T, E>) => Result<U, E>;
591/**
592 Provide a fallback for a given {@linkcode Result}. Behaves like a logical
593 `or`: if the `result` value is an {@linkcode Ok}, returns that `result`;
594 otherwise, returns the `defaultResult` value.
595
596 This is useful when you want to make sure that something which takes a
597 `Result` always ends up getting an `Ok` variant, by supplying a default value
598 for the case that you currently have an {@linkcode Err}.
599
600 ```ts
601 import { ok, err, Result, or } from 'true-utils/result';
602
603 const okA = ok<string, string>('a');
604 const okB = ok<string, string>('b');
605 const anErr = err<string, string>(':wat:');
606 const anotherErr = err<string, string>(':headdesk:');
607
608 console.log(or(okB, okA).toString()); // Ok(A)
609 console.log(or(anErr, okA).toString()); // Ok(A)
610 console.log(or(okB, anErr).toString()); // Ok(B)
611 console.log(or(anotherErr, anErr).toString()); // Err(:headdesk:)
612 ```
613
614 @template T The type wrapped in the `Ok` case of `result`.
615 @template E The type wrapped in the `Err` case of `result`.
616 @template F The type wrapped in the `Err` case of `defaultResult`.
617 @param defaultResult The `Result` to use if `result` is an `Err`.
618 @param result The `Result` instance to check.
619 @returns `result` if it is an `Ok`, otherwise `defaultResult`.
620 */
621export declare function or<T, E, F>(defaultResult: Result<T, F>, result: Result<T, E>): Result<T, F>;
622export declare function or<T, E, F>(defaultResult: Result<T, F>): (result: Result<T, E>) => Result<T, F>;
623/**
624 Like {@linkcode or}, but using a function to construct the alternative
625 {@linkcode Result}.
626
627 Sometimes you need to perform an operation using other data in the environment
628 to construct the fallback value. In these situations, you can pass a function
629 (which may be a closure) as the `elseFn` to generate the fallback `Result<T>`.
630 It can then transform the data in the `Err` to something usable as an
631 {@linkcode Ok}, or generate a new {@linkcode Err} instance as appropriate.
632
633 Useful for transforming failures to usable data.
634
635 @param elseFn The function to apply to the contents of the `Err` if `result`
636 is an `Err`, to create a new `Result`.
637 @param result The `Result` to use if it is an `Ok`.
638 @returns The `result` if it is `Ok`, or the `Result` returned by `elseFn`
639 if `result` is an `Err.
640 */
641export declare function orElse<T, E, F>(elseFn: (err: E) => Result<T, F>, result: Result<T, E>): Result<T, F>;
642export declare function orElse<T, E, F>(elseFn: (err: E) => Result<T, F>): (result: Result<T, E>) => Result<T, F>;
643/**
644 Safely get the value out of the {@linkcode Ok} variant of a {@linkcode Result}.
645
646 This is the recommended way to get a value out of a `Result` most of the time.
647
648 ```ts
649 import { ok, err, unwrapOr } from 'true-myth/result';
650
651 const anOk = ok<number, string>(12);
652 console.log(unwrapOr(0, anOk)); // 12
653
654 const anErr = err<number, string>('nooooo');
655 console.log(unwrapOr(0, anErr)); // 0
656 ```
657
658 @template T The value wrapped in the `Ok`.
659 @template E The value wrapped in the `Err`.
660 @param defaultValue The value to use if `result` is an `Err`.
661 @param result The `Result` instance to unwrap if it is an `Ok`.
662 @returns The content of `result` if it is an `Ok`, otherwise
663 `defaultValue`.
664 */
665export declare function unwrapOr<T, U, E>(defaultValue: U, result: Result<T, E>): U | T;
666export declare function unwrapOr<T, U, E>(defaultValue: U): (result: Result<T, E>) => U | T;
667/**
668 Safely get the value out of a {@linkcode Result} by returning the wrapped
669 value if it is {@linkcode Ok}, or by applying `orElseFn` to the value in the
670 {@linkcode Err}.
671
672 This is useful when you need to *generate* a value (e.g. by using current
673 values in the environment – whether preloaded or by local closure) instead of
674 having a single default value available (as in {@linkcode unwrapOr}).
675
676 ```ts
677 import { ok, err, unwrapOrElse } from 'true-myth/result';
678
679 // You can imagine that someOtherValue might be dynamic.
680 const someOtherValue = 2;
681 const handleErr = (errValue: string) => errValue.length + someOtherValue;
682
683 const anOk = ok<number, string>(42);
684 console.log(unwrapOrElse(handleErr, anOk)); // 42
685
686 const anErr = err<number, string>('oh teh noes');
687 console.log(unwrapOrElse(handleErr, anErr)); // 13
688 ```
689
690 @template T The value wrapped in the `Ok`.
691 @template E The value wrapped in the `Err`.
692 @param orElseFn A function applied to the value wrapped in `result` if it is
693 an `Err`, to generate the final value.
694 @param result The `result` to unwrap if it is an `Ok`.
695 @returns The value wrapped in `result` if it is `Ok` or the value
696 returned by `orElseFn` applied to the value in `Err`.
697 */
698export declare function unwrapOrElse<T, U, E>(orElseFn: (error: E) => U, result: Result<T, E>): T | U;
699export declare function unwrapOrElse<T, U, E>(orElseFn: (error: E) => U): (result: Result<T, E>) => T | U;
700/**
701 Create a `String` representation of a {@linkcode Result} instance.
702
703 An {@linkcode Ok} instance will be `Ok(<representation of the value>)`, and an
704 {@linkcode Err} instance will be `Err(<representation of the error>)`, where
705 the representation of the value or error is simply the value or error's own
706 `toString` representation. For example:
707
708 call | output
709 --------------------------------- | ----------------------
710 `toString(ok(42))` | `Ok(42)`
711 `toString(ok([1, 2, 3]))` | `Ok(1,2,3)`
712 `toString(ok({ an: 'object' }))` | `Ok([object Object])`n
713 `toString(err(42))` | `Err(42)`
714 `toString(err([1, 2, 3]))` | `Err(1,2,3)`
715 `toString(err({ an: 'object' }))` | `Err([object Object])`
716
717 @template T The type of the wrapped value; its own `.toString` will be used
718 to print the interior contents of the `Just` variant.
719 @param result The value to convert to a string.
720 @returns The string representation of the `Maybe`.
721 */
722export declare const toString: <T, E>(result: Result<T, E>) => string;
723/**
724 * Create an `Object` representation of a {@linkcode Result} instance.
725 *
726 * Useful for serialization. `JSON.stringify()` uses it.
727 *
728 * @param result The value to convert to JSON
729 * @returns The JSON representation of the `Result`
730 */
731export declare const toJSON: <T, E>(result: Result<T, E>) => ResultJSON<T, E>;
732/**
733 A lightweight object defining how to handle each variant of a
734 {@linkcode Result}.
735 */
736export type Matcher<T, E, A> = {
737 Ok: (value: T) => A;
738 Err: (error: E) => A;
739};
740/**
741 Performs the same basic functionality as {@linkcode unwrapOrElse}, but instead
742 of simply unwrapping the value if it is {@linkcode Ok} and applying a value to
743 generate the same default type if it is {@linkcode Err}, lets you supply
744 functions which may transform the wrapped type if it is `Ok` or get a default
745 value for `Err`.
746
747 This is kind of like a poor man's version of pattern matching, which
748 JavaScript currently lacks.
749
750 Instead of code like this:
751
752 ```ts
753 import Result, { isOk, match } from 'true-myth/result';
754
755 const logValue = (mightBeANumber: Result<number, string>) => {
756 console.log(
757 mightBeANumber.isOk
758 ? mightBeANumber.value.toString()
759 : `There was an error: ${unsafelyGetErr(mightBeANumber)}`
760 );
761 };
762 ```
763
764 ...we can write code like this:
765
766 ```ts
767 import Result, { match } from 'true-myth/result';
768
769 const logValue = (mightBeANumber: Result<number, string>) => {
770 const value = match(
771 {
772 Ok: n => n.toString(),
773 Err: e => `There was an error: ${e}`,
774 },
775 mightBeANumber
776 );
777 console.log(value);
778 };
779 ```
780
781 This is slightly longer to write, but clearer: the more complex the resulting
782 expression, the hairer it is to understand the ternary. Thus, this is
783 especially convenient for times when there is a complex result, e.g. when
784 rendering part of a React component inline in JSX/TSX.
785
786 @param matcher A lightweight object defining what to do in the case of each
787 variant.
788 @param result The `result` instance to check.
789 */
790export declare function match<T, E, A>(matcher: Matcher<T, E, A>, result: Result<T, E>): A;
791/**
792 Performs the same basic functionality as {@linkcode unwrapOrElse}, but instead
793 of simply unwrapping the value if it is {@linkcode Ok} and applying a value to
794 generate the same default type if it is {@linkcode Err}, lets you supply
795 functions which may transform the wrapped type if it is `Ok` or get a default
796 value for `Err`.
797
798 This is kind of like a poor man's version of pattern matching, which
799 JavaScript currently lacks.
800
801 Instead of code like this:
802
803 ```ts
804 import Result, { isOk, match } from 'true-myth/result';
805
806 const logValue = (mightBeANumber: Result<number, string>) => {
807 console.log(
808 mightBeANumber.isOk
809 ? mightBeANumber.value.toString()
810 : `There was an error: ${unsafelyGetErr(mightBeANumber)}`
811 );
812 };
813 ```
814
815 ...we can write code like this:
816
817 ```ts
818 import Result, { match } from 'true-myth/result';
819
820 const logValue = (mightBeANumber: Result<number, string>) => {
821 const value = match(
822 {
823 Ok: n => n.toString(),
824 Err: e => `There was an error: ${e}`,
825 },
826 mightBeANumber
827 );
828 console.log(value);
829 };
830 ```
831
832 This is slightly longer to write, but clearer: the more complex the resulting
833 expression, the hairer it is to understand the ternary. Thus, this is
834 especially convenient for times when there is a complex result, e.g. when
835 rendering part of a React component inline in JSX/TSX.
836
837 @param matcher A lightweight object defining what to do in the case of each
838 variant.
839 */
840export declare function match<T, E, A>(matcher: Matcher<T, E, A>): (result: Result<T, E>) => A;
841/**
842 Allows quick triple-equal equality check between the values inside two
843 {@linkcode Result}s without having to unwrap them first.
844
845 ```ts
846 const a = Result.of(3)
847 const b = Result.of(3)
848 const c = Result.of(null)
849 const d = Result.nothing()
850
851 Result.equals(a, b) // true
852 Result.equals(a, c) // false
853 Result.equals(c, d) // true
854 ```
855
856 @param resultB A `maybe` to compare to.
857 @param resultA A `maybe` instance to check.
858 */
859export declare function equals<T, E>(resultB: Result<T, E>, resultA: Result<T, E>): boolean;
860export declare function equals<T, E>(resultB: Result<T, E>): (resultA: Result<T, E>) => boolean;
861/**
862 Allows you to *apply* (thus `ap`) a value to a function without having to take
863 either out of the context of their {@linkcode Result}s. This does mean that
864 the transforming function is itself within a `Result`, which can be hard to
865 grok at first but lets you do some very elegant things. For example, `ap`
866 allows you to do this (using the method form, since nesting `ap` calls is
867 awkward):
868
869 ```ts
870 import { ap, ok, err } from 'true-myth/result';
871
872 const one = ok<number, string>(1);
873 const five = ok<number, string>(5);
874 const whoops = err<number, string>('oh no');
875
876 const add = (a: number) => (b: number) => a + b;
877 const resultAdd = ok<typeof add, string>(add);
878
879 resultAdd.ap(one).ap(five); // Ok(6)
880 resultAdd.ap(one).ap(whoops); // Err('oh no')
881 resultAdd.ap(whoops).ap(five) // Err('oh no')
882 ```
883
884 Without `ap`, you'd need to do something like a nested `match`:
885
886 ```ts
887 import { ok, err } from 'true-myth/result';
888
889 const one = ok<number, string>(1);
890 const five = ok<number, string>(5);
891 const whoops = err<number, string>('oh no');
892
893 one.match({
894 Ok: n => five.match({
895 Ok: o => ok<number, string>(n + o),
896 Err: e => err<number, string>(e),
897 }),
898 Err: e => err<number, string>(e),
899 }); // Ok(6)
900
901 one.match({
902 Ok: n => whoops.match({
903 Ok: o => ok<number, string>(n + o),
904 Err: e => err<number, string>(e),
905 }),
906 Err: e => err<number, string>(e),
907 }); // Err('oh no')
908
909 whoops.match({
910 Ok: n => five.match({
911 Ok: o => ok(n + o),
912 Err: e => err(e),
913 }),
914 Err: e => err(e),
915 }); // Err('oh no')
916 ```
917
918 And this kind of thing comes up quite often once you're using `Result` to
919 handle errors throughout your application.
920
921 For another example, imagine you need to compare the equality of two
922 ImmutableJS data structures, where a `===` comparison won't work. With `ap`,
923 that's as simple as this:
924
925 ```ts
926 import { ok } from 'true-myth/result';
927 import { is as immutableIs, Set } from 'immutable';
928
929 const is = (first: unknown) => (second: unknown) =>
930 immutableIs(first, second);
931
932 const x = ok(Set.of(1, 2, 3));
933 const y = ok(Set.of(2, 3, 4));
934
935 ok(is).ap(x).ap(y); // Ok(false)
936 ```
937
938 Without `ap`, we're back to that gnarly nested `match`:
939
940 ```ts
941 import Result, { ok, err } from 'true-myth/result';
942 import { is, Set } from 'immutable';
943
944 const x = ok(Set.of(1, 2, 3));
945 const y = ok(Set.of(2, 3, 4));
946
947 x.match({
948 Ok: iX => y.match({
949 Ok: iY => Result.of(is(iX, iY)),
950 Err: (e) => ok(false),
951 })
952 Err: (e) => ok(false),
953 }); // Ok(false)
954 ```
955
956 In summary: anywhere you have two `Result` instances and need to perform an
957 operation that uses both of them, `ap` is your friend.
958
959 Two things to note, both regarding *currying*:
960
961 1. All functions passed to `ap` must be curried. That is, they must be of the
962 form (for add) `(a: number) => (b: number) => a + b`, *not* the more usual
963 `(a: number, b: number) => a + b` you see in JavaScript more generally.
964
965 (Unfortunately, these do not currently work with lodash or Ramda's `curry`
966 helper functions. A future update to the type definitions may make that
967 work, but the intermediate types produced by those helpers and the more
968 general function types expected by this function do not currently align.)
969
970 2. You will need to call `ap` as many times as there are arguments to the
971 function you're dealing with. So in the case of this `add3` function,
972 which has the "arity" (function argument count) of 3 (`a` and `b`), you'll
973 need to call `ap` twice: once for `a`, and once for `b`. To see why, let's
974 look at what the result in each phase is:
975
976 ```ts
977 const add3 = (a: number) => (b: number) => (c: number) => a + b + c;
978
979 const resultAdd = ok(add); // Ok((a: number) => (b: number) => (c: number) => a + b + c)
980 const resultAdd1 = resultAdd.ap(ok(1)); // Ok((b: number) => (c: number) => 1 + b + c)
981 const resultAdd1And2 = resultAdd1.ap(ok(2)) // Ok((c: number) => 1 + 2 + c)
982 const final = maybeAdd1.ap(ok(3)); // Ok(4)
983 ```
984
985 So for `toString`, which just takes a single argument, you would only need
986 to call `ap` once.
987
988 ```ts
989 const toStr = (v: { toString(): string }) => v.toString();
990 ok(toStr).ap(12); // Ok("12")
991 ```
992
993 One other scenario which doesn't come up *quite* as often but is conceivable
994 is where you have something that may or may not actually construct a function
995 for handling a specific `Result` scenario. In that case, you can wrap the
996 possibly-present in `ap` and then wrap the values to apply to the function to
997 in `Result` themselves.
998
999 Because `Result` often requires you to type out the full type parameterization
1000 on a regular basis, it's convenient to use TypeScript's `typeof` operator to
1001 write out the type of a curried function. For example, if you had a function
1002 that simply merged three strings, you might write it like this:
1003
1004 ```ts
1005 import Result from 'true-myth/result';
1006 import { curry } from 'lodash';
1007
1008 const merge3Strs = (a: string, b: string, c: string) => string;
1009 const curriedMerge = curry(merge3Strs);
1010
1011 const fn = Result.ok<typeof curriedMerge, string>(curriedMerge);
1012 ```
1013
1014 The alternative is writing out the full signature long-form:
1015
1016 ```ts
1017 const fn = Result.ok<(a: string) => (b: string) => (c: string) => string, string>(curriedMerge);
1018 ```
1019
1020 **Aside:** `ap` is not named `apply` because of the overlap with JavaScript's
1021 existing [`apply`] function – and although strictly speaking, there isn't any
1022 direct overlap (`Result.apply` and `Function.prototype.apply` don't intersect
1023 at all) it's useful to have a different name to avoid implying that they're
1024 the same.
1025
1026 [`apply`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
1027
1028 @param resultFn result of a function from T to U
1029 @param result result of a T to apply to `fn`
1030 */
1031export declare function ap<A, B, E>(resultFn: Result<(a: A) => B, E>, result: Result<A, E>): Result<B, E>;
1032export declare function ap<A, B, E>(resultFn: Result<(a: A) => B, E>): (result: Result<A, E>) => Result<B, E>;
1033/**
1034 Determine whether an item is an instance of {@linkcode Result}.
1035
1036 @param item The item to check.
1037 */
1038export declare function isInstance<T, E>(item: unknown): item is Result<T, E>;
1039export interface ResultConstructor {
1040 ok: typeof ResultImpl.ok;
1041 err: typeof ResultImpl.err;
1042}
1043/**
1044 A value which may ({@linkcode Ok}) or may not ({@linkcode Err}) be present.
1045
1046 The behavior of this type is checked by TypeScript at compile time, and bears
1047 no runtime overhead other than the very small cost of the container object.
1048 */
1049export type Result<T, E> = Ok<T, E> | Err<T, E>;
1050export declare const Result: ResultConstructor;
1051export default Result;
1052//# sourceMappingURL=result.d.ts.map
\No newline at end of file