1213 lines
50 KiB
TypeScript
1213 lines
50 KiB
TypeScript
|
/** [[include:doc/result.md]] */
|
|||
|
/** (keep typedoc from getting confused by the import) */
|
|||
|
import * as Maybe from './maybe';
|
|||
|
declare type Maybe<T> = import('./maybe').Maybe<T>;
|
|||
|
import Unit from './unit';
|
|||
|
/**
|
|||
|
Discriminant for `Ok` and `Err` variants of `Result` type.
|
|||
|
|
|||
|
You can use the discriminant via the `variant` property of `Result` instances
|
|||
|
if you need to match explicitly on it.
|
|||
|
*/
|
|||
|
export declare enum Variant {
|
|||
|
Ok = "Ok",
|
|||
|
Err = "Err"
|
|||
|
}
|
|||
|
interface OkJSON<T> {
|
|||
|
variant: Variant.Ok;
|
|||
|
value: T;
|
|||
|
}
|
|||
|
interface ErrJSON<E> {
|
|||
|
variant: Variant.Err;
|
|||
|
error: E;
|
|||
|
}
|
|||
|
declare type ResultJSON<T, E> = OkJSON<T> | ErrJSON<E>;
|
|||
|
/** Simply defines the common shape for `Ok` and `Err`. */
|
|||
|
export interface ResultShape<T, E> {
|
|||
|
/** Distinguish between the `Ok` and `Err` variants. */
|
|||
|
readonly variant: Variant;
|
|||
|
/** Method variant for [`Result.isOk`](../modules/_result_.html#isok) */
|
|||
|
isOk(this: Result<T, E>): this is Ok<T, E>;
|
|||
|
/** Method variant for [`Result.isErr`](../modules/_result_.html#iserr) */
|
|||
|
isErr(this: Result<T, E>): this is Err<T, E>;
|
|||
|
/** Method variant for [`Result.map`](../modules/_result_.html#map) */
|
|||
|
map<U>(this: Result<T, E>, mapFn: (t: T) => U): Result<U, E>;
|
|||
|
/** Method variant for [`Result.mapOr`](../modules/_result_.html#mapor) */
|
|||
|
mapOr<U>(this: Result<T, E>, orU: U, mapFn: (t: T) => U): U;
|
|||
|
/** Method variant for [`Result.mapOrElse`](../modules/_result_.html#maporelse) */
|
|||
|
mapOrElse<U>(this: Result<T, E>, orElseFn: (err: E) => U, mapFn: (t: T) => U): U;
|
|||
|
/** Method variant for [`Result.match`](../modules/_result_.html#match) */
|
|||
|
match<U>(this: Result<T, E>, matcher: Matcher<T, E, U>): U;
|
|||
|
/** Method variant for [`Result.mapErr`](../modules/_result_.html#maperr) */
|
|||
|
mapErr<F>(this: Result<T, E>, mapErrFn: (e: E) => F): Result<T, F>;
|
|||
|
/** Method variant for [`Result.or`](../modules/_result_.html#or) */
|
|||
|
or<F>(this: Result<T, E>, orResult: Result<T, F>): Result<T, F>;
|
|||
|
/** Method variant for [`Result.orElse`](../modules/_result_.html#orelse) */
|
|||
|
orElse<F>(this: Result<T, E>, orElseFn: (err: E) => Result<T, F>): Result<T, F>;
|
|||
|
/** Method variant for [`Result.and`](../modules/_result_.html#and) */
|
|||
|
and<U>(this: Result<T, E>, mAnd: Result<U, E>): Result<U, E>;
|
|||
|
/** Method variant for [`Result.andThen`](../modules/_result_.html#andthen) */
|
|||
|
andThen<U>(this: Result<T, E>, andThenFn: (t: T) => Result<U, E>): Result<U, E>;
|
|||
|
/** Method variant for [`Result.chain`](../modules/_result_.html#chain) */
|
|||
|
chain<U>(this: Result<T, E>, chainFn: (t: T) => Result<U, E>): Result<U, E>;
|
|||
|
/** Method variant for [`Result.flatMap`](../modules/_result_.html#flatmap) */
|
|||
|
flatMap<U>(this: Result<T, E>, chainFn: (t: T) => Result<U, E>): Result<U, E>;
|
|||
|
/** Method variant for [`Result.unwrap`](../modules/_result_.html#unwrap) */
|
|||
|
unsafelyUnwrap(): T | never;
|
|||
|
/** Method variant for [`Result.unwrapErr`](../modules/_result_.html#unwraperr) */
|
|||
|
unsafelyUnwrapErr(): E | never;
|
|||
|
/** Method variant for [`Result.unwrapOr`](../modules/_result_.html#unwrapor) */
|
|||
|
unwrapOr<U>(this: Result<T, E>, defaultValue: U): T | U;
|
|||
|
/** Method variant for [`Result.unwrapOrElse`](../modules/_result_.html#unwrapOrElse) */
|
|||
|
unwrapOrElse<U>(this: Result<T, E>, elseFn: (error: E) => U): T | U;
|
|||
|
/** Method variant for [`Result.toMaybe`](../modules/_result_.html#tomaybe) */
|
|||
|
toMaybe(this: Result<T, E>): Maybe<T>;
|
|||
|
/** Method variant for [`Result.toString`](../modules/_result_.html#tostring) */
|
|||
|
toString(this: Result<T, E>): string;
|
|||
|
/** Method variant for [`Result.toJSON`](../modules/_result_.html#toJSON) */
|
|||
|
toJSON(this: Result<T, E>): ResultJSON<T, E>;
|
|||
|
/** Method variant for [`Result.equals`](../modules/_result_.html#equals) */
|
|||
|
equals(this: Result<T, E>, comparison: Result<T, E>): boolean;
|
|||
|
/** Method variant for [`Result.ap`](../modules/_result_.html#ap) */
|
|||
|
ap<A, B>(this: Result<(a: A) => B, E>, r: Result<A, E>): Result<B, E>;
|
|||
|
}
|
|||
|
/**
|
|||
|
An `Ok` instance is the *successful* variant instance of the
|
|||
|
[`Result`](../modules/_result_.html#result) type, representing a successful
|
|||
|
outcome from an operation which may fail. For a full discussion, see [the
|
|||
|
module docs](../modules/_result_.html).
|
|||
|
|
|||
|
@typeparam T The type wrapped in this `Ok` variant of `Result`.
|
|||
|
@typeparam E The type which would be wrapped in an `Err` variant of `Result`.
|
|||
|
*/
|
|||
|
export declare class Ok<T, E> implements ResultShape<T, E> {
|
|||
|
/**
|
|||
|
Unwrap the contained value. A convenience method for functional idioms.
|
|||
|
|
|||
|
A common scenario where you might want to use this is in a pipeline of
|
|||
|
functions:
|
|||
|
|
|||
|
```ts
|
|||
|
import Result, { Ok } from 'true-myth/result';
|
|||
|
|
|||
|
function getLengths(results: Array<Result<string, string>>): Array<number> {
|
|||
|
return results
|
|||
|
.filter(Result.isOk)
|
|||
|
.map(Ok.unwrap)
|
|||
|
.map(s => s.length);
|
|||
|
}
|
|||
|
```
|
|||
|
*/
|
|||
|
static unwrap<O>(theOk: Ok<O, any>): O;
|
|||
|
/** `Ok` is always [`Variant.Ok`](../enums/_result_.variant#ok). */
|
|||
|
readonly variant: Variant.Ok;
|
|||
|
/** The wrapped value. */
|
|||
|
readonly value: T;
|
|||
|
/**
|
|||
|
Create an instance of `Result.Ok` with `new`.
|
|||
|
|
|||
|
Note: While you *may* create the `Result` type via normal
|
|||
|
JavaScript class construction, it is not recommended for the functional
|
|||
|
style for which the library is intended. Instead, use [`Result.ok`].
|
|||
|
|
|||
|
[`Result.ok`]: ../modules/_result_.html#ok
|
|||
|
|
|||
|
```ts
|
|||
|
// Avoid:
|
|||
|
const aString = new Result.Ok('characters');
|
|||
|
|
|||
|
// Prefer:
|
|||
|
const aString = Result.ok('characters);
|
|||
|
```
|
|||
|
|
|||
|
Note that you may explicitly pass `Unit` to the `Ok` constructor to create
|
|||
|
a `Result<Unit, E>`. However, you may *not* call the `Ok` constructor with
|
|||
|
`null` or `undefined` to get that result (the type system won't allow you to
|
|||
|
construct it that way). Instead, for convenience, you can simply call
|
|||
|
`Result.ok()`, which will construct the type correctly.
|
|||
|
|
|||
|
@param value
|
|||
|
The value to wrap in a `Result.Ok`.
|
|||
|
|
|||
|
Note: `null` and `undefined` are allowed by the type signature so that the
|
|||
|
constructor may `throw` on those rather than constructing a type like
|
|||
|
`Result<undefined>`.
|
|||
|
|
|||
|
@throws If you pass `null`.
|
|||
|
*/
|
|||
|
constructor(value?: T | null);
|
|||
|
/** Method variant for [`Result.isOk`](../modules/_result_.html#isok) */
|
|||
|
isOk(this: Result<T, E>): this is Ok<T, E>;
|
|||
|
/** Method variant for [`Result.isErr`](../modules/_result_.html#iserr) */
|
|||
|
isErr(this: Result<T, E>): this is Err<T, E>;
|
|||
|
/** Method variant for [`Result.map`](../modules/_result_.html#map) */
|
|||
|
map<U>(this: Result<T, E>, mapFn: (t: T) => U): Result<U, E>;
|
|||
|
/** Method variant for [`Result.mapOr`](../modules/_result_.html#mapor) */
|
|||
|
mapOr<U>(this: Result<T, E>, orU: U, mapFn: (t: T) => U): U;
|
|||
|
/** Method variant for [`Result.mapOrElse`](../modules/_result_.html#maporelse) */
|
|||
|
mapOrElse<U>(this: Result<T, E>, orElseFn: (err: E) => U, mapFn: (t: T) => U): U;
|
|||
|
/** Method variant for [`Result.match`](../modules/_result_.html#match) */
|
|||
|
match<U>(this: Result<T, E>, matcher: Matcher<T, E, U>): U;
|
|||
|
/** Method variant for [`Result.mapErr`](../modules/_result_.html#maperr) */
|
|||
|
mapErr<F>(this: Result<T, E>, mapErrFn: (e: E) => F): Result<T, F>;
|
|||
|
/** Method variant for [`Result.or`](../modules/_result_.html#or) */
|
|||
|
or<F>(this: Result<T, E>, orResult: Result<T, F>): Result<T, F>;
|
|||
|
/** Method variant for [`Result.orElse`](../modules/_result_.html#orelse) */
|
|||
|
orElse<F>(this: Result<T, E>, orElseFn: (err: E) => Result<T, F>): Result<T, F>;
|
|||
|
/** Method variant for [`Result.and`](../modules/_result_.html#and) */
|
|||
|
and<U>(this: Result<T, E>, mAnd: Result<U, E>): Result<U, E>;
|
|||
|
/** Method variant for [`Result.andThen`](../modules/_result_.html#andthen) */
|
|||
|
andThen<U>(this: Result<T, E>, andThenFn: (t: T) => Result<U, E>): Result<U, E>;
|
|||
|
/** Method variant for [`Result.chain`](../modules/_result_.html#chain) */
|
|||
|
chain<U>(this: Result<T, E>, chainFn: (t: T) => Result<U, E>): Result<U, E>;
|
|||
|
/** Method variant for [`Result.flatMap`](../modules/_result_.html#flatmap) */
|
|||
|
flatMap<U>(this: Result<T, E>, flatMapFn: (t: T) => Result<U, E>): Result<U, E>;
|
|||
|
/** Method variant for [`Result.unwrap`](../modules/_result_.html#unwrap) */
|
|||
|
unsafelyUnwrap(): T;
|
|||
|
/** Method variant for [`Result.unwrapErr`](../modules/_result_.html#unwraperr) */
|
|||
|
unsafelyUnwrapErr(): never;
|
|||
|
/** Method variant for [`Result.unwrapOr`](../modules/_result_.html#unwrapor) */
|
|||
|
unwrapOr<U>(this: Result<T, E>, defaultValue: U): T | U;
|
|||
|
/** Method variant for [`Result.unwrapOrElse`](../modules/_result_.html#unwrapOrElse) */
|
|||
|
unwrapOrElse<U>(this: Result<T, E>, elseFn: (error: E) => U): T | U;
|
|||
|
/** Method variant for [`Result.toMaybe`](../modules/_result_.html#tomaybe) */
|
|||
|
toMaybe(this: Result<T, E>): Maybe<T>;
|
|||
|
/** Method variant for [`Result.toString`](../modules/_result_.html#tostring) */
|
|||
|
toString(this: Result<T, E>): string;
|
|||
|
/** Method variant for [`Result.toJSON`](../modules/_result_.html#toJSON) */
|
|||
|
toJSON(this: Result<T, E>): ResultJSON<T, E>;
|
|||
|
/** Method variant for [`Result.equals`](../modules/_result_.html#equals) */
|
|||
|
equals(this: Result<T, E>, comparison: Result<T, E>): boolean;
|
|||
|
/** Method variant for [`Result.ap`](../modules/_result_.html#ap) */
|
|||
|
ap<A, B>(this: Result<(a: A) => B, E>, r: Result<A, E>): Result<B, E>;
|
|||
|
}
|
|||
|
/**
|
|||
|
An `Err` instance is the *failure* variant instance of the
|
|||
|
[`Result`](../modules/_result_.html#result) type, representing a failure
|
|||
|
outcome from an operation which may fail. For a full discussion, see [the
|
|||
|
module docs](../modules/_result_.html).
|
|||
|
|
|||
|
@typeparam T The type which would be wrapped in an `Ok` variant of `Result`.
|
|||
|
@typeparam E The type wrapped in this `Err` variant of `Result`.
|
|||
|
*/
|
|||
|
export declare class Err<T, E> implements ResultShape<T, E> {
|
|||
|
/**
|
|||
|
Unwrap the contained error . A convenience method for functional idioms.
|
|||
|
|
|||
|
A common scenario where you might want to use this is in a pipeline of
|
|||
|
functions:
|
|||
|
|
|||
|
```ts
|
|||
|
import Result, { Ok } from 'true-myth/result';
|
|||
|
|
|||
|
function getMessages(results: Array<Result<string, Error>>): Array<number> {
|
|||
|
return maybeStrings
|
|||
|
.filter(Result.isErr)
|
|||
|
.map(Err.unwrapErr)
|
|||
|
.map(e => e.message);
|
|||
|
}
|
|||
|
```
|
|||
|
*/
|
|||
|
static unwrapErr<F>(theErr: Err<F, any>): F;
|
|||
|
/** `Err` is always [`Variant.Err`](../enums/_result_.variant#err). */
|
|||
|
readonly variant: Variant.Err;
|
|||
|
/** The wrapped error value. */
|
|||
|
readonly error: E;
|
|||
|
/**
|
|||
|
Create an instance of `Result.Err` with `new`.
|
|||
|
|
|||
|
Note: While you *may* create the `Result` type via normal
|
|||
|
JavaScript class construction, it is not recommended for the functional
|
|||
|
style for which the library is intended. Instead, use [`Result.err`].
|
|||
|
|
|||
|
[`Result.err`]: ../modules/_result_.html#err
|
|||
|
|
|||
|
```ts
|
|||
|
// Avoid:
|
|||
|
const anErr = new Result.Err('alas, failure');
|
|||
|
|
|||
|
// Prefer:
|
|||
|
const anErr = Result.err('alas, failure');
|
|||
|
```
|
|||
|
|
|||
|
Note that you may explicitly pass `Unit` to the `Err` constructor to create
|
|||
|
a `Result<T, Unit>`. However, you may *not* call the `Err` constructor with
|
|||
|
`null` or `undefined` to get that result (the type system won't allow you to
|
|||
|
construct it that way). Instead, for convenience, you can simply call
|
|||
|
`Result.err()`, which will construct the type correctly.
|
|||
|
|
|||
|
@param error
|
|||
|
The value to wrap in a `Result.Err`.
|
|||
|
|
|||
|
`Note: null` and `undefined` are allowed by the type signature so that the
|
|||
|
constructor may `throw` on those rather than constructing a type like
|
|||
|
`Result<number, undefined>`.
|
|||
|
|
|||
|
@throws If you pass `null` or `undefined`.
|
|||
|
*/
|
|||
|
constructor(error: E | null);
|
|||
|
/** Method variant for [`Result.isOk`](../modules/_result_.html#isok) */
|
|||
|
isOk(this: Result<T, E>): this is Ok<T, E>;
|
|||
|
/** Method variant for [`Result.isErr`](../modules/_result_.html#iserr) */
|
|||
|
isErr(this: Result<T, E>): this is Err<T, E>;
|
|||
|
/** Method variant for [`Result.map`](../modules/_result_.html#map) */
|
|||
|
map<U>(this: Result<T, E>, mapFn: (t: T) => U): Result<U, E>;
|
|||
|
/** Method variant for [`Result.mapOr`](../modules/_result_.html#mapor) */
|
|||
|
mapOr<U>(this: Result<T, E>, orU: U, mapFn: (t: T) => U): U;
|
|||
|
/** Method variant for [`Result.mapOrElse`](../modules/_result_.html#maporelse) */
|
|||
|
mapOrElse<U>(this: Result<T, E>, orElseFn: (err: E) => U, mapFn: (t: T) => U): U;
|
|||
|
/** Method variant for [`Result.match`](../modules/_result_.html#match) */
|
|||
|
match<U>(this: Result<T, E>, matchObj: Matcher<T, E, U>): U;
|
|||
|
/** Method variant for [`Result.mapErr`](../modules/_result_.html#maperr) */
|
|||
|
mapErr<F>(this: Result<T, E>, mapErrFn: (e: E) => F): Result<T, F>;
|
|||
|
/** Method variant for [`Result.or`](../modules/_result_.html#or) */
|
|||
|
or<F>(this: Result<T, E>, orResult: Result<T, F>): Result<T, F>;
|
|||
|
/** Method variant for [`Result.orElse`](../modules/_result_.html#orelse) */
|
|||
|
orElse<F>(this: Result<T, E>, orElseFn: (err: E) => Result<T, F>): Result<T, F>;
|
|||
|
/** Method variant for [`Result.and`](../modules/_result_.html#and) */
|
|||
|
and<U>(this: Result<T, E>, mAnd: Result<U, E>): Result<U, E>;
|
|||
|
/** Method variant for [`Result.andThen`](../modules/_result_.html#andthen) */
|
|||
|
andThen<U>(this: Result<T, E>, andThenFn: (t: T) => Result<U, E>): Result<U, E>;
|
|||
|
/** Method variant for [`Result.chain`](../modules/_result_.html#chain) */
|
|||
|
chain<U>(this: Result<T, E>, chainFn: (t: T) => Result<U, E>): Result<U, E>;
|
|||
|
/** Method variant for [`Result.flatMap`](../modules/_result_.html#flatmap) */
|
|||
|
flatMap<U>(this: Result<T, E>, flatMapFn: (t: T) => Result<U, E>): Result<U, E>;
|
|||
|
/** Method variant for [`Result.unsafelyUnwrap`](../modules/_result_.html#unsafelyunwrap) */
|
|||
|
unsafelyUnwrap(): never;
|
|||
|
/** Method variant for [`Result.unsafelyUnwrapErr`](../modules/_result_.html#unsafelyunwraperr) */
|
|||
|
unsafelyUnwrapErr(): E;
|
|||
|
/** Method variant for [`Result.unwrapOr`](../modules/_result_.html#unwrapor) */
|
|||
|
unwrapOr<U>(this: Result<T, E>, defaultValue: U): T | U;
|
|||
|
/** Method variant for [`Result.unwrapOrElse`](../modules/_result_.html#unwraporelse) */
|
|||
|
unwrapOrElse<U>(this: Result<T, E>, elseFn: (error: E) => U): T | U;
|
|||
|
/** Method variant for [`Result.toMaybe`](../modules/_result_.html#tomaybe) */
|
|||
|
toMaybe(this: Result<T, E>): Maybe<T>;
|
|||
|
/** Method variant for [`Result.toString`](../modules/_result_.html#tostring) */
|
|||
|
toString(this: Result<T, E>): string;
|
|||
|
/** Method variant for [`Result.toJSON`](../modules/_result_.html#toJSON) */
|
|||
|
toJSON(this: Result<T, E>): ResultJSON<T, E>;
|
|||
|
/** Method variant for [`Result.equals`](../modules/_result_.html#equals) */
|
|||
|
equals(this: Result<T, E>, comparison: Result<T, E>): boolean;
|
|||
|
/** Method variant for [`Result.ap`](../modules/_result_.html#ap) */
|
|||
|
ap<A, B>(this: Result<(a: A) => B, E>, r: Result<A, E>): Result<B, E>;
|
|||
|
}
|
|||
|
/**
|
|||
|
Is this `Result` an `Ok` instance?
|
|||
|
|
|||
|
In TypeScript, narrows the type from `Result<T, E>` to `Ok<T, E>`.
|
|||
|
*/
|
|||
|
export declare function isOk<T, E>(result: Result<T, E>): result is Ok<T, E>;
|
|||
|
/**
|
|||
|
Is this `Result` an `Err` instance?
|
|||
|
|
|||
|
In TypeScript, narrows the type from `Result<T, E>` to `Err<T, E>`.
|
|||
|
*/
|
|||
|
export declare function isErr<T, E>(result: Result<T, E>): result is Err<T, E>;
|
|||
|
/**
|
|||
|
Create an instance of `Result.Ok`.
|
|||
|
|
|||
|
If you need to create an instance with a specific type (as you do whenever you
|
|||
|
are not constructing immediately for a function return or as an argument to a
|
|||
|
function), you can use a type parameter:
|
|||
|
|
|||
|
```ts
|
|||
|
const yayNumber = Result.ok<number, string>(12);
|
|||
|
```
|
|||
|
|
|||
|
Note: `null` is allowed by the type signature so that so that the function
|
|||
|
may be used to `throw` on passing `null` rather than constructing a type like
|
|||
|
`Result<null, string>`. `undefined` is allowed as a convenience method for
|
|||
|
constructing a `Result<Unit, E>`.
|
|||
|
|
|||
|
```ts
|
|||
|
const normalResult = Result.ok<number, string>(42);
|
|||
|
const explicitUnit = Result.ok<Unit, string>(Unit);
|
|||
|
const implicitUnit = Result.ok<Unit, string>();
|
|||
|
```
|
|||
|
|
|||
|
In the context of an immediate function return, or an arrow function with a
|
|||
|
single expression value, you do not have to specify the types, so this can be
|
|||
|
quite convenient.
|
|||
|
|
|||
|
```ts
|
|||
|
type SomeData = {
|
|||
|
//...
|
|||
|
};
|
|||
|
|
|||
|
const isValid = (data: SomeData): boolean => {
|
|||
|
// true or false...
|
|||
|
}
|
|||
|
|
|||
|
const arrowValidate = (data: SomeData): Result<Unit, string> =>
|
|||
|
isValid(data) ? Result.ok() : Result.err('something was wrong!');
|
|||
|
|
|||
|
function fnValidate(data: someData): Result<Unit, string> {
|
|||
|
return isValid(data) ? Result.ok() : Result.err('something was wrong');
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
@typeparam T The type of the item contained in the `Result`.
|
|||
|
@param value The value to wrap in a `Result.Ok`.
|
|||
|
*/
|
|||
|
export declare function ok<T = unknown, E = unknown>(): Result<Unit, E>;
|
|||
|
export declare function ok<T = unknown, E = unknown>(value: T): Result<T, E>;
|
|||
|
/** `Result.of` is an alias for `Result.ok`. */
|
|||
|
export declare const of: typeof ok;
|
|||
|
/**
|
|||
|
Create an instance of `Result.Error`.
|
|||
|
|
|||
|
If you need to create an instance with a specific type (as you do whenever you
|
|||
|
are not constructing immediately for a function return or as an argument to a
|
|||
|
function), you can use a type parameter:
|
|||
|
|
|||
|
```ts
|
|||
|
const notString = Result.err<number, string>('something went wrong');
|
|||
|
```
|
|||
|
|
|||
|
Note: `null` is allowed by the type signature so that so that the function
|
|||
|
may be used to `throw` on passing `null` rather than constructing a type like
|
|||
|
`Result<null, string>`. `undefined` is allowed as a convenience method for
|
|||
|
constructing a `Result<Unit, E>`.
|
|||
|
|
|||
|
```ts
|
|||
|
const normalResult = Result.err<number, string>('oh no');
|
|||
|
const explicitUnit = Result.err<number, Unit>(Unit);
|
|||
|
const implicitUnit = Result.err<number, Unit>();
|
|||
|
```
|
|||
|
|
|||
|
In the context of an immediate function return, or an arrow function with a
|
|||
|
single expression value, you do not have to specify the types, so this can be
|
|||
|
quite convenient.
|
|||
|
|
|||
|
```ts
|
|||
|
type SomeData = {
|
|||
|
//...
|
|||
|
};
|
|||
|
|
|||
|
const isValid = (data: SomeData): boolean => {
|
|||
|
// true or false...
|
|||
|
}
|
|||
|
|
|||
|
const arrowValidate = (data: SomeData): Result<number, Unit> =>
|
|||
|
isValid(data) ? Result.ok(42) : Result.err();
|
|||
|
|
|||
|
function fnValidate(data: someData): Result<number, Unit> {
|
|||
|
return isValid(data) ? Result.ok(42) : Result.err();
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
@typeparam T The type of the item contained in the `Result`.
|
|||
|
@param E The error value to wrap in a `Result.Err`.
|
|||
|
*/
|
|||
|
export declare function err<T = unknown, E = unknown>(): Result<T, Unit>;
|
|||
|
export declare function err<T = unknown, E = unknown>(error: E): Result<T, E>;
|
|||
|
/**
|
|||
|
Execute the provided callback, wrapping the return value in `Result.Ok` or
|
|||
|
`Result.Err(error)` if there is an exception.
|
|||
|
|
|||
|
```ts
|
|||
|
const aSuccessfulOperation = () => 2 + 2;
|
|||
|
|
|||
|
const anOkResult = Result.tryOr('Oh noes!!1', () => {
|
|||
|
aSuccessfulOperation()
|
|||
|
}); // => Ok(4)
|
|||
|
|
|||
|
const thisOperationThrows = () => throw new Error('Bummer');
|
|||
|
|
|||
|
const anErrResult = Result.tryOr('Oh noes!!1', () => {
|
|||
|
thisOperationThrows();
|
|||
|
}); // => Err('Oh noes!!1')
|
|||
|
```
|
|||
|
|
|||
|
@param error The error value in case of an exception
|
|||
|
@param callback The callback to try executing
|
|||
|
*/
|
|||
|
export declare function tryOr<T, E>(error: E, callback: () => T): Result<T, E>;
|
|||
|
export declare function tryOr<T, E>(error: E): (callback: () => T) => Result<T, E>;
|
|||
|
/**
|
|||
|
Execute the provided callback, wrapping the return value in `Result.Ok`.
|
|||
|
If there is an exception, return a `Result.Err` of whatever the `onError`
|
|||
|
function returns.
|
|||
|
|
|||
|
```ts
|
|||
|
const aSuccessfulOperation = () => 2 + 2;
|
|||
|
|
|||
|
const anOkResult = Result.tryOrElse(
|
|||
|
(e) => e,
|
|||
|
aSuccessfulOperation
|
|||
|
); // => Ok(4)
|
|||
|
|
|||
|
const thisOperationThrows = () => throw 'Bummer'
|
|||
|
|
|||
|
const anErrResult = Result.tryOrElse((e) => e, () => {
|
|||
|
thisOperationThrows();
|
|||
|
}); // => Err('Bummer')
|
|||
|
```
|
|||
|
|
|||
|
@param onError A function that takes `e` exception and returns what will
|
|||
|
be wrapped in a `Result.Err`
|
|||
|
@param callback The callback to try executing
|
|||
|
*/
|
|||
|
export declare function tryOrElse<T, E>(onError: (e: unknown) => E, callback: () => T): Result<T, E>;
|
|||
|
export declare function tryOrElse<T, E>(onError: (e: unknown) => E): (callback: () => T) => Result<T, E>;
|
|||
|
/**
|
|||
|
Map over a `Result` instance: apply the function to the wrapped value if the
|
|||
|
instance is `Ok`, and return the wrapped error value wrapped as a new `Err` of
|
|||
|
the correct type (`Result<U, E>`) if the instance is `Err`.
|
|||
|
|
|||
|
`Result.map` works a lot like `Array.prototype.map`, but with one important
|
|||
|
difference. Both `Result` and `Array` are containers for other kinds of items,
|
|||
|
but where `Array.prototype.map` has 0 to _n_ items, a `Result` always has
|
|||
|
exactly one item, which is *either* a success or an error instance.
|
|||
|
|
|||
|
Where `Array.prototype.map` will apply the mapping function to every item in
|
|||
|
the array (if there are any), `Result.map` will only apply the mapping
|
|||
|
function to the (single) element if an `Ok` instance, if there is one.
|
|||
|
|
|||
|
If you have no items in an array of
|
|||
|
numbers named `foo` and call `foo.map(x => x + 1)`, you'll still some have an
|
|||
|
array with nothing in it. But if you have any items in the array (`[2, 3]`),
|
|||
|
and you call `foo.map(x => x + 1)` on it, you'll get a new array with each of
|
|||
|
those items inside the array "container" transformed (`[3, 4]`).
|
|||
|
|
|||
|
With `Result.map`, the `Err` variant is treated *by the `map` function* kind
|
|||
|
of the same way as the empty array case: it's just ignored, and you get back a
|
|||
|
new `Result` that is still just the same `Err` instance. But if you have an
|
|||
|
`Ok` variant, the map function is applied to it, and you get back a new
|
|||
|
`Result` with the value transformed, and still wrapped in an `Ok`.
|
|||
|
|
|||
|
#### Examples
|
|||
|
|
|||
|
```ts
|
|||
|
import { ok, err, map, toString } from 'true-myth/result';
|
|||
|
const double = n => n * 2;
|
|||
|
|
|||
|
const anOk = ok(12);
|
|||
|
const mappedOk = map(double, anOk);
|
|||
|
console.log(toString(mappedOk)); // Ok(24)
|
|||
|
|
|||
|
const anErr = err("nothing here!");
|
|||
|
const mappedErr = map(double, anErr);
|
|||
|
console.log(toString(mappedOk)); // Err(nothing here!)
|
|||
|
```
|
|||
|
|
|||
|
@typeparam T The type of the value wrapped in an `Ok` instance, and taken as
|
|||
|
the argument to the `mapFn`.
|
|||
|
@typeparam U The type of the value wrapped in the new `Ok` instance after
|
|||
|
applying `mapFn`, that is, the type returned by `mapFn`.
|
|||
|
@typeparam E The type of the value wrapped in an `Err` instance.
|
|||
|
@param mapFn The function to apply the value to if `result` is `Ok`.
|
|||
|
@param result The `Result` instance to map over.
|
|||
|
@returns A new `Result` with the result of applying `mapFn` to the value
|
|||
|
in an `Ok`, or else the original `Err` value wrapped in the new
|
|||
|
instance.
|
|||
|
*/
|
|||
|
export declare function map<T, U, E>(mapFn: (t: T) => U, result: Result<T, E>): Result<U, E>;
|
|||
|
export declare function map<T, U, E>(mapFn: (t: T) => U): (result: Result<T, E>) => Result<U, E>;
|
|||
|
/**
|
|||
|
Map over a `Result` instance as in [`map`](#map) and get out the value
|
|||
|
if `result` is an `Ok`, or return a default value if `result` is an `Err`.
|
|||
|
|
|||
|
#### Examples
|
|||
|
|
|||
|
```ts
|
|||
|
import { ok, err, mapOr } from 'true-myth/result';
|
|||
|
|
|||
|
const length = (s: string) => s.length;
|
|||
|
|
|||
|
const anOkString = ok('a string');
|
|||
|
const theStringLength = mapOr(0, anOkString);
|
|||
|
console.log(theStringLength); // 8
|
|||
|
|
|||
|
const anErr = err('uh oh');
|
|||
|
const anErrMapped = mapOr(0, anErr);
|
|||
|
console.log(anErrMapped); // 0
|
|||
|
```
|
|||
|
|
|||
|
@param orU The default value to use if `result` is an `Err`.
|
|||
|
@param mapFn The function to apply the value to if `result` is an `Ok`.
|
|||
|
@param result The `Result` instance to map over.
|
|||
|
*/
|
|||
|
export declare function mapOr<T, U, E>(orU: U, mapFn: (t: T) => U, result: Result<T, E>): U;
|
|||
|
export declare function mapOr<T, U, E>(orU: U, mapFn: (t: T) => U): (result: Result<T, E>) => U;
|
|||
|
export declare function mapOr<T, U, E>(orU: U): (mapFn: (t: T) => U) => (result: Result<T, E>) => U;
|
|||
|
/**
|
|||
|
Map over a `Result` instance as in [`map`](#map) and get out the value if
|
|||
|
`result` is `Ok`, or apply a function (`orElseFn`) to the value wrapped in
|
|||
|
the `Err` to get a default value.
|
|||
|
|
|||
|
Like [`mapOr`](#mapor) but using a function to transform the error into a
|
|||
|
usable value instead of simply using a default value.
|
|||
|
|
|||
|
#### Examples
|
|||
|
|
|||
|
```ts
|
|||
|
import { ok, err, mapOrElse } from 'true-myth/result';
|
|||
|
|
|||
|
const summarize = (s: string) => `The response was: '${s}'`;
|
|||
|
const getReason = (err: { code: number, reason: string }) => err.reason;
|
|||
|
|
|||
|
const okResponse = ok("Things are grand here.");
|
|||
|
const mappedOkAndUnwrapped = mapOrElse(getReason, summarize, okResponse);
|
|||
|
console.log(mappedOkAndUnwrapped); // The response was: 'Things are grand here.'
|
|||
|
|
|||
|
const errResponse = err({ code: 500, reason: 'Nothing at this endpoint!' });
|
|||
|
const mappedErrAndUnwrapped = mapOrElse(getReason, summarize, errResponse);
|
|||
|
console.log(mappedErrAndUnwrapped); // Nothing at this endpoint!
|
|||
|
```
|
|||
|
|
|||
|
@typeparam T The type of the wrapped `Ok` value.
|
|||
|
@typeparam U The type of the resulting value from applying `mapFn` to the
|
|||
|
`Ok` value or `orElseFn` to the `Err` value.
|
|||
|
@typeparam E The type of the wrapped `Err` value.
|
|||
|
@param orElseFn The function to apply to the wrapped `Err` value to get a
|
|||
|
usable value if `result` is an `Err`.
|
|||
|
@param mapFn The function to apply to the wrapped `Ok` value if `result` is
|
|||
|
an `Ok`.
|
|||
|
@param result The `Result` instance to map over.
|
|||
|
*/
|
|||
|
export declare function mapOrElse<T, U, E>(orElseFn: (err: E) => U, mapFn: (t: T) => U, result: Result<T, E>): U;
|
|||
|
export declare function mapOrElse<T, U, E>(orElseFn: (err: E) => U, mapFn: (t: T) => U): (result: Result<T, E>) => U;
|
|||
|
export declare function mapOrElse<T, U, E>(orElseFn: (err: E) => U): (mapFn: (t: T) => U) => (result: Result<T, E>) => U;
|
|||
|
/**
|
|||
|
Map over a `Result`, exactly as in [`map`](#map), but operating on the value
|
|||
|
wrapped in an `Err` instead of the value wrapped in the `Ok`. This is handy
|
|||
|
for when you need to line up a bunch of different types of errors, or if you
|
|||
|
need an error of one shape to be in a different shape to use somewhere else in
|
|||
|
your codebase.
|
|||
|
|
|||
|
#### Examples
|
|||
|
|
|||
|
```ts
|
|||
|
import { ok, err, mapErr, toString } from 'true-myth/result';
|
|||
|
|
|||
|
const reason = (err: { code: number, reason: string }) => err.reason;
|
|||
|
|
|||
|
const anOk = ok(12);
|
|||
|
const mappedOk = mapErr(reason, anOk);
|
|||
|
console.log(toString(mappedOk)); // Ok(12)
|
|||
|
|
|||
|
const anErr = err({ code: 101, reason: 'bad file' });
|
|||
|
const mappedErr = mapErr(reason, anErr);
|
|||
|
console.log(toString(mappedErr)); // Err(bad file)
|
|||
|
```
|
|||
|
|
|||
|
@typeparam T The type of the value wrapped in the `Ok` of the `Result`.
|
|||
|
@typeparam E The type of the value wrapped in the `Err` of the `Result`.
|
|||
|
@typeparam F The type of the value wrapped in the `Err` of a new `Result`,
|
|||
|
returned by the `mapErrFn`.
|
|||
|
@param mapErrFn The function to apply to the value wrapped in `Err` if `result` is an `Err`.
|
|||
|
@param result The `Result` instance to map over an error case for.
|
|||
|
*/
|
|||
|
export declare function mapErr<T, E, F>(mapErrFn: (e: E) => F, result: Result<T, E>): Result<T, F>;
|
|||
|
export declare function mapErr<T, E, F>(mapErrFn: (e: E) => F): (result: Result<T, E>) => Result<T, F>;
|
|||
|
/**
|
|||
|
You can think of this like a short-circuiting logical "and" operation on a
|
|||
|
`Result` type. If `result` is `Ok`, then the result is the `andResult`. If
|
|||
|
`result` is `Err`, the result is the `Err`.
|
|||
|
|
|||
|
This is useful when you have another `Result` value you want to provide if
|
|||
|
and *only if* you have an `Ok` – that is, when you need to make sure that if you
|
|||
|
`Err`, whatever else you're handing a `Result` to *also* gets that `Err`.
|
|||
|
|
|||
|
Notice that, unlike in [`map`](#map) or its variants, the original `result` is
|
|||
|
not involved in constructing the new `Result`.
|
|||
|
|
|||
|
#### Examples
|
|||
|
|
|||
|
```ts
|
|||
|
import { and, ok, err, toString } from 'true-myth/result';
|
|||
|
|
|||
|
const okA = ok('A');
|
|||
|
const okB = ok('B');
|
|||
|
const anErr = err({ so: 'bad' });
|
|||
|
|
|||
|
console.log(toString(and(okB, okA))); // Ok(B)
|
|||
|
console.log(toString(and(okB, anErr))); // Err([object Object])
|
|||
|
console.log(toString(and(anErr, okA))); // Err([object Object])
|
|||
|
console.log(toString(and(anErr, anErr))); // Err([object Object])
|
|||
|
```
|
|||
|
|
|||
|
@typeparam T The type of the value wrapped in the `Ok` of the `Result`.
|
|||
|
@typeparam U The type of the value wrapped in the `Ok` of the `andResult`,
|
|||
|
i.e. the success type of the `Result` present if the checked
|
|||
|
`Result` is `Ok`.
|
|||
|
@typeparam E The type of the value wrapped in the `Err` of the `Result`.
|
|||
|
@param andResult The `Result` instance to return if `result` is `Err`.
|
|||
|
@param result The `Result` instance to check.
|
|||
|
*/
|
|||
|
export declare function and<T, U, E>(andResult: Result<U, E>, result: Result<T, E>): Result<U, E>;
|
|||
|
export declare function and<T, U, E>(andResult: Result<U, E>): (result: Result<T, E>) => Result<U, E>;
|
|||
|
/**
|
|||
|
Apply a function to the wrapped value if `Ok` and return a new `Ok`
|
|||
|
containing the resulting value; or if it is `Err` return it unmodified.
|
|||
|
|
|||
|
This differs from `map` in that `thenFn` returns another `Result`. You can use
|
|||
|
`andThen` to combine two functions which *both* create a `Result` from an
|
|||
|
unwrapped type.
|
|||
|
|
|||
|
You may find the `.then` method on an ES6 `Promise` helpful for comparison: if
|
|||
|
you have a `Promise`, you can pass its `then` method a callback which
|
|||
|
returns another `Promise`, and the result will not be a *nested* promise, but
|
|||
|
a single `Promise`. The difference is that `Promise#then` unwraps *all*
|
|||
|
layers to only ever return a single `Promise` value, whereas `Result.andThen`
|
|||
|
will not unwrap nested `Result`s.
|
|||
|
|
|||
|
This is also commonly known as (and therefore aliased as) [`flatMap`] or
|
|||
|
[`chain`]. It is sometimes also known as `bind`, but *not* aliased as such
|
|||
|
because [`bind` already means something in JavaScript][bind].
|
|||
|
|
|||
|
[`flatMap`]: #flatmap
|
|||
|
[`chain`]: #chain
|
|||
|
[bind]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
|
|||
|
|
|||
|
#### Examples
|
|||
|
|
|||
|
```ts
|
|||
|
import { ok, err, andThen, toString } from 'true-myth/result';
|
|||
|
|
|||
|
const toLengthAsResult = (s: string) => ok(s.length);
|
|||
|
|
|||
|
const anOk = ok('just a string');
|
|||
|
const lengthAsResult = andThen(toLengthAsResult, anOk);
|
|||
|
console.log(toString(lengthAsResult)); // Ok(13)
|
|||
|
|
|||
|
const anErr = err(['srsly', 'whatever']);
|
|||
|
const notLengthAsResult = andThen(toLengthAsResult, anErr);
|
|||
|
console.log(toString(notLengthAsResult)); // Err(srsly,whatever)
|
|||
|
```
|
|||
|
|
|||
|
@typeparam T The type of the value wrapped in the `Ok` of the `Result`.
|
|||
|
@typeparam U The type of the value wrapped in the `Ok` of the `Result`
|
|||
|
returned by the `thenFn`.
|
|||
|
@typeparam E The type of the value wrapped in the `Err` of the `Result`.
|
|||
|
@param thenFn The function to apply to the wrapped `T` if `maybe` is `Just`.
|
|||
|
@param result The `Maybe` to evaluate and possibly apply a function to.
|
|||
|
*/
|
|||
|
export declare function andThen<T, U, E>(thenFn: (t: T) => Result<U, E>, result: Result<T, E>): Result<U, E>;
|
|||
|
export declare function andThen<T, U, E>(thenFn: (t: T) => Result<U, E>): (result: Result<T, E>) => Result<U, E>;
|
|||
|
/** Alias for [`andThen`](#andthen). */
|
|||
|
export declare const chain: typeof andThen;
|
|||
|
/** Alias for [`andThen`](#andthen). */
|
|||
|
export declare const flatMap: typeof andThen;
|
|||
|
/**
|
|||
|
Provide a fallback for a given `Result`. Behaves like a logical `or`: if the
|
|||
|
`result` value is an `Ok`, returns that `result`; otherwise, returns the
|
|||
|
`defaultResult` value.
|
|||
|
|
|||
|
This is useful when you want to make sure that something which takes a
|
|||
|
`Result` always ends up getting an `Ok` variant, by supplying a default value
|
|||
|
for the case that you currently have an `Err`.
|
|||
|
|
|||
|
```ts
|
|||
|
import { ok, err, Result, or } from 'true-utils/result';
|
|||
|
|
|||
|
const okA = ok<string, string>('a');
|
|||
|
const okB = ok<string, string>('b');
|
|||
|
const anErr = err<string, string>(':wat:');
|
|||
|
const anotherErr = err<string, string>(':headdesk:');
|
|||
|
|
|||
|
console.log(or(okB, okA).toString()); // Ok(A)
|
|||
|
console.log(or(anErr, okA).toString()); // Ok(A)
|
|||
|
console.log(or(okB, anErr).toString()); // Ok(B)
|
|||
|
console.log(or(anotherErr, anErr).toString()); // Err(:headdesk:)
|
|||
|
```
|
|||
|
|
|||
|
@typeparam T The type wrapped in the `Ok` case of `result`.
|
|||
|
@typeparam E The type wrapped in the `Err` case of `result`.
|
|||
|
@typeparam F The type wrapped in the `Err` case of `defaultResult`.
|
|||
|
@param defaultResult The `Result` to use if `result` is an `Err`.
|
|||
|
@param result The `Result` instance to check.
|
|||
|
@returns `result` if it is an `Ok`, otherwise `defaultResult`.
|
|||
|
*/
|
|||
|
export declare function or<T, E, F>(defaultResult: Result<T, F>, result: Result<T, E>): Result<T, F>;
|
|||
|
export declare function or<T, E, F>(defaultResult: Result<T, F>): (result: Result<T, E>) => Result<T, F>;
|
|||
|
/**
|
|||
|
Like `or`, but using a function to construct the alternative `Result`.
|
|||
|
|
|||
|
Sometimes you need to perform an operation using other data in the environment
|
|||
|
to construct the fallback value. In these situations, you can pass a function
|
|||
|
(which may be a closure) as the `elseFn` to generate the fallback `Result<T>`.
|
|||
|
It can then transform the data in the `Err` to something usable as an `Ok`, or
|
|||
|
generate a new `Err` instance as appropriate.
|
|||
|
|
|||
|
Useful for transforming failures to usable data.
|
|||
|
|
|||
|
@param elseFn The function to apply to the contents of the `Err` if `result`
|
|||
|
is an `Err`, to create a new `Result`.
|
|||
|
@param result The `Result` to use if it is an `Ok`.
|
|||
|
@returns The `result` if it is `Ok`, or the `Result` returned by `elseFn`
|
|||
|
if `result` is an `Err.
|
|||
|
*/
|
|||
|
export declare function orElse<T, E, F>(elseFn: (err: E) => Result<T, F>, result: Result<T, E>): Result<T, F>;
|
|||
|
export declare function orElse<T, E, F>(elseFn: (err: E) => Result<T, F>): (result: Result<T, E>) => Result<T, F>;
|
|||
|
/**
|
|||
|
Get the value out of the `Result`.
|
|||
|
|
|||
|
Returns the content of an `Ok`, but **throws if the `Result` is `Err`.**
|
|||
|
Prefer to use [`unwrapOr`](#unwrapor) or [`unwrapOrElse`](#unwraporelse).
|
|||
|
|
|||
|
@throws If the `Result` instance is `Nothing`.
|
|||
|
*/
|
|||
|
export declare function unsafelyUnwrap<T, E>(result: Result<T, E>): T;
|
|||
|
/** Alias for [`unsafelyUnwrap`](#unsafelyunwrap) */
|
|||
|
export declare const unsafelyGet: typeof unsafelyUnwrap;
|
|||
|
/** Alias for [`unsafelyUnwrap`](#unsafelyunwrap) */
|
|||
|
export declare const unsafeGet: typeof unsafelyUnwrap;
|
|||
|
/**
|
|||
|
Get the error value out of the [`Result`](#result).
|
|||
|
|
|||
|
Returns the content of an `Err`, but **throws if the `Result` is `Ok`**.
|
|||
|
Prefer to use [`unwrapOrElse`](#unwraporelse).
|
|||
|
|
|||
|
@param result
|
|||
|
@throws Error If the `Result` instance is `Nothing`.
|
|||
|
*/
|
|||
|
export declare function unsafelyUnwrapErr<T, E>(result: Result<T, E>): E;
|
|||
|
/** Alias for [`unsafelyUnwrapErr`](#unsafelyunwraperr) */
|
|||
|
export declare const unsafelyGetErr: typeof unsafelyUnwrapErr;
|
|||
|
/**
|
|||
|
Safely get the value out of the `Ok` variant of a [`Result`](#result).
|
|||
|
|
|||
|
This is the recommended way to get a value out of a `Result` most of the time.
|
|||
|
|
|||
|
```ts
|
|||
|
import { ok, err, unwrapOr } from 'true-myth/result';
|
|||
|
|
|||
|
const anOk = ok<number, string>(12);
|
|||
|
console.log(unwrapOr(0, anOk)); // 12
|
|||
|
|
|||
|
const anErr = err<number, string>('nooooo');
|
|||
|
console.log(unwrapOr(0, anErr)); // 0
|
|||
|
```
|
|||
|
|
|||
|
@typeparam T The value wrapped in the `Ok`.
|
|||
|
@typeparam E The value wrapped in the `Err`.
|
|||
|
@param defaultValue The value to use if `result` is an `Err`.
|
|||
|
@param result The `Result` instance to unwrap if it is an `Ok`.
|
|||
|
@returns The content of `result` if it is an `Ok`, otherwise
|
|||
|
`defaultValue`.
|
|||
|
*/
|
|||
|
export declare function unwrapOr<T, U, E>(defaultValue: U, result: Result<T, E>): U | T;
|
|||
|
export declare function unwrapOr<T, U, E>(defaultValue: U): (result: Result<T, E>) => U | T;
|
|||
|
/** Alias for [`unwrapOr`](#unwrapor) */
|
|||
|
export declare const getOr: typeof unwrapOr;
|
|||
|
/**
|
|||
|
Safely get the value out of a [`Result`](#result) by returning the wrapped
|
|||
|
value if it is `Ok`, or by applying `orElseFn` to the value in the `Err`.
|
|||
|
|
|||
|
This is useful when you need to *generate* a value (e.g. by using current
|
|||
|
values in the environment – whether preloaded or by local closure) instead of
|
|||
|
having a single default value available (as in [`unwrapOr`](#unwrapor)).
|
|||
|
|
|||
|
```ts
|
|||
|
import { ok, err, unwrapOrElse } from 'true-myth/result';
|
|||
|
|
|||
|
// You can imagine that someOtherValue might be dynamic.
|
|||
|
const someOtherValue = 2;
|
|||
|
const handleErr = (errValue: string) => errValue.length + someOtherValue;
|
|||
|
|
|||
|
const anOk = ok<number, string>(42);
|
|||
|
console.log(unwrapOrElse(handleErr, anOk)); // 42
|
|||
|
|
|||
|
const anErr = err<number, string>('oh teh noes');
|
|||
|
console.log(unwrapOrElse(handleErr, anErr)); // 13
|
|||
|
```
|
|||
|
|
|||
|
@typeparam T The value wrapped in the `Ok`.
|
|||
|
@typeparam E The value wrapped in the `Err`.
|
|||
|
@param orElseFn A function applied to the value wrapped in `result` if it is
|
|||
|
an `Err`, to generate the final value.
|
|||
|
@param result The `result` to unwrap if it is an `Ok`.
|
|||
|
@returns The value wrapped in `result` if it is `Ok` or the value
|
|||
|
returned by `orElseFn` applied to the value in `Err`.
|
|||
|
*/
|
|||
|
export declare function unwrapOrElse<T, U, E>(orElseFn: (error: E) => U, result: Result<T, E>): T | U;
|
|||
|
export declare function unwrapOrElse<T, U, E>(orElseFn: (error: E) => U): (result: Result<T, E>) => T | U;
|
|||
|
/** Alias for [`unwrapOrElse`](#unwraporelse) */
|
|||
|
export declare const getOrElse: typeof unwrapOrElse;
|
|||
|
/**
|
|||
|
Convert a [`Result`](#result) to a [`Maybe`](../modules/_maybe_.html#maybe).
|
|||
|
|
|||
|
The converted type will be [`Just`] if the `Result` is [`Ok`] or [`Nothing`]
|
|||
|
if the `Result` is [`Err`]; the wrapped error value will be discarded.
|
|||
|
|
|||
|
[`Just`]: ../classes/_maybe_.just.html
|
|||
|
[`Nothing`]: ../classes/_maybe_.nothing.html
|
|||
|
[`Ok`]: ../classes/_result_.ok.html
|
|||
|
[`Err`]: ../classes/_result_.err.html
|
|||
|
|
|||
|
@param result The `Result` to convert to a `Maybe`
|
|||
|
@returns `Just` the value in `result` if it is `Ok`; otherwise `Nothing`
|
|||
|
*/
|
|||
|
export declare function toMaybe<T>(result: Result<T, any>): Maybe<T>;
|
|||
|
/**
|
|||
|
Transform a [`Maybe`](../modules/_maybe_.html#maybe) into a [`Result`](#result).
|
|||
|
|
|||
|
If the `Maybe` is a [`Just`], its value will be wrapped in the [`Ok`] variant;
|
|||
|
if it is a [`Nothing`] the `errValue` will be wrapped in the [`Err`] variant.
|
|||
|
|
|||
|
[`Just`]: ../classes/_maybe_.just.html
|
|||
|
[`Nothing`]: ../classes/_maybe_.nothing.html
|
|||
|
[`Ok`]: ../classes/_result_.ok.html
|
|||
|
[`Err`]: ../classes/_result_.err.html
|
|||
|
|
|||
|
@param errValue A value to wrap in an `Err` if `maybe` is a `Nothing`.
|
|||
|
@param maybe The `Maybe` to convert to a `Result`.
|
|||
|
*/
|
|||
|
export declare function fromMaybe<T, E>(errValue: E, maybe: Maybe<T>): Result<T, E>;
|
|||
|
export declare function fromMaybe<T, E>(errValue: E): (maybe: Maybe<T>) => Result<T, E>;
|
|||
|
/**
|
|||
|
Create a `String` representation of a `result` instance.
|
|||
|
|
|||
|
An `Ok` instance will be printed as `Ok(<representation of the value>)`, and
|
|||
|
an `Err` instance will be printed as `Err(<representation of the error>)`,
|
|||
|
where the representation of the value or error is simply the value or error's
|
|||
|
own `toString` representation. For example:
|
|||
|
|
|||
|
call | output
|
|||
|
--------------------------------- | ----------------------
|
|||
|
`toString(ok(42))` | `Ok(42)`
|
|||
|
`toString(ok([1, 2, 3]))` | `Ok(1,2,3)`
|
|||
|
`toString(ok({ an: 'object' }))` | `Ok([object Object])`n
|
|||
|
`toString(err(42))` | `Err(42)`
|
|||
|
`toString(err([1, 2, 3]))` | `Err(1,2,3)`
|
|||
|
`toString(err({ an: 'object' }))` | `Err([object Object])`
|
|||
|
|
|||
|
@typeparam T The type of the wrapped value; its own `.toString` will be used
|
|||
|
to print the interior contents of the `Just` variant.
|
|||
|
@param maybe The value to convert to a string.
|
|||
|
@returns The string representation of the `Maybe`.
|
|||
|
*/
|
|||
|
export declare const toString: <T extends {
|
|||
|
toString(): string;
|
|||
|
}, E extends {
|
|||
|
toString(): string;
|
|||
|
}>(result: Result<T, E>) => string;
|
|||
|
/**
|
|||
|
* Create an `Object` representation of a `Result` instance.
|
|||
|
*
|
|||
|
* Useful for serialization. `JSON.stringify()` uses it.
|
|||
|
*
|
|||
|
* @param result The value to convert to JSON
|
|||
|
* @returns The JSON representation of the `Result`
|
|||
|
*/
|
|||
|
export declare const toJSON: <T, E>(result: Result<T, E>) => ResultJSON<T, E>;
|
|||
|
/** A lightweight object defining how to handle each variant of a Maybe. */
|
|||
|
export declare type Matcher<T, E, A> = {
|
|||
|
Ok: (value: T) => A;
|
|||
|
Err: (error: E) => A;
|
|||
|
};
|
|||
|
/**
|
|||
|
Performs the same basic functionality as `getOrElse`, but instead of simply
|
|||
|
unwrapping the value if it is `Ok` and applying a value to generate the same
|
|||
|
default type if it is `Nothing`, lets you supply functions which may transform
|
|||
|
the wrapped type if it is `Ok` or get a default value for `Nothing`.
|
|||
|
|
|||
|
This is kind of like a poor man's version of pattern matching, which
|
|||
|
JavaScript currently lacks.
|
|||
|
|
|||
|
Instead of code like this:
|
|||
|
|
|||
|
```ts
|
|||
|
import { Result, isOk, match } from 'true-myth/result';
|
|||
|
|
|||
|
const logValue = (mightBeANumber: Result<number, string>) => {
|
|||
|
console.log(
|
|||
|
isOk(mightBeANumber)
|
|||
|
? unsafelyUnwrap(mightBeANumber).toString()
|
|||
|
: `There was an error: ${unsafelyGetErr(mightBeANumber)}`
|
|||
|
);
|
|||
|
};
|
|||
|
```
|
|||
|
|
|||
|
...we can write code like this:
|
|||
|
|
|||
|
```ts
|
|||
|
import { Result, match } from 'true-myth/result';
|
|||
|
|
|||
|
const logValue = (mightBeANumber: Result<number, string>) => {
|
|||
|
const value = match(
|
|||
|
{
|
|||
|
Ok: n => n.toString(),
|
|||
|
Err: e => `There was an error: ${e}`,
|
|||
|
},
|
|||
|
mightBeANumber
|
|||
|
);
|
|||
|
console.log(value);
|
|||
|
};
|
|||
|
```
|
|||
|
|
|||
|
This is slightly longer to write, but clearer: the more complex the resulting
|
|||
|
expression, the hairer it is to understand the ternary. Thus, this is
|
|||
|
especially convenient for times when there is a complex result, e.g. when
|
|||
|
rendering part of a React component inline in JSX/TSX.
|
|||
|
|
|||
|
@param matcher A lightweight object defining what to do in the case of each
|
|||
|
variant.
|
|||
|
@param maybe The `maybe` instance to check.
|
|||
|
*/
|
|||
|
export declare function match<T, E, A>(matcher: Matcher<T, E, A>, result: Result<T, E>): A;
|
|||
|
export declare function match<T, E, A>(matcher: Matcher<T, E, A>): (result: Result<T, E>) => A;
|
|||
|
/** Alias for [`match`](#match) */
|
|||
|
export declare const cata: typeof match;
|
|||
|
/**
|
|||
|
Allows quick triple-equal equality check between the values inside two `result`s
|
|||
|
without having to unwrap them first.
|
|||
|
|
|||
|
```ts
|
|||
|
const a = Result.of(3)
|
|||
|
const b = Result.of(3)
|
|||
|
const c = Result.of(null)
|
|||
|
const d = Result.nothing()
|
|||
|
|
|||
|
Result.equals(a, b) // true
|
|||
|
Result.equals(a, c) // false
|
|||
|
Result.equals(c, d) // true
|
|||
|
```
|
|||
|
|
|||
|
@param resultB A `maybe` to compare to.
|
|||
|
@param resultA A `maybe` instance to check.
|
|||
|
*/
|
|||
|
export declare function equals<T, E>(resultB: Result<T, E>, resultA: Result<T, E>): boolean;
|
|||
|
export declare function equals<T, E>(resultB: Result<T, E>): (resultA: Result<T, E>) => boolean;
|
|||
|
/**
|
|||
|
Allows you to *apply* (thus `ap`) a value to a function without having to
|
|||
|
take either out of the context of their `Result`s. This does mean that the
|
|||
|
transforming function is itself within a `Result`, which can be hard to grok
|
|||
|
at first but lets you do some very elegant things. For example, `ap` allows
|
|||
|
you to do this:
|
|||
|
|
|||
|
```ts
|
|||
|
import Result from 'true-myth/result';
|
|||
|
|
|||
|
const one = Result.ok<number, string>(1);
|
|||
|
const five = Result.ok<number, string>(5);
|
|||
|
const whoops = Result.err<number, string>('oh no');
|
|||
|
|
|||
|
const add = (a: number) => (b: number) => a + b;
|
|||
|
const resultAdd = Result.ok<typeof add, string>(add);
|
|||
|
|
|||
|
resultAdd.ap(one).ap(five); // Ok(6)
|
|||
|
resultAdd.ap(one).ap(whoops); // Err('oh no')
|
|||
|
resultAdd.ap(whoops).ap(five) // Err('oh no')
|
|||
|
```
|
|||
|
|
|||
|
Without `Result.ap`, you'd need to do something like a nested `Result.match`:
|
|||
|
|
|||
|
```ts
|
|||
|
import { ok, err } from 'true-myth/result';
|
|||
|
|
|||
|
const one = ok<number, string>(1);
|
|||
|
const five = ok<number, string>(5);
|
|||
|
const whoops = err<number, string>('oh no');
|
|||
|
|
|||
|
one.match({
|
|||
|
Ok: n => five.match({
|
|||
|
Ok: o => ok<number, string>(n + o),
|
|||
|
Err: e => err<number, string>(e),
|
|||
|
}),
|
|||
|
Err: e => err<number, string>(e),
|
|||
|
}); // Ok(6)
|
|||
|
|
|||
|
one.match({
|
|||
|
Ok: n => whoops.match({
|
|||
|
Ok: o => ok<number, string>(n + o),
|
|||
|
Err: e => err<number, string>(e),
|
|||
|
}),
|
|||
|
Err: e => err<number, string>(e),
|
|||
|
}); // Err('oh no')
|
|||
|
|
|||
|
whoops.match({
|
|||
|
Ok: n => five.match({
|
|||
|
Ok: o => ok(n + o),
|
|||
|
Err: e => err(e),
|
|||
|
}),
|
|||
|
Err: e => err(e),
|
|||
|
}); // Err('oh no')
|
|||
|
```
|
|||
|
|
|||
|
And this kind of thing comes up quite often once you're using `Maybe` to
|
|||
|
handle optionality throughout your application.
|
|||
|
|
|||
|
For another example, imagine you need to compare the equality of two
|
|||
|
ImmutableJS data structures, where a `===` comparison won't work. With `ap`,
|
|||
|
that's as simple as this:
|
|||
|
|
|||
|
```ts
|
|||
|
import { ok } from 'true-myth/result';
|
|||
|
import Immutable from 'immutable';
|
|||
|
import { curry } from 'lodash'
|
|||
|
|
|||
|
const is = curry(Immutable.is);
|
|||
|
|
|||
|
const x = ok(Immutable.Set.of(1, 2, 3));
|
|||
|
const y = ok(Immutable.Set.of(2, 3, 4));
|
|||
|
|
|||
|
ok(is).ap(x).ap(y); // Ok(false)
|
|||
|
```
|
|||
|
|
|||
|
Without `ap`, we're back to that gnarly nested `match`:
|
|||
|
|
|||
|
```ts
|
|||
|
* import Result, { ok, err } from 'true-myth/result';
|
|||
|
import Immutable from 'immutable';
|
|||
|
import { curry } from 'lodash'
|
|||
|
|
|||
|
const is = curry(Immutable.is);
|
|||
|
|
|||
|
const x = ok(Immutable.Set.of(1, 2, 3));
|
|||
|
const y = ok(Immutable.Set.of(2, 3, 4));
|
|||
|
|
|||
|
x.match({
|
|||
|
Ok: iX => y.match({
|
|||
|
Ok: iY => Result.of(Immutable.is(iX, iY)),
|
|||
|
Err: (e) => ok(false),
|
|||
|
})
|
|||
|
Err: (e) => ok(false),
|
|||
|
}); // Ok(false)
|
|||
|
```
|
|||
|
|
|||
|
In summary: anywhere you have two `Maybe` instances and need to perform an
|
|||
|
operation that uses both of them, `ap` is your friend.
|
|||
|
|
|||
|
Two things to note, both regarding *currying*:
|
|||
|
|
|||
|
1. All functions passed to `ap` must be curried. That is, they must be of the
|
|||
|
form (for add) `(a: number) => (b: number) => a + b`, *not* the more usual
|
|||
|
`(a: number, b: number) => a + b` you see in JavaScript more generally.
|
|||
|
|
|||
|
For convenience, you may want to look at Lodash's `_.curry` or Ramda's
|
|||
|
`R.curry`, which allow you to create curried versions of functions
|
|||
|
whenever you want:
|
|||
|
|
|||
|
```
|
|||
|
import Result from 'true-myth/result';
|
|||
|
import { curry } from 'lodash';
|
|||
|
|
|||
|
const normalAdd = (a: number, b: number) => a + b;
|
|||
|
const curriedAdd = curry(normalAdd); // (a: number) => (b: number) => a + b;
|
|||
|
|
|||
|
Result.of(curriedAdd).ap(Result.of(1)).ap(Result.of(5)); // Ok(6)
|
|||
|
```
|
|||
|
|
|||
|
2. You will need to call `ap` as many times as there are arguments to the
|
|||
|
function you're dealing with. So in the case of `add`, which has the
|
|||
|
"arity" (function argument count) of 2 (`a` and `b`), you'll need to call
|
|||
|
`ap` twice: once for `a`, and once for `b`. To see why, let's look at what
|
|||
|
the result in each phase is:
|
|||
|
|
|||
|
```ts
|
|||
|
const add = (a: number) => (b: number) => a + b;
|
|||
|
|
|||
|
const maybeAdd = Result.of(add); // Ok((a: number) => (b: number) => a + b)
|
|||
|
const maybeAdd1 = maybeAdd.ap(Result.of(1)); // Ok((b: number) => 1 + b)
|
|||
|
const final = maybeAdd1.ap(Result.of(3)); // Ok(4)
|
|||
|
```
|
|||
|
|
|||
|
So for `toString`, which just takes a single argument, you would only need
|
|||
|
to call `ap` once.
|
|||
|
|
|||
|
```ts
|
|||
|
const toStr = (v: { toString(): string }) => v.toString();
|
|||
|
Result.of(toStr).ap(12); // Ok("12")
|
|||
|
```
|
|||
|
|
|||
|
One other scenario which doesn't come up *quite* as often but is conceivable
|
|||
|
is where you have something that may or may not actually construct a function
|
|||
|
for handling a specific `Result` scenario. In that case, you can wrap the
|
|||
|
possibly-present in `ap` and then wrap the values to apply to the function to
|
|||
|
in `Result` themselves.
|
|||
|
|
|||
|
Because `Result` often requires you to type out the full type parameterization
|
|||
|
on a regular basis, it's convenient to use TypeScript's `typeof` operator to
|
|||
|
write out the type of a curried function. For example, if you had a function
|
|||
|
that simply merged three strings, you might write it like this:
|
|||
|
|
|||
|
```ts
|
|||
|
import Result from 'true-myth/result';
|
|||
|
import { curry } from 'lodash';
|
|||
|
|
|||
|
const merge3Strs = (a: string, b: string, c: string) => string;
|
|||
|
const curriedMerge = curry(merge3Strs);
|
|||
|
|
|||
|
const fn = Result.ok<typeof curriedMerge, string>(curriedMerge);
|
|||
|
```
|
|||
|
|
|||
|
The alternative is writing out the full signature long-form:
|
|||
|
|
|||
|
```ts
|
|||
|
const fn = Result.ok<(a: string) => (b: string) => (c: string) => string, string>(curriedMerge);
|
|||
|
```
|
|||
|
|
|||
|
**Aside:** `ap` is not named `apply` because of the overlap with JavaScript's
|
|||
|
existing [`apply`] function – and although strictly speaking, there isn't any
|
|||
|
direct overlap (`Result.apply` and `Function.prototype.apply` don't intersect
|
|||
|
at all) it's useful to have a different name to avoid implying that they're
|
|||
|
the same.
|
|||
|
|
|||
|
[`apply`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
|
|||
|
|
|||
|
@param resultFn result of a function from T to U
|
|||
|
@param result result of a T to apply to `fn`
|
|||
|
*/
|
|||
|
export declare function ap<T, U, E>(resultFn: Result<(t: T) => U, E>, result: Result<T, E>): Result<U, E>;
|
|||
|
export declare function ap<T, U, E>(resultFn: Result<(t: T) => U, E>): (result: Result<T, E>) => Result<U, E>;
|
|||
|
/**
|
|||
|
Determine whether an item is an instance of `Just` or `Nothing`.
|
|||
|
|
|||
|
@param item The item to check.
|
|||
|
*/
|
|||
|
export declare function isInstance<T = any, E = any>(item: any): item is Result<T, E>;
|
|||
|
/**
|
|||
|
A value which may (`Ok`) or may not (`Err`) be present.
|
|||
|
|
|||
|
The behavior of this type is checked by TypeScript at compile time, and bears
|
|||
|
no runtime overhead other than the very small cost of the container object.
|
|||
|
*/
|
|||
|
export declare type Result<T, E> = Ok<T, E> | Err<T, E>;
|
|||
|
export declare const Result: {
|
|||
|
Variant: typeof Variant;
|
|||
|
Ok: typeof Ok;
|
|||
|
Err: typeof Err;
|
|||
|
isOk: typeof isOk;
|
|||
|
isErr: typeof isErr;
|
|||
|
ok: typeof ok;
|
|||
|
err: typeof err;
|
|||
|
tryOr: typeof tryOr;
|
|||
|
tryOrElse: typeof tryOrElse;
|
|||
|
map: typeof map;
|
|||
|
mapOr: typeof mapOr;
|
|||
|
mapOrElse: typeof mapOrElse;
|
|||
|
mapErr: typeof mapErr;
|
|||
|
and: typeof and;
|
|||
|
andThen: typeof andThen;
|
|||
|
chain: typeof andThen;
|
|||
|
flatMap: typeof andThen;
|
|||
|
or: typeof or;
|
|||
|
orElse: typeof orElse;
|
|||
|
unsafelyUnwrap: typeof unsafelyUnwrap;
|
|||
|
unsafelyGet: typeof unsafelyUnwrap;
|
|||
|
unsafeGet: typeof unsafelyUnwrap;
|
|||
|
unsafelyUnwrapErr: typeof unsafelyUnwrapErr;
|
|||
|
unsafelyGetErr: typeof unsafelyUnwrapErr;
|
|||
|
unwrapOr: typeof unwrapOr;
|
|||
|
getOr: typeof unwrapOr;
|
|||
|
unwrapOrElse: typeof unwrapOrElse;
|
|||
|
getOrElse: typeof unwrapOrElse;
|
|||
|
toMaybe: typeof toMaybe;
|
|||
|
fromMaybe: typeof fromMaybe;
|
|||
|
toString: <T extends {
|
|||
|
toString(): string;
|
|||
|
}, E extends {
|
|||
|
toString(): string;
|
|||
|
}>(result: Result<T, E>) => string;
|
|||
|
toJSON: <T_1, E_1>(result: Result<T_1, E_1>) => ResultJSON<T_1, E_1>;
|
|||
|
match: typeof match;
|
|||
|
cata: typeof match;
|
|||
|
equals: typeof equals;
|
|||
|
ap: typeof ap;
|
|||
|
isInstance: typeof isInstance;
|
|||
|
};
|
|||
|
export default Result;
|
|||
|
//# sourceMappingURL=result.d.ts.map
|