1488 lines
56 KiB
TypeScript
1488 lines
56 KiB
TypeScript
/** [[include:doc/maybe.md]] */
|
||
/** (keep typedoc from getting confused by the imports) */
|
||
import * as Result from './result';
|
||
declare type Result<T, E> = import('./result').Result<T, E>;
|
||
/**
|
||
Discriminant for the `Just` and `Nothing` variants.
|
||
|
||
You can use the discriminant via the `variant` property of `Maybe` instances
|
||
if you need to match explicitly on it.
|
||
*/
|
||
export declare enum Variant {
|
||
Just = "Just",
|
||
Nothing = "Nothing"
|
||
}
|
||
interface JustJSON<T> {
|
||
variant: Variant.Just;
|
||
value: T;
|
||
}
|
||
interface NothingJSON {
|
||
variant: Variant.Nothing;
|
||
}
|
||
declare type MaybeJSON<T> = JustJSON<T> | NothingJSON;
|
||
/** Simply defines the common shape for `Just` and `Nothing`. */
|
||
export interface MaybeShape<T> {
|
||
/** Distinguish between the `Just` and `Nothing` [variants](../enums/_maybe_.variant). */
|
||
readonly variant: Variant;
|
||
/** Method variant for [`Maybe.isJust`](../modules/_maybe_.html#isjust) */
|
||
isJust(this: Maybe<T>): this is Just<T>;
|
||
/** Method variant for [`Maybe.isNothing`](../modules/_maybe_.html#isnothing) */
|
||
isNothing(this: Maybe<T>): this is Nothing<T>;
|
||
/** Method variant for [`Maybe.map`](../modules/_maybe_.html#map) */
|
||
map<U>(this: Maybe<T>, mapFn: (t: T) => U): Maybe<U>;
|
||
/** Method variant for [`Maybe.mapOr`](../modules/_maybe_.html#mapor) */
|
||
mapOr<U>(this: Maybe<T>, orU: U, mapFn: (t: T) => U): U;
|
||
/** Method variant for [`Maybe.mapOrElse`](../modules/_maybe_.html#maporelse) */
|
||
mapOrElse<U>(this: Maybe<T>, orElseFn: () => U, mapFn: (t: T) => U): U;
|
||
/** Method variant for [`Maybe.match`](../modules/_maybe_.html#match) */
|
||
match<U>(this: Maybe<T>, matcher: Matcher<T, U>): U;
|
||
/** Method variant for [`Maybe.or`](../modules/_maybe_.html#or) */
|
||
or(this: Maybe<T>, mOr: Maybe<T>): Maybe<T>;
|
||
/** Method variant for [`Maybe.orElse`](../modules/_maybe_.html#orelse) */
|
||
orElse(this: Maybe<T>, orElseFn: () => Maybe<T>): Maybe<T>;
|
||
/** Method variant for [`Maybe.and`](../modules/_maybe_.html#and) */
|
||
and<U>(this: Maybe<T>, mAnd: Maybe<U>): Maybe<U>;
|
||
/** Method variant for [`Maybe.andThen`](../modules/_maybe_.html#andthen) */
|
||
andThen<U>(this: Maybe<T>, andThenFn: (t: T) => Maybe<U>): Maybe<U>;
|
||
/** Method variant for [`Maybe.chain`](../modules/_maybe_.html#chain) */
|
||
chain<U>(this: Maybe<T>, chainFn: (t: T) => Maybe<U>): Maybe<U>;
|
||
/** Method variant for [`Maybe.flatMap`](../modules/_maybe_.html#flatmap) */
|
||
flatMap<U>(this: Maybe<T>, flatMapFn: (t: T) => Maybe<U>): Maybe<U>;
|
||
/** Method variant for [`Maybe.unwrap`](../modules/_maybe_.html#unwrap) */
|
||
unsafelyUnwrap(): T | never;
|
||
/** Method variant for [`Maybe.unwrapOrElse`](../modules/_maybe_.html#unwraporelse) */
|
||
unwrapOrElse<U>(this: Maybe<T>, elseFn: () => U): T | U;
|
||
/** Method variant for [`Maybe.toOkOrErr`](../modules/_maybe_.html#tookorerr) */
|
||
toOkOrErr<E>(this: Maybe<T>, error: E): Result<T, E>;
|
||
/** Method variant for [`Maybe.toOkOrElseErr`](../modules/_maybe_.html#tookorelseerr) */
|
||
toOkOrElseErr<E>(this: Maybe<T>, elseFn: () => E): Result<T, E>;
|
||
/** Method variant for [`Maybe.toString`](../modules/_maybe_.html#tostring) */
|
||
toString(this: Maybe<T>): string;
|
||
/** Method variant for [`Maybe.toJSON`](../modules/_maybe_.html#toJSON) */
|
||
toJSON(this: Maybe<T>): MaybeJSON<T>;
|
||
/** Method variant for [`Maybe.equals`](../modules/_maybe_.html#equals) */
|
||
equals(this: Maybe<T>, comparison: Maybe<T>): boolean;
|
||
/** Method variant for [`Maybe.ap`](../modules/_maybe_.html#ap) */
|
||
ap<U>(this: Maybe<(val: T) => U>, val: Maybe<T>): Maybe<U>;
|
||
/**
|
||
Method variant for [`Maybe.get`](../modules/_maybe_.html#prop)
|
||
|
||
If you have a `Maybe` of an object type, you can do `thatMaybe.get('a key')`
|
||
to look up the next layer down in the object.
|
||
|
||
```ts
|
||
type DeepOptionalType = {
|
||
something?: {
|
||
with?: {
|
||
deeperKeys?: string;
|
||
}
|
||
}
|
||
};
|
||
|
||
const fullySet: DeepType = {
|
||
something: {
|
||
with: {
|
||
deeperKeys: 'like this'
|
||
}
|
||
}
|
||
};
|
||
|
||
const deepJust = Maybe.of(fullySet)
|
||
.get('something')
|
||
.get('with')
|
||
.get('deeperKeys');
|
||
|
||
console.log(deepJust); // Just('like this');
|
||
|
||
const partiallyUnset: DeepType = { something: { } };
|
||
|
||
const deepEmpty = Maybe.of(partiallyUnset)
|
||
.get('something')
|
||
.get('with')
|
||
.get('deeperKeys');
|
||
|
||
console.log(deepEmpty); // Nothing
|
||
```
|
||
*/
|
||
get<K extends keyof T>(this: Maybe<T>, key: K): Maybe<NonNullable<T[K]>>;
|
||
}
|
||
/**
|
||
A `Just` instance is the *present* variant instance of the
|
||
[`Maybe`](../modules/_maybe_.html#maybe) type, representing the presence of a
|
||
value which may be absent. For a full discussion, see [the module
|
||
docs](../modules/_maybe_.html).
|
||
|
||
@typeparam T The type wrapped in this `Just` variant of `Maybe`.
|
||
*/
|
||
export declare class Just<T> implements MaybeShape<T> {
|
||
/**
|
||
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 Maybe, { Just } from 'true-myth/maybe';
|
||
|
||
function getLengths(maybeStrings: Array<Maybe<string>>): Array<number> {
|
||
return maybeStrings
|
||
.filter(Maybe.isJust)
|
||
.map(Just.unwrap)
|
||
.map(s => s.length);
|
||
}
|
||
```
|
||
*/
|
||
static unwrap<J>(theJust: Just<J>): J;
|
||
/** `Just` is always [`Variant.Just`](../enums/_maybe_.variant#just). */
|
||
readonly variant: Variant.Just;
|
||
/** The wrapped value. */
|
||
readonly value: T;
|
||
/**
|
||
Create an instance of `Maybe.Just` with `new`.
|
||
|
||
@note While you *may* create the `Just` type via normal JavaScript
|
||
class construction, it is not recommended for the functional style for
|
||
which the library is intended. Instead, use [`Maybe.of`] (for the general
|
||
case) or [`Maybe.just`] for this specific case.
|
||
|
||
[`Maybe.of`]: ../modules/_maybe_.html#of
|
||
[`Maybe.just`]: ../modules/_maybe_.html#just
|
||
|
||
```ts
|
||
// Avoid:
|
||
const aString = new Maybe.Just('characters');
|
||
|
||
// Prefer:
|
||
const aString = Maybe.just('characters);
|
||
```
|
||
|
||
@param value
|
||
The value to wrap in a `Maybe.Just`.
|
||
|
||
`null` and `undefined` are allowed by the type signature so that the
|
||
constructor may `throw` on those rather than constructing a type like
|
||
`Maybe<undefined>`.
|
||
|
||
@throws If you pass `null` or `undefined`.
|
||
*/
|
||
constructor(value?: T | null);
|
||
/** Method variant for [`Maybe.isJust`](../modules/_maybe_.html#isjust) */
|
||
isJust(this: Maybe<T>): this is Just<T>;
|
||
/** Method variant for [`Maybe.isNothing`](../modules/_maybe_.html#isnothing) */
|
||
isNothing(this: Maybe<T>): this is Nothing<T>;
|
||
/** Method variant for [`Maybe.map`](../modules/_maybe_.html#map) */
|
||
map<U>(this: Maybe<T>, mapFn: (t: T) => U): Maybe<U>;
|
||
/** Method variant for [`Maybe.mapOr`](../modules/_maybe_.html#mapor) */
|
||
mapOr<U>(this: Maybe<T>, orU: U, mapFn: (t: T) => U): U;
|
||
/** Method variant for [`Maybe.mapOrElse`](../modules/_maybe_.html#maporelse) */
|
||
mapOrElse<U>(this: Maybe<T>, orElseFn: () => U, mapFn: (t: T) => U): U;
|
||
/** Method variant for [`Maybe.match`](../modules/_maybe_.html#match) */
|
||
match<U>(this: Maybe<T>, matcher: Matcher<T, U>): U;
|
||
/** Method variant for [`Maybe.or`](../modules/_maybe_.html#or) */
|
||
or(this: Maybe<T>, mOr: Maybe<T>): Maybe<T>;
|
||
/** Method variant for [`Maybe.orElse`](../modules/_maybe_.html#orelse) */
|
||
orElse(this: Maybe<T>, orElseFn: () => Maybe<T>): Maybe<T>;
|
||
/** Method variant for [`Maybe.and`](../modules/_maybe_.html#and) */
|
||
and<U>(this: Maybe<T>, mAnd: Maybe<U>): Maybe<U>;
|
||
/** Method variant for [`Maybe.andThen`](../modules/_maybe_.html#andthen) */
|
||
andThen<U>(this: Maybe<T>, andThenFn: (t: T) => Maybe<U>): Maybe<U>;
|
||
/** Method variant for [`Maybe.chain`](../modules/_maybe_.html#chain) */
|
||
chain<U>(this: Maybe<T>, chainFn: (t: T) => Maybe<U>): Maybe<U>;
|
||
/** Method variant for [`Maybe.flatMap`](../modules/_maybe_.html#flatmap) */
|
||
flatMap<U>(this: Maybe<T>, flatMapFn: (t: T) => Maybe<U>): Maybe<U>;
|
||
/** Method variant for [`Maybe.unsafelyUnwrap`](../modules/_maybe_.html#unsafelyunwrap) */
|
||
unsafelyUnwrap(): T;
|
||
/** Method variant for [`Maybe.unwrapOr`](../modules/_maybe_.html#unwrapor) */
|
||
unwrapOr<U>(this: Maybe<T>, defaultValue: U): T | U;
|
||
/** Method variant for [`Maybe.unwrapOrElse`](../modules/_maybe_.html#unwraporelse) */
|
||
unwrapOrElse<U>(this: Maybe<T>, elseFn: () => U): T | U;
|
||
/** Method variant for [`Maybe.toOkOrErr`](../modules/_maybe_.html#tookorerr) */
|
||
toOkOrErr<E>(this: Maybe<T>, error: E): Result<T, E>;
|
||
/** Method variant for [`Maybe.toOkOrElseErr`](../modules/_maybe_.html#tookorelseerr) */
|
||
toOkOrElseErr<E>(this: Maybe<T>, elseFn: () => E): Result<T, E>;
|
||
/** Method variant for [`Maybe.toString`](../modules/_maybe_.html#tostring) */
|
||
toString(this: Maybe<T>): string;
|
||
/** Method variant for [`Maybe.toJSON`](../modules/_maybe_.html#toJSON) */
|
||
toJSON(this: Maybe<T>): MaybeJSON<T>;
|
||
/** Method variant for [`Maybe.equals`](../modules/_maybe_.html#equals) */
|
||
equals(this: Maybe<T>, comparison: Maybe<T>): boolean;
|
||
/** Method variant for [`Maybe.ap`](../modules/_maybe_.html#ap) */
|
||
ap<A, B>(this: Maybe<(val: A) => B>, val: Maybe<A>): Maybe<B>;
|
||
/**
|
||
Method variant for [`Maybe.get`](../modules/_maybe_.html#prop)
|
||
|
||
If you have a `Maybe` of an object type, you can do `thatMaybe.get('a key')`
|
||
to look up the next layer down in the object.
|
||
|
||
```ts
|
||
type DeepOptionalType = {
|
||
something?: {
|
||
with?: {
|
||
deeperKeys?: string;
|
||
}
|
||
}
|
||
};
|
||
|
||
const fullySet: DeepType = {
|
||
something: {
|
||
with: {
|
||
deeperKeys: 'like this'
|
||
}
|
||
}
|
||
};
|
||
|
||
const deepJust = Maybe.of(fullySet)
|
||
.get('something')
|
||
.get('with')
|
||
.get('deeperKeys');
|
||
|
||
console.log(deepJust); // Just('like this');
|
||
|
||
const partiallyUnset: DeepType = { something: { } };
|
||
|
||
const deepEmpty = Maybe.of(partiallyUnset)
|
||
.get('something')
|
||
.get('with')
|
||
.get('deeperKeys');
|
||
|
||
console.log(deepEmpty); // Nothing
|
||
```
|
||
*/
|
||
get<K extends keyof T>(this: Maybe<T>, key: K): Maybe<NonNullable<T[K]>>;
|
||
}
|
||
/**
|
||
A `Nothing` instance is the *absent* variant instance of the
|
||
[`Maybe`](../modules/_maybe_.html#maybe) type, representing the presence of a
|
||
value which may be absent. For a full discussion, see [the module
|
||
docs](../modules/_maybe_.html).
|
||
|
||
@typeparam T The type which would be wrapped in a `Just` variant of `Maybe`.
|
||
*/
|
||
export declare class Nothing<T> implements MaybeShape<T> {
|
||
/** `Nothing` is always [`Variant.Nothing`](../enums/_maybe_.variant#nothing). */
|
||
readonly variant: Variant.Nothing;
|
||
/**
|
||
Create an instance of `Maybe.Nothing` with `new`.
|
||
|
||
@note While you *may* create the `Nothing` type via normal JavaScript
|
||
class construction, it is not recommended for the functional style for
|
||
which the library is intended. Instead, use [`Maybe.of`] (for the general
|
||
case) or [`Maybe.nothing`] for this specific case.
|
||
|
||
[`Maybe.of`]: ../modules/_maybe_.html#of
|
||
[`Maybe.nothing`]: ../modules/_maybe_.html#nothing
|
||
|
||
```ts
|
||
// Avoid:
|
||
const aNothing = new Maybe.Err();
|
||
|
||
// Prefer:
|
||
const aNothing = Maybe.nothing();
|
||
```
|
||
|
||
`null` and `undefined` are allowed so that you may explicitly construct the
|
||
`Err` type with a known `null` or `undefined` value. (This maybe helpful
|
||
primarily when transitioning a codebase to the use of `Maybe`.)
|
||
|
||
@throws If you pass `null` or `undefined`.
|
||
*/
|
||
constructor(_?: null);
|
||
/** Method variant for [`Maybe.isJust`](../modules/_maybe_.html#isjust) */
|
||
isJust(this: Maybe<T>): this is Just<T>;
|
||
/** Method variant for [`Maybe.isNothing`](../modules/_maybe_.html#isnothing) */
|
||
isNothing(this: Maybe<T>): this is Nothing<T>;
|
||
/** Method variant for [`Maybe.map`](../modules/_maybe_.html#map) */
|
||
map<U>(this: Maybe<T>, mapFn: (t: T) => U): Maybe<U>;
|
||
/** Method variant for [`Maybe.mapOr`](../modules/_maybe_.html#mapor) */
|
||
mapOr<U>(this: Maybe<T>, orU: U, mapFn: (t: T) => U): U;
|
||
/** Method variant for [`Maybe.mapOrElse`](../modules/_maybe_.html#maporelse) */
|
||
mapOrElse<U>(this: Maybe<T>, orElseFn: () => U, mapFn: (t: T) => U): U;
|
||
/** Method variant for [`Maybe.match`](../modules/_maybe_.html#match) */
|
||
match<U>(this: Maybe<T>, matcher: Matcher<T, U>): U;
|
||
/** Method variant for [`Maybe.or`](../modules/_maybe_.html#or) */
|
||
or(this: Maybe<T>, mOr: Maybe<T>): Maybe<T>;
|
||
/** Method variant for [`Maybe.orElse`](../modules/_maybe_.html#orelse) */
|
||
orElse(this: Maybe<T>, orElseFn: () => Maybe<T>): Maybe<T>;
|
||
/** Method variant for [`Maybe.and`](../modules/_maybe_.html#and) */
|
||
and<U>(this: Maybe<T>, mAnd: Maybe<U>): Maybe<U>;
|
||
/** Method variant for [`Maybe.andThen`](../modules/_maybe_.html#andthen) */
|
||
andThen<U>(this: Maybe<T>, andThenFn: (t: T) => Maybe<U>): Maybe<U>;
|
||
/** Method variant for [`Maybe.chain`](../modules/_maybe_.html#chain) */
|
||
chain<U>(this: Maybe<T>, chainFn: (t: T) => Maybe<U>): Maybe<U>;
|
||
/** Method variant for [`Maybe.flatMap`](../modules/_maybe_.html#flatmap) */
|
||
flatMap<U>(this: Maybe<T>, flatMapFn: (t: T) => Maybe<U>): Maybe<U>;
|
||
/** Method variant for [`Maybe.unsafelyUnwrap`](../modules/_maybe_.html#unsafelyunwrap) */
|
||
unsafelyUnwrap(): never;
|
||
/** Method variant for [`Maybe.unwrapOr`](../modules/_maybe_.html#unwrapor) */
|
||
unwrapOr<U>(this: Maybe<T>, defaultValue: U): T | U;
|
||
/** Method variant for [`Maybe.unwrapOrElse`](../modules/_maybe_.html#unwraporelse) */
|
||
unwrapOrElse<U>(this: Maybe<T>, elseFn: () => U): T | U;
|
||
/** Method variant for [`Maybe.toOkOrErr`](../modules/_maybe_.html#tookorerr) */
|
||
toOkOrErr<E>(this: Maybe<T>, error: E): Result<T, E>;
|
||
/** Method variant for [`Maybe.toOkOrElseErr`](../modules/_maybe_.html#tookorelseerr) */
|
||
toOkOrElseErr<E>(this: Maybe<T>, elseFn: () => E): Result<T, E>;
|
||
/** Method variant for [`Maybe.toString`](../modules/_maybe_.html#tostring) */
|
||
toString(this: Maybe<T>): string;
|
||
/** Method variant for [`Maybe.toJSON`](../modules/_maybe_.html#toJSON) */
|
||
toJSON(this: Maybe<T>): MaybeJSON<T>;
|
||
/** Method variant for [`Maybe.equals`](../modules/_maybe_.html#equals) */
|
||
equals(this: Maybe<T>, comparison: Maybe<T>): boolean;
|
||
/** Method variant for [`Maybe.ap`](../modules/_maybe_.html#ap) */
|
||
ap<A, B>(this: Maybe<(val: A) => B>, val: Maybe<A>): Maybe<B>;
|
||
/**
|
||
Method variant for [`Maybe.get`](../modules/_maybe_.html#prop)
|
||
|
||
If you have a `Maybe` of an object type, you can do `thatMaybe.get('a key')`
|
||
to look up the next layer down in the object.
|
||
|
||
```ts
|
||
type DeepOptionalType = {
|
||
something?: {
|
||
with?: {
|
||
deeperKeys?: string;
|
||
}
|
||
}
|
||
};
|
||
|
||
const fullySet: DeepType = {
|
||
something: {
|
||
with: {
|
||
deeperKeys: 'like this'
|
||
}
|
||
}
|
||
};
|
||
|
||
const deepJust = Maybe.of(fullySet)
|
||
.get('something')
|
||
.get('with')
|
||
.get('deeperKeys');
|
||
|
||
console.log(deepJust); // Just('like this');
|
||
|
||
const partiallyUnset: DeepType = { something: { } };
|
||
|
||
const deepEmpty = Maybe.of(partiallyUnset)
|
||
.get('something')
|
||
.get('with')
|
||
.get('deeperKeys');
|
||
|
||
console.log(deepEmpty); // Nothing
|
||
```
|
||
*/
|
||
get<K extends keyof T>(this: Maybe<T>, key: K): Maybe<NonNullable<T[K]>>;
|
||
}
|
||
/**
|
||
Is this result a `Just` instance?
|
||
|
||
@typeparam T The type of the wrapped value.
|
||
@param maybe The `Maybe` instance to check.
|
||
@returns `true` if `maybe` is `Just`, `false` otherwise. In TypeScript,
|
||
also narrows the type from `Maybe<T>` to `Just<T>`.
|
||
*/
|
||
export declare function isJust<T>(maybe: Maybe<T>): maybe is Just<T>;
|
||
/**
|
||
Is this result a `Nothing` instance?
|
||
|
||
@typeparam T The type of the wrapped value.
|
||
@param maybe The `Maybe` instance to check.
|
||
@returns `true` if `maybe` is `nothing`, `false` otherwise. In TypeScript,
|
||
also narrows the type from `Maybe<T>` to `Nothing<T>`.
|
||
*/
|
||
export declare function isNothing<T>(maybe: Maybe<T>): maybe is Nothing<T>;
|
||
/**
|
||
Create an instance of `Maybe.Just`.
|
||
|
||
`null` and `undefined` are allowed by the type signature so that the
|
||
function may `throw` on those rather than constructing a type like
|
||
`Maybe<undefined>`.
|
||
|
||
@typeparam T The type of the item contained in the `Maybe`.
|
||
@param value The value to wrap in a `Maybe.Just`.
|
||
@returns An instance of `Maybe.Just<T>`.
|
||
@throws If you pass `null` or `undefined`.
|
||
*/
|
||
export declare function just<T = unknown>(value?: T | null): Maybe<T>;
|
||
/**
|
||
Create an instance of `Maybe.Nothing`.
|
||
|
||
If you want to create an instance with a specific type, e.g. for use in a
|
||
function which expects a `Maybe<T>` where the `<T>` is known but you have no
|
||
value to give it, you can use a type parameter:
|
||
|
||
```ts
|
||
const notString = Maybe.nothing<string>();
|
||
```
|
||
|
||
@typeparam T The type of the item contained in the `Maybe`.
|
||
@returns An instance of `Maybe.Nothing<T>`.
|
||
*/
|
||
export declare function nothing<T = unknown>(_?: null): Maybe<T>;
|
||
/**
|
||
Create a `Maybe` from any value.
|
||
|
||
To specify that the result should be interpreted as a specific type, you may
|
||
invoke `Maybe.of` with an explicit type parameter:
|
||
|
||
```ts
|
||
const foo = Maybe.of<string>(null);
|
||
```
|
||
|
||
This is usually only important in two cases:
|
||
|
||
1. If you are intentionally constructing a `Nothing` from a known `null` or
|
||
undefined value *which is untyped*.
|
||
2. If you are specifying that the type is more general than the value passed
|
||
(since TypeScript can define types as literals).
|
||
|
||
@typeparam T The type of the item contained in the `Maybe`.
|
||
@param value The value to wrap in a `Maybe`. If it is `undefined` or `null`,
|
||
the result will be `Nothing`; otherwise it will be the type of
|
||
the value passed.
|
||
*/
|
||
export declare function of<T>(value?: T | null): Maybe<T>;
|
||
/**
|
||
Alias for [`of`](#of), convenient for a standalone import:
|
||
|
||
```ts
|
||
import { maybe } from 'true-myth/maybe';
|
||
|
||
interface Dict<T> {
|
||
[key: string]: T | null | undefined;
|
||
}
|
||
|
||
interface StrictDict<T> {
|
||
[key: string]: Maybe<T>;
|
||
}
|
||
|
||
function wrapNullables<T>(dict: Dict<T>): StrictDict<T> {
|
||
return Object.keys(dict).reduce((strictDict, key) => {
|
||
strictDict[key] = maybe(dict[key]);
|
||
return strictDict;
|
||
}, {} as StrictDict<T>);
|
||
}
|
||
```
|
||
*/
|
||
export declare const maybe: typeof of;
|
||
/** Alias for [`of`](#of), primarily for compatibility with Folktale. */
|
||
export declare const fromNullable: typeof of;
|
||
/**
|
||
Map over a `Maybe` instance: apply the function to the wrapped value if the
|
||
instance is `Just`, and return `Nothing` if the instance is `Nothing`.
|
||
|
||
`Maybe.map` works a lot like `Array.prototype.map`: `Maybe` and `Array` are
|
||
both *containers* for other things. If you have no items in an array of
|
||
numbers named `foo` and call `foo.map(x => x + 1)`, you'll still just 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]`).
|
||
|
||
That's exactly what's happening with `Maybe.map`. If the container is *empty*
|
||
– the `Nothing` variant – you just get back an empty container. If the
|
||
container has something in it – the `Just` variant – you get back a container
|
||
with the item inside transformed.
|
||
|
||
(So... why not just use an array? The biggest reason is that an array can be
|
||
any length. With a `Maybe`, we're capturing the idea of "something or
|
||
nothing" rather than "0 to n" items. And this lets us implement a whole set
|
||
of *other* interfaces, like those in this module.)
|
||
|
||
#### Examples
|
||
|
||
```ts
|
||
const length = (s: string) => s.length;
|
||
|
||
const justAString = Maybe.just('string');
|
||
const justTheStringLength = map(length, justAString);
|
||
console.log(justTheStringLength.toString()); // Just(6)
|
||
|
||
const notAString = Maybe.nothing<string>();
|
||
const notAStringLength = map(length, notAString);
|
||
console.log(notAStringLength.toString()); // "Nothing"
|
||
```
|
||
|
||
@typeparam T The type of the wrapped value.
|
||
@typeparam U The type of the wrapped value of the returned `Maybe`.
|
||
@param mapFn The function to apply the value to if `Maybe` is `Just`.
|
||
@param maybe The `Maybe` instance to map over.
|
||
@returns A new `Maybe` with the result of applying `mapFn` to the value
|
||
in a `Just`, or `Nothing` if `maybe` is `Nothing`.
|
||
*/
|
||
export declare function map<T, U>(mapFn: (t: T) => U): (maybe: Maybe<T>) => Maybe<U>;
|
||
export declare function map<T, U>(mapFn: (t: T) => U, maybe: Maybe<T>): Maybe<U>;
|
||
/**
|
||
Map over a `Maybe` instance and get out the value if `maybe` is a `Just`, or
|
||
return a default value if `maybe` is a `Nothing`.
|
||
|
||
#### Examples
|
||
|
||
```ts
|
||
const length = (s: string) => s.length;
|
||
|
||
const justAString = Maybe.just('string');
|
||
const theStringLength = mapOr(0, length, justAString);
|
||
console.log(theStringLength); // 6
|
||
|
||
const notAString = Maybe.nothing<string>();
|
||
const notAStringLength = mapOr(0, length, notAString)
|
||
console.log(notAStringLength); // 0
|
||
```
|
||
|
||
@typeparam T The type of the wrapped value.
|
||
@typeparam U The type of the wrapped value of the returned `Maybe`.
|
||
@param orU The default value to use if `maybe` is `Nothing`
|
||
@param mapFn The function to apply the value to if `Maybe` is `Just`
|
||
@param maybe The `Maybe` instance to map over.
|
||
*/
|
||
export declare function mapOr<T, U>(orU: U, mapFn: (t: T) => U, maybe: Maybe<T>): U;
|
||
export declare function mapOr<T, U>(orU: U, mapFn: (t: T) => U): (maybe: Maybe<T>) => U;
|
||
export declare function mapOr<T, U>(orU: U): (mapFn: (t: T) => U) => (maybe: Maybe<T>) => U;
|
||
/**
|
||
Map over a `Maybe` instance and get out the value if `maybe` is a `Just`,
|
||
or use a function to construct a default value if `maybe` is `Nothing`.
|
||
|
||
#### Examples
|
||
|
||
```ts
|
||
const length = (s: string) => s.length;
|
||
const getDefault = () => 0;
|
||
|
||
const justAString = Maybe.just('string');
|
||
const theStringLength = mapOrElse(getDefault, length, justAString);
|
||
console.log(theStringLength); // 6
|
||
|
||
const notAString = Maybe.nothing<string>();
|
||
const notAStringLength = mapOrElse(getDefault, length, notAString)
|
||
console.log(notAStringLength); // 0
|
||
```
|
||
|
||
@typeparam T The type of the wrapped value.
|
||
@typeparam U The type of the wrapped value of the returned `Maybe`.
|
||
@param orElseFn The function to apply if `maybe` is `Nothing`.
|
||
@param mapFn The function to apply to the wrapped value if `maybe` is `Just`
|
||
@param maybe The `Maybe` instance to map over.
|
||
*/
|
||
export declare function mapOrElse<T, U>(orElseFn: () => U, mapFn: (t: T) => U, maybe: Maybe<T>): U;
|
||
export declare function mapOrElse<T, U>(orElseFn: () => U, mapFn: (t: T) => U): (maybe: Maybe<T>) => U;
|
||
export declare function mapOrElse<T, U>(orElseFn: () => U): (mapFn: (t: T) => U) => (maybe: Maybe<T>) => U;
|
||
/**
|
||
You can think of this like a short-circuiting logical "and" operation on a
|
||
`Maybe` type. If `maybe` is `Just`, then the result is the `andMaybe`. If
|
||
`maybe` is `Nothing`, the result is `Nothing`.
|
||
|
||
This is useful when you have another `Maybe` value you want to provide if and
|
||
*only if* you have a `Just` – that is, when you need to make sure that if you
|
||
`Nothing`, whatever else you're handing a `Maybe` to *also* gets a `Nothing`.
|
||
|
||
Notice that, unlike in [`map`](#map) or its variants, the original `maybe` is
|
||
not involved in constructing the new `Maybe`.
|
||
|
||
#### Examples
|
||
|
||
```ts
|
||
import Maybe from 'true-myth/maybe';
|
||
|
||
const justA = Maybe.just('A');
|
||
const justB = Maybe.just('B');
|
||
const nothing: Maybe<number> = nothing();
|
||
|
||
console.log(Maybe.and(justB, justA).toString()); // Just(B)
|
||
console.log(Maybe.and(justB, nothing).toString()); // Nothing
|
||
console.log(Maybe.and(nothing, justA).toString()); // Nothing
|
||
console.log(Maybe.and(nothing, nothing).toString()); // Nothing
|
||
```
|
||
|
||
@typeparam T The type of the initial wrapped value.
|
||
@typeparam U The type of the wrapped value of the returned `Maybe`.
|
||
@param andMaybe The `Maybe` instance to return if `maybe` is `Just`
|
||
@param maybe The `Maybe` instance to check.
|
||
@return `Nothing` if the original `maybe` is `Nothing`, or `andMaybe`
|
||
if the original `maybe` is `Just`.
|
||
*/
|
||
export declare function and<T, U>(andMaybe: Maybe<U>, maybe: Maybe<T>): Maybe<U>;
|
||
export declare function and<T, U>(andMaybe: Maybe<U>): (maybe: Maybe<T>) => Maybe<U>;
|
||
/**
|
||
Apply a function to the wrapped value if `Just` and return a new `Just`
|
||
containing the resulting value; or return `Nothing` if `Nothing`.
|
||
|
||
This differs from `map` in that `thenFn` returns another `Maybe`. You can use
|
||
`andThen` to combine two functions which *both* create a `Maybe` from an
|
||
unwrapped type.
|
||
|
||
You may find the `.then` method on an ES6 `Promise` helpful for b:
|
||
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 `Maybe.andThen`
|
||
will not unwrap nested `Maybe`s.
|
||
|
||
This is also commonly known as (and therefore aliased as) [`flatMap`][flatMap]
|
||
or [`chain`][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
|
||
|
||
#### Example
|
||
|
||
(This is a somewhat contrived example, but it serves to show the way the
|
||
function behaves.)
|
||
|
||
```ts
|
||
import Maybe from 'true-myth/maybe';
|
||
|
||
// string -> Maybe<number>
|
||
const toMaybeLength = (s: string): Maybe<number> => Maybe.of(s.length);
|
||
|
||
// Maybe<string>
|
||
const aMaybeString = Maybe.of('Hello, there!');
|
||
|
||
// Maybe<number>
|
||
const resultingLength = Maybe.andThen(toMaybeLength, aMaybeString);
|
||
console.log(Maybe.toString(resultingLength)); // 13
|
||
```
|
||
|
||
Note that the result is not `(Just(13))`, but `13`!
|
||
|
||
@typeparam T The type of the wrapped value.
|
||
@typeparam U The type of the wrapped value in the resulting `Maybe`.
|
||
@param thenFn The function to apply to the wrapped `T` if `maybe` is `Just`.
|
||
@param maybe The `Maybe` to evaluate and possibly apply a function to the
|
||
contents of.
|
||
@returns The result of the `thenFn` (a new `Maybe`) if `maybe` is a
|
||
`Just`, otherwise `Nothing` if `maybe` is a `Nothing`.
|
||
*/
|
||
export declare function andThen<T, U>(thenFn: (t: T) => Maybe<U>, maybe: Maybe<T>): Maybe<U>;
|
||
export declare function andThen<T, U>(thenFn: (t: T) => Maybe<U>): (maybe: Maybe<T>) => Maybe<U>;
|
||
/** Alias for [`andThen`](#andthen). */
|
||
export declare const chain: typeof andThen;
|
||
/** Alias for [`andThen`](#andthen). */
|
||
export declare const flatMap: typeof andThen;
|
||
/** Alias for [`andThen`](#andthen). */
|
||
export declare const bind: typeof andThen;
|
||
/**
|
||
Provide a fallback for a given `Maybe`. Behaves like a logical `or`: if the
|
||
`maybe` value is a `Just`, returns that `maybe`; otherwise, returns the
|
||
`defaultMaybe` value.
|
||
|
||
This is useful when you want to make sure that something which takes a
|
||
`Maybe` always ends up getting a `Just` variant, by supplying a default value
|
||
for the case that you currently have a nothing.
|
||
|
||
```ts
|
||
import Maybe from 'true-utils/maybe';
|
||
|
||
const justA = Maybe.just("a");
|
||
const justB = Maybe.just("b");
|
||
const aNothing: Maybe<string> = nothing();
|
||
|
||
console.log(Maybe.or(justB, justA).toString()); // Just(A)
|
||
console.log(Maybe.or(aNothing, justA).toString()); // Just(A)
|
||
console.log(Maybe.or(justB, aNothing).toString()); // Just(B)
|
||
console.log(Maybe.or(aNothing, aNothing).toString()); // Nothing
|
||
```
|
||
|
||
@typeparam T The type of the wrapped value.
|
||
@param defaultMaybe The `Maybe` to use if `maybe` is a `Nothing`.
|
||
@param maybe The `Maybe` instance to evaluate.
|
||
@returns `maybe` if it is a `Just`, otherwise `defaultMaybe`.
|
||
*/
|
||
export declare function or<T>(defaultMaybe: Maybe<T>, maybe: Maybe<T>): Maybe<T>;
|
||
export declare function or<T>(defaultMaybe: Maybe<T>): (maybe: Maybe<T>) => Maybe<T>;
|
||
/**
|
||
Like `or`, but using a function to construct the alternative `Maybe`.
|
||
|
||
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 `Maybe<T>`.
|
||
|
||
Useful for transforming empty scenarios based on values in context.
|
||
|
||
@typeparam T The type of the wrapped value.
|
||
@param elseFn The function to apply if `maybe` is `Nothing`
|
||
@param maybe The `maybe` to use if it is `Just`.
|
||
@returns The `maybe` if it is `Just`, or the `Maybe` returned by
|
||
`elseFn` if the `maybe` is `Nothing`.
|
||
*/
|
||
export declare function orElse<T>(elseFn: () => Maybe<T>, maybe: Maybe<T>): Maybe<T>;
|
||
export declare function orElse<T>(elseFn: () => Maybe<T>): (maybe: Maybe<T>) => Maybe<T>;
|
||
/**
|
||
Get the value out of the `Maybe`.
|
||
|
||
Returns the content of a `Just`, but **throws if the `Maybe` is `Nothing`**.
|
||
Prefer to use [`unwrapOr`](#unwrapor) or [`unwrapOrElse`](#unwraporelse).
|
||
|
||
@typeparam T The type of the wrapped value.
|
||
@param maybe The value to unwrap
|
||
@returns The unwrapped value if the `Maybe` instance is `Just`.
|
||
@throws If the `maybe` is `Nothing`.
|
||
*/
|
||
export declare function unsafelyUnwrap<T>(maybe: Maybe<T>): T;
|
||
/** Alias for [`unsafelyUnwrap`](#unsafelyunwrap) */
|
||
export declare const unsafelyGet: typeof unsafelyUnwrap;
|
||
/** Alias for [`unsafelyUnwrap`](#unsafelyunwrap) */
|
||
export declare const unsafeGet: typeof unsafelyUnwrap;
|
||
/**
|
||
Safely get the value out of a `Maybe`.
|
||
|
||
Returns the content of a `Just` or `defaultValue` if `Nothing`. This is the
|
||
recommended way to get a value out of a `Maybe` most of the time.
|
||
|
||
```ts
|
||
import Maybe from 'true-myth/maybe';
|
||
|
||
const notAString = Maybe.nothing<string>();
|
||
const isAString = Maybe.just('look ma! some characters!');
|
||
|
||
console.log(Maybe.unwrapOr('<empty>', notAString)); // "<empty>"
|
||
console.log(Maybe.unwrapOr('<empty>', isAString)); // "look ma! some characters!"
|
||
```
|
||
|
||
@typeparam T The type of the wrapped value.
|
||
@param defaultValue The value to return if `maybe` is a `Nothing`.
|
||
@param maybe The `Maybe` instance to unwrap if it is a `Just`.
|
||
@returns The content of `maybe` if it is a `Just`, otherwise
|
||
`defaultValue`.
|
||
*/
|
||
export declare function unwrapOr<T, U>(defaultValue: U, maybe: Maybe<T>): T | U;
|
||
export declare function unwrapOr<T, U>(defaultValue: U): (maybe: Maybe<T>) => T | U;
|
||
/** Alias for [`unwrapOr`](#unwrapor) */
|
||
export declare const getOr: typeof unwrapOr;
|
||
/**
|
||
Safely get the value out of a [`Maybe`](#maybe) by returning the wrapped
|
||
value if it is `Just`, or by applying `orElseFn` if it is `Nothing`.
|
||
|
||
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 Maybe from 'true-myth/maybe';
|
||
|
||
// You can imagine that someOtherValue might be dynamic.
|
||
const someOtherValue = 99;
|
||
const handleNothing = () => someOtherValue;
|
||
|
||
const aJust = Maybe.just(42);
|
||
console.log(Maybe.unwrapOrElse(handleNothing, aJust)); // 42
|
||
|
||
const aNothing = nothing<number>();
|
||
console.log(Maybe.unwrapOrElse(handleNothing, aNothing)); // 99
|
||
```
|
||
|
||
@typeparam T The wrapped value.
|
||
@param orElseFn A function used to generate a valid value if `maybe` is a
|
||
`Nothing`.
|
||
@param maybe The `Maybe` instance to unwrap if it is a `Just`
|
||
@returns Either the content of `maybe` or the value returned from
|
||
`orElseFn`.
|
||
*/
|
||
export declare function unwrapOrElse<T, U>(orElseFn: () => U, maybe: Maybe<T>): T | U;
|
||
export declare function unwrapOrElse<T, U>(orElseFn: () => U): (maybe: Maybe<T>) => T | U;
|
||
/** Alias for [`unwrapOrElse`](#unwraporelse) */
|
||
export declare const getOrElse: typeof unwrapOrElse;
|
||
/**
|
||
Transform the [`Maybe`](#maybe) into a
|
||
[`Result`](../modules/_result_.html#result), using the wrapped value as the
|
||
`Ok` value if `Just`; otherwise using the supplied `error` value for `Err`.
|
||
|
||
@typeparam T The wrapped value.
|
||
@typeparam E The error type to in the `Result`.
|
||
@param error The error value to use if the `Maybe` is `Nothing`.
|
||
@param maybe The `Maybe` instance to convert.
|
||
@returns A `Result` containing the value wrapped in `maybe` in an `Ok`,
|
||
or `error` in an `Err`.
|
||
*/
|
||
export declare function toOkOrErr<T, E>(error: E, maybe: Maybe<T>): Result<T, E>;
|
||
export declare function toOkOrErr<T, E>(error: E): (maybe: Maybe<T>) => Result<T, E>;
|
||
/**
|
||
Transform the [`Maybe`](#maybe) into a
|
||
[`Result`](../modules/_result_.html#result), using the wrapped value as the
|
||
`Ok` value if `Just`; otherwise using `elseFn` to generate `Err`.
|
||
|
||
@typeparam T The wrapped value.
|
||
@typeparam E The error type to in the `Result`.
|
||
@param elseFn The function which generates an error of type `E`.
|
||
@param maybe The `Maybe` instance to convert.
|
||
@returns A `Result` containing the value wrapped in `maybe` in an `Ok`,
|
||
or the value generated by `elseFn` in an `Err`.
|
||
*/
|
||
export declare function toOkOrElseErr<T, E>(elseFn: () => E, maybe: Maybe<T>): Result<T, E>;
|
||
export declare function toOkOrElseErr<T, E>(elseFn: () => E): (maybe: Maybe<T>) => Result<T, E>;
|
||
/**
|
||
Construct a `Maybe<T>` from a `Result<T, E>`.
|
||
|
||
If the `Result` is an `Ok`, wrap its value in `Just`. If the `Result` is an
|
||
`Err`, throw away the wrapped `E` and transform to a `Nothing`.
|
||
|
||
@typeparam T The type of the value wrapped in a `Result.Ok` and in the `Just`
|
||
of the resulting `Maybe`.
|
||
@param result The `Result` to construct a `Maybe` from.
|
||
@returns `Just` if `result` was `Ok` or `Nothing` if it was `Err`.
|
||
*/
|
||
export declare function fromResult<T>(result: Result<T, any>): Maybe<T>;
|
||
/**
|
||
Create a `String` representation of a `Maybe` instance.
|
||
|
||
A `Just` instance will be printed as `Just(<representation of the value>)`,
|
||
where the representation of the value is simply the value's own `toString`
|
||
representation. For example:
|
||
|
||
| call | output |
|
||
|----------------------------------------|-------------------------|
|
||
| `toString(Maybe.of(42))` | `Just(42)` |
|
||
| `toString(Maybe.of([1, 2, 3]))` | `Just(1,2,3)` |
|
||
| `toString(Maybe.of({ an: 'object' }))` | `Just([object Object])` |
|
||
| `toString(Maybe.nothing())` | `Nothing` |
|
||
|
||
@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 function toString<T extends {
|
||
toString(): string;
|
||
}>(maybe: Maybe<T>): string;
|
||
/**
|
||
* Create an `Object` representation of a `Maybe` instance.
|
||
*
|
||
* Useful for serialization. `JSON.stringify()` uses it.
|
||
*
|
||
* @param maybe The value to convert to JSON
|
||
* @returns The JSON representation of the `Maybe`
|
||
*/
|
||
export declare function toJSON<T>(maybe: Maybe<T>): MaybeJSON<T>;
|
||
/** A lightweight object defining how to handle each variant of a Maybe. */
|
||
export declare type Matcher<T, A> = {
|
||
Just: (value: T) => A;
|
||
Nothing: () => A;
|
||
};
|
||
/**
|
||
Performs the same basic functionality as `getOrElse`, but instead of simply
|
||
unwrapping the value if it is `Just` 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 `Just` 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 Maybe from 'true-myth/maybe';
|
||
|
||
const logValue = (mightBeANumber: Maybe<number>) => {
|
||
const valueToLog = Maybe.mightBeANumber.isJust()
|
||
? Maybe.unsafelyUnwrap(mightBeANumber).toString()
|
||
: 'Nothing to log.';
|
||
|
||
console.log(valueToLog);
|
||
};
|
||
```
|
||
|
||
...we can write code like this:
|
||
|
||
```ts
|
||
import Maybe from 'true-myth/maybe';
|
||
|
||
const logValue = (mightBeANumber: Maybe<number>) => {
|
||
const value = Maybe.match(
|
||
{
|
||
Just: n => n.toString(),
|
||
Nothing: () => 'Nothing to log.',
|
||
},
|
||
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, A>(matcher: Matcher<T, A>, maybe: Maybe<T>): A;
|
||
export declare function match<T, A>(matcher: Matcher<T, A>): (m: Maybe<T>) => A;
|
||
/** Alias for [`match`](#match) */
|
||
export declare const cata: typeof match;
|
||
/**
|
||
Allows quick triple-equal equality check between the values inside two `maybe`s
|
||
without having to unwrap them first.
|
||
|
||
```ts
|
||
const a = Maybe.of(3);
|
||
const b = Maybe.of(3);
|
||
const c = Maybe.of(null);
|
||
const d = Maybe.nothing();
|
||
|
||
Maybe.equals(a, b); // true
|
||
Maybe.equals(a, c); // false
|
||
Maybe.equals(c, d); // true
|
||
```
|
||
|
||
@param mb A `maybe` to compare to.
|
||
@param ma A `maybe` instance to check.
|
||
*/
|
||
export declare function equals<T>(mb: Maybe<T>, ma: Maybe<T>): boolean;
|
||
export declare function equals<T>(mb: Maybe<T>): (ma: Maybe<T>) => boolean;
|
||
/**
|
||
Allows you to *apply* (thus `ap`) a value to a function without having to
|
||
take either out of the context of their `Maybe`s. This does mean that the
|
||
transforming function is itself within a `Maybe`, which can be hard to grok
|
||
at first but lets you do some very elegant things. For example, `ap` allows
|
||
you to this:
|
||
|
||
```ts
|
||
import { just, nothing } from 'true-myth/maybe';
|
||
|
||
const one = just(1);
|
||
const five = just(5);
|
||
const none = nothing();
|
||
|
||
const add = (a: number) => (b: number) => a + b;
|
||
const maybeAdd = just(add);
|
||
|
||
maybeAdd.ap(one).ap(five); // Just(6)
|
||
maybeAdd.ap(one).ap(none); // Nothing
|
||
maybeAdd.ap(none).ap(five) // Nothing
|
||
```
|
||
|
||
Without `Maybe.ap`, you'd need to do something like a nested `Maybe.match`:
|
||
|
||
```ts
|
||
import { just, nothing } from 'true-myth/maybe';
|
||
|
||
const one = just(1);
|
||
const five = just(5);
|
||
const none = nothing();
|
||
|
||
one.match({
|
||
Just: n => five.match({
|
||
Just: o => just(n + o),
|
||
Nothing: () => nothing(),
|
||
}),
|
||
Nothing: () => nothing(),
|
||
}); // Just(6)
|
||
|
||
one.match({
|
||
Just: n => none.match({
|
||
Just: o => just(n + o),
|
||
Nothing: () => nothing(),
|
||
}),
|
||
Nothing: () => nothing(),
|
||
}); // Nothing
|
||
|
||
none.match({
|
||
Just: n => five.match({
|
||
Just: o => just(n + o),
|
||
Nothing: () => nothing(),
|
||
}),
|
||
Nothing: () => nothing(),
|
||
}); // Nothing
|
||
```
|
||
|
||
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 Maybe from 'true-myth/maybe';
|
||
import Immutable from 'immutable';
|
||
import { curry } from 'lodash'
|
||
|
||
const is = curry(Immutable.is);
|
||
|
||
const x = Maybe.of(Immutable.Set.of(1, 2, 3));
|
||
const y = Maybe.of(Immutable.Set.of(2, 3, 4));
|
||
|
||
Maybe.of(is).ap(x).ap(y); // Just(false)
|
||
```
|
||
|
||
Without `ap`, we're back to that gnarly nested `match`:
|
||
|
||
```ts
|
||
* import Maybe, { just, nothing } from 'true-myth/maybe';
|
||
import Immutable from 'immutable';
|
||
import { curry } from 'lodash'
|
||
|
||
const is = curry(Immutable.is);
|
||
|
||
const x = Maybe.of(Immutable.Set.of(1, 2, 3));
|
||
const y = Maybe.of(Immutable.Set.of(2, 3, 4));
|
||
|
||
x.match({
|
||
Just: iX => y.match({
|
||
Just: iY => Maybe.just(Immutable.is(iX, iY)),
|
||
Nothing: () => Maybe.nothing(),
|
||
})
|
||
Nothing: () => Maybe.nothing(),
|
||
}); // Just(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 Maybe from 'true-myth/maybe';
|
||
import { curry } from 'lodash';
|
||
|
||
const normalAdd = (a: number, b: number) => a + b;
|
||
const curriedAdd = curry(normalAdd); // (a: number) => (b: number) => a + b;
|
||
|
||
Maybe.of(curriedAdd).ap(Maybe.of(1)).ap(Maybe.of(5)); // Just(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 = Maybe.of(add); // Just((a: number) => (b: number) => a + b)
|
||
const maybeAdd1 = maybeAdd.ap(Maybe.of(1)); // Just((b: number) => 1 + b)
|
||
const final = maybeAdd1.ap(Maybe.of(3)); // Just(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();
|
||
Maybe.of(toStr).ap(12); // Just("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 `Maybe` scenario. In that case, you can wrap the
|
||
possibly-present in `ap` and then wrap the values to apply to the function to
|
||
in `Maybe` themselves.
|
||
|
||
**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 (`Maybe.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 maybeFn maybe a function from T to U
|
||
@param maybe maybe a T to apply to `fn`
|
||
*/
|
||
export declare function ap<T, U>(maybeFn: Maybe<(t: T) => U>, maybe: Maybe<T>): Maybe<U>;
|
||
export declare function ap<T, U>(maybeFn: Maybe<(t: T) => U>): (maybe: Maybe<T>) => Maybe<U>;
|
||
/**
|
||
Determine whether an item is an instance of `Just` or `Nothing`.
|
||
|
||
@param item The item to check.
|
||
*/
|
||
export declare function isInstance<T = any>(item: any): item is Maybe<T>;
|
||
declare type Predicate<T> = (element: T, index: number, array: T[]) => boolean;
|
||
/**
|
||
Safely search for an element in an array.
|
||
|
||
This function behaves like `Array.prototype.find`, but returns `Maybe<T>`
|
||
instead of `T | undefined`.
|
||
|
||
## Examples
|
||
|
||
The basic form is:
|
||
|
||
```ts
|
||
import Maybe from 'true-myth/maybe';
|
||
|
||
let array = [1, 2, 3];
|
||
Maybe.find(v => v > 1, array); // Just(2)
|
||
Maybe.find(v => v < 1, array); // Nothing
|
||
```
|
||
|
||
The function is curried so you can use it in a functional chain. For example
|
||
(leaving aside error handling on a bad response for simplicity), suppose the
|
||
url `https://arrays.example.com` returned a JSON payload with the type
|
||
`Array<{ count: number, name: string }>`, and we wanted to get the first
|
||
of these where `count` was at least 100. We could write this:
|
||
|
||
```ts
|
||
import Maybe from 'true-myth/maybe';
|
||
|
||
type Item = { count: number; name: string };
|
||
type Response = Array<Item>;
|
||
|
||
// curried variant!
|
||
const findAtLeast100 = Maybe.find(({ count }: Item) => count > 100);
|
||
|
||
fetch('https://arrays.example.com')
|
||
.then(response => response.json() as Response)
|
||
.then(findAtLeast100)
|
||
.then(found => {
|
||
if (found.isJust()) {
|
||
console.log(`The matching value is ${found.value.name}!`);
|
||
}
|
||
});
|
||
```
|
||
|
||
@param predicate A function to execute on each value in the array, returning
|
||
`true` when the item in the array matches the condition. The
|
||
signature for `predicate` is identical to the signature for
|
||
the first argument to `Array.prototype.find`. The function
|
||
is called once for each element of the array, in ascending
|
||
order, until it finds one where predicate returns true. If
|
||
such an element is found, find immediately returns that
|
||
element value wrapped in `Just`. Otherwise, `Maybe.find`
|
||
returns `Nothing`.
|
||
* @param array The array to search using the predicate.
|
||
*/
|
||
export declare function find<T>(predicate: Predicate<T>, array: T[]): Maybe<T>;
|
||
export declare function find<T>(predicate: Predicate<T>): (array: T[]) => Maybe<T>;
|
||
/**
|
||
Safely get the first item from a list, returning `Just` the first item if the
|
||
array has at least one item in it, or `Nothing` if it is empty.
|
||
|
||
## Examples
|
||
|
||
```ts
|
||
let empty = [];
|
||
Maybe.head(empty); // => Nothing
|
||
|
||
let full = [1, 2, 3];
|
||
Maybe.head(full); // => Just(1)
|
||
```
|
||
|
||
@param array The array to get the first item from.
|
||
*/
|
||
export declare function head<T>(array: Array<T | null | undefined>): Maybe<T>;
|
||
/** A convenience alias for `Maybe.head`. */
|
||
export declare const first: typeof head;
|
||
/**
|
||
Safely get the last item from a list, returning `Just` the last item if the
|
||
array has at least one item in it, or `Nothing` if it is empty.
|
||
|
||
## Examples
|
||
|
||
```ts
|
||
let empty = [];
|
||
Maybe.last(empty); // => Nothing
|
||
|
||
let full = [1, 2, 3];
|
||
Maybe.last(full); // => Just(3)
|
||
```
|
||
|
||
@param array The array to get the first item from.
|
||
*/
|
||
export declare function last<T>(array: Array<T | null | undefined>): Maybe<T>;
|
||
/**
|
||
Convert the arguments to a single `Maybe`. Useful for dealing with arrays of
|
||
`Maybe`s, via the spread operator.
|
||
|
||
## Examples
|
||
|
||
```ts
|
||
import Maybe from 'true-myth/maybe';
|
||
|
||
let valid = [Maybe.just(2), Maybe.just('three')];
|
||
Maybe.all(...valid); // => Just([2, 'three']);
|
||
|
||
let invalid = [Maybe.just(2), Maybe.nothing<string>()];
|
||
Maybe.all(...invalid); // => Nothing
|
||
```
|
||
|
||
## Note on Spread
|
||
|
||
This requires the use of the spread operator because (at least as of
|
||
TypeScript 3.0), the type inference falls down when attempting to build this
|
||
same type with an array directly. Moreover, this spread-based approach handles
|
||
heteregenous arrays; TS *also* fails to infer correctly for anything but
|
||
homogeneous arrays when using that approach.
|
||
|
||
@param maybes The `Maybe`s to resolve to a single `Maybe`.
|
||
*/
|
||
export declare function all<T extends Array<Maybe<any>>>(...maybes: T): All<T>;
|
||
declare type All<T extends Array<Maybe<any>>> = T extends Array<Maybe<infer U>> ? Maybe<Array<U>> : never;
|
||
/**
|
||
Given a tuple of `Maybe`s, return a `Maybe` of the tuple values.
|
||
|
||
Given a tuple of type `[Maybe<A>, Maybe<B>]`, the resulting type is
|
||
`Maybe<[A, B]>`. Works with up to a 5-tuple. (If you're doing more than a
|
||
5-tuple, what are you doing???)
|
||
|
||
## Examples
|
||
|
||
If any of the items in the tuple are `Nothing`, the whole result is `Nothing`.
|
||
Here, for example, `result` has the type `Maybe<[string, number]>` and will be
|
||
`Nothing`:
|
||
|
||
```ts
|
||
import Maybe from 'true-myth/maybe';
|
||
|
||
type Tuple = [Maybe<string>, Maybe<number>];
|
||
|
||
let invalid: Tuple = [Maybe.just('wat'), Maybe.nothing()];
|
||
let result = Maybe.tuple(invalid); // => Nothing
|
||
```
|
||
|
||
If all of the items in the tuple are `Just`, the result is `Just` wrapping the
|
||
tuple of the values of the items. Here, for example, `result` again has the
|
||
type `Maybe<[string, number]>` and will be `Just(['hey', 12]`:
|
||
|
||
```ts
|
||
import Maybe from 'true-myth/maybe';
|
||
|
||
type Tuple = [Maybe<string>, Maybe<number>];
|
||
|
||
let valid: Tuple = [Maybe.just('hey'), Maybe.just(12)];
|
||
let result = Maybe.tuple(valid); // => Just(['hey', 12])
|
||
```
|
||
|
||
@param maybes: the tuple of `Maybe`s to convert to a `Maybe` of tuple values.
|
||
*/
|
||
export declare function tuple<T>(maybes: [Maybe<T>]): Maybe<[T]>;
|
||
export declare function tuple<T, U>(maybes: [Maybe<T>, Maybe<U>]): Maybe<[T, U]>;
|
||
export declare function tuple<T, U, V>(maybes: [Maybe<T>, Maybe<U>, Maybe<V>]): Maybe<[T, U, V]>;
|
||
export declare function tuple<T, U, V, W>(maybes: [Maybe<T>, Maybe<U>, Maybe<V>, Maybe<W>]): Maybe<[T, U, V, W]>;
|
||
/**
|
||
Safely extract a key from an object, returning `Just` if the key has a value
|
||
on the object and `Nothing` if it does not.
|
||
|
||
The check is type-safe: you won't even be able to compile if you try to look
|
||
up a property that TypeScript *knows* doesn't exist on the object.
|
||
|
||
```ts
|
||
type Person = { name?: string };
|
||
|
||
const me: Person = { name: 'Chris' };
|
||
console.log(Maybe.property('name', me)); // Just('Chris')
|
||
|
||
const nobody: Person = {};
|
||
console.log(Maybe.property('name', nobody)); // Nothing
|
||
```
|
||
|
||
However, it also works correctly with dictionary types:
|
||
|
||
```ts
|
||
type Dict<T> = { [key: string]: T };
|
||
|
||
const score: Dict<number> = {
|
||
player1: 0,
|
||
player2: 1
|
||
};
|
||
|
||
console.log(Maybe.property('player1', score)); // Just(0)
|
||
console.log(Maybe.property('player2', score)); // Just(1)
|
||
console.log(Maybe.property('player3', score)); // Nothing
|
||
```
|
||
|
||
The order of keys is so that it can be partially applied:
|
||
|
||
```ts
|
||
type Person = { name?: string };
|
||
|
||
const lookupName = Maybe.property('name');
|
||
|
||
const me: Person = { name: 'Chris' };
|
||
console.log(lookupName(me)); // Just('Chris')
|
||
|
||
const nobody: Person = {};
|
||
console.log(lookupName(nobody)); // Nothing
|
||
```
|
||
|
||
@param key The key to pull out of the object.
|
||
@param obj The object to look up the key from.
|
||
*/
|
||
export declare function property<T, K extends keyof T>(key: K, obj: T): Maybe<NonNullable<T[K]>>;
|
||
export declare function property<T, K extends keyof T>(key: K): (obj: T) => Maybe<NonNullable<T[K]>>;
|
||
/**
|
||
Safely extract a key from a Maybe of an object, returning `Just` if the key
|
||
has a value on the object and `Nothing` if it does not. (Like `Maybe.property`
|
||
but operating on a `Maybe<T>` rather than directly on a `T`.)
|
||
|
||
The check is type-safe: you won't even be able to compile if you try to look
|
||
up a property that TypeScript *knows* doesn't exist on the object.
|
||
|
||
```ts
|
||
type Person = { name?: string };
|
||
|
||
const me: Maybe<Person> = Maybe.just({ name: 'Chris' });
|
||
console.log(Maybe.get('name', me)); // Just('Chris')
|
||
|
||
const nobody = Maybe.nothing<Person>();
|
||
console.log(Maybe.get('name', nobody)); // Nothing
|
||
```
|
||
|
||
However, it also works correctly with dictionary types:
|
||
|
||
```ts
|
||
type Dict<T> = { [key: string]: T };
|
||
|
||
const score: Maybe<Dict<number>> = Maybe.just({
|
||
player1: 0,
|
||
player2: 1
|
||
});
|
||
|
||
console.log(Maybe.get('player1', score)); // Just(0)
|
||
console.log(Maybe.get('player2', score)); // Just(1)
|
||
console.log(Maybe.get('player3', score)); // Nothing
|
||
```
|
||
|
||
The order of keys is so that it can be partially applied:
|
||
|
||
```ts
|
||
type Person = { name?: string };
|
||
|
||
const lookupName = Maybe.get('name');
|
||
|
||
const me: Person = { name: 'Chris' };
|
||
console.log(lookupName(me)); // Just('Chris')
|
||
|
||
const nobody: Person = {};
|
||
console.log(lookupName(nobody)); // Nothing
|
||
```
|
||
|
||
@param key The key to pull out of the object.
|
||
@param obj The object to look up the key from.
|
||
*/
|
||
export declare function get<T, K extends keyof T>(key: K, maybeObj: Maybe<T>): Maybe<T[K]>;
|
||
export declare function get<T, K extends keyof T>(key: K): (maybeObj: Maybe<T>) => Maybe<T[K]>;
|
||
/**
|
||
Transform a function from a normal JS function which may return `null` or
|
||
`undefined` to a function which returns a `Maybe` instead.
|
||
|
||
For example, dealing with the `Document#querySelector` DOM API involves a
|
||
*lot* of things which can be `null`:
|
||
|
||
```ts
|
||
const foo = document.querySelector('#foo');
|
||
let width: number;
|
||
if (foo !== null) {
|
||
width = foo.getBoundingClientRect().width;
|
||
} else {
|
||
width = 0;
|
||
}
|
||
|
||
const getStyle = (el: HTMLElement, rule: string) => el.style[rule];
|
||
const bar = document.querySelector('.bar');
|
||
let color: string;
|
||
if (bar != null) {
|
||
let possibleColor = getStyle(bar, 'color');
|
||
if (possibleColor !== null) {
|
||
color = possibleColor;
|
||
} else {
|
||
color = 'black';
|
||
}
|
||
}
|
||
```
|
||
|
||
(Imagine in this example that there were more than two options: the
|
||
simplifying workarounds you commonly use to make this terser in JS, like the
|
||
ternary operator or the short-circuiting `||` operator, eventually become very
|
||
confusing with more complicated flows.)
|
||
|
||
We can work around this with `Maybe`, always wrapping each layer in `Maybe.of`
|
||
invocations, and this is *somewhat* better:
|
||
|
||
```ts
|
||
const aWidth = Maybe.of(document.querySelector('#foo'))
|
||
.map(el => el.getBoundingClientRect().width)
|
||
.unwrapOr(0);
|
||
|
||
const aColor = Maybe.of(document.querySelector('.bar'))
|
||
.andThen(el => Maybe.of(getStyle(el, 'color'))
|
||
.unwrapOr('black');
|
||
```
|
||
|
||
With `wrapReturn`, though, you can create a transformed version of a function
|
||
*once* and then be able to use it freely throughout your codebase, *always*
|
||
getting back a `Maybe`:
|
||
|
||
```ts
|
||
const querySelector = Maybe.wrapReturn(document.querySelector.bind(document));
|
||
const safelyGetStyle = Maybe.wrapReturn(getStyle);
|
||
|
||
const aWidth = querySelector('#foo')
|
||
.map(el => el.getBoundingClientRect().width)
|
||
.unwrapOr(0);
|
||
|
||
const aColor = querySelector('.bar')
|
||
.andThen(el => safelyGetStyle(el, 'color'))
|
||
.unwrapOr('black');
|
||
```
|
||
|
||
@param fn The function to transform; the resulting function will have the
|
||
exact same signature except for its return type.
|
||
*/
|
||
export declare function wrapReturn<F extends (...args: any[]) => any>(fn: F): (...args: Parameters<F>) => Maybe<NonNullable<ReturnType<F>>>;
|
||
/** Alias for [`wrapReturn`](#wrapReturn). */
|
||
export declare const maybeify: typeof wrapReturn;
|
||
export declare const transmogrify: typeof wrapReturn;
|
||
/** A value which may (`Just<T>`) or may not (`Nothing`) be present. */
|
||
export declare type Maybe<T> = Just<T> | Nothing<T>;
|
||
export declare const Maybe: {
|
||
Variant: typeof Variant;
|
||
Just: typeof Just;
|
||
Nothing: typeof Nothing;
|
||
all: typeof all;
|
||
isJust: typeof isJust;
|
||
isNothing: typeof isNothing;
|
||
just: typeof just;
|
||
nothing: typeof nothing;
|
||
of: typeof of;
|
||
find: typeof find;
|
||
first: typeof head;
|
||
fromNullable: typeof of;
|
||
head: typeof head;
|
||
last: typeof last;
|
||
map: typeof map;
|
||
mapOr: typeof mapOr;
|
||
mapOrElse: typeof mapOrElse;
|
||
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;
|
||
unwrapOr: typeof unwrapOr;
|
||
getOr: typeof unwrapOr;
|
||
unwrapOrElse: typeof unwrapOrElse;
|
||
getOrElse: typeof unwrapOrElse;
|
||
toOkOrErr: typeof toOkOrErr;
|
||
toOkOrElseErr: typeof toOkOrElseErr;
|
||
fromResult: typeof fromResult;
|
||
toString: typeof toString;
|
||
toJSON: typeof toJSON;
|
||
tuple: typeof tuple;
|
||
match: typeof match;
|
||
cata: typeof match;
|
||
equals: typeof equals;
|
||
ap: typeof ap;
|
||
isInstance: typeof isInstance;
|
||
property: typeof property;
|
||
get: typeof get;
|
||
wrapReturn: typeof wrapReturn;
|
||
ify: typeof wrapReturn;
|
||
};
|
||
export default Maybe;
|
||
//# sourceMappingURL=maybe.d.ts.map
|