2.2.5 • Published 5 years ago

monad-types v2.2.5

Weekly downloads
-
License
MIT
Repository
github
Last release
5 years ago

monad-types

Adds Optional and Result types from functions language to JavaScript/Typescript

Difference between Optional and Result

While the two are very similar there is a difference in the information they represent. While an optional represents whether requested data was present or not, the result represents whether an operation was successful. They both work in the same way; the only difference is that a result can hold an error message whereas an optional cannot.

Installation

You can install 'monad-types' using NPM.

npm install --save monad-types

Breaking Changes

import { Result } from 'monad-types'
import { Optional } from 'monad-types'

Optional.optional(5)
/* is now */
Optional.of(5)

Optional.optional(5).get
/* is now */
Optional.optional(5).value

Optional.optional(5).orUndefined
/* Replaced with */
Optional.optional(5).value


Result.ok(5).get
/* is now */
Result.ok(5).value

Result.ok(5).orUndefined
/* Replaced with */
Result.ok(5).value

Result Example

import { Result } from 'monad-types'

function fetchUserIdByName(name: string) {
    // Fetch some data ...
    return Result.error('The connection to the database server was refused')
}

function fetchProfilePictureByUserId(id: number) {
    // Fetch some data ...
    return Result.error('The connection to the database server was refused')
}


const userId = fetchUserByName('John Doe')

// fetchProfilePictureByUserId is only called if result from
// fetchUserByName was ok, otherwise map will return the userId
// result.
const pic = userId.map(id => fetchProfilePictureByUserId(id))
/* or */
const pic = userId.mapAsync(async id => fetchProfilePictureByUserId(id))

if (pic.isOk) {
    // Do something only if the result of fetchProfilePictureByUserId
    // was okay
}

setPicture(pic.getOrElse(defaultPicture))

const msg = pic.match({
    ok: x => 'Everything worked!',
    error: e => e.message
})

Optional Example

import { Optional } from 'monad-types'

function fetchUserIdByName(name: string) {
    // Fetch some data ...
    if (err) {
        return Optional.none()
    } else {
        return Optional.some(id)
    }
}

function fetchProfilePictureByUserId(id: number) {
    // Fetch some data ...
    if (err) {
        return Optional.none()
    } else {
        return Optional.some(picture)
    }
}


const userId = fetchUserByName('John Doe')

// fetchProfilePictureByUserId is only called if result from
// fetchUserByName was some, otherwise map will return the userId
// option.
const pic = userId.map(id => fetchProfilePictureByUserId(id))

if (pic.isPresent) {
    // Do something only if the picture was found
}

setPicture(pic.getOrElse(defaultPicture))

const msg = pic.match({
    some: x => 'Everything worked!',
    none: () => 'There was no image'
})

API Documentation

class Optional<T> {
    /**
     * Returns the optional's value if the optional is some, otherwise undefined
     */
    value: T | undefined

    /**
     * Returns the optional's value if the optional is some, otherwise returns the result of evaluating default.
     * @param defaultValue Default value
     */
    getOrElse(defaultValue: T | (() => T)): T

    /**
     * Returns the optional itself if it is some, otherwise return the result of evaluating alternative.
     * @param alternative Alternative optional
     */
    orElse(alternative: () => Optional<T>): Optional<T>

    /**
     * Returns true if the optional's value is some, false otherwise.
     */
    isSome(): boolean

    /**
     * Returns true if the optional's value is none, false otherwise.
     */
    isNone(): boolean

    /**
     * Builds a new optional by applying a function to value of this optional.
     * @param f Map functions
     */
    map<S>(f: (_: T) => S | Optional<S>): Optional<S>

    /**
     * Builds a new optional by applying a function to value of this optional.
     * @param f Map functions
     */
    mapAsync<S>(f: (value: T) => Promise<Optional<S>> | Promise<S>): Promise<Optional<S>>

    /**
     * Pattern match signature.
     * @param matcher Match object
     */
    match<S>(matcher: Matcher<T, S>): S

    /**
     * Check if two optionals are equal
     * @param other Optional to compare to
     */
    equals(other: Optional<T>): boolean

    /**
     * Create object representation of optional
     */
    toObject(): { some: T } | { none: 0 }

    /**
     * Create optional from object representation
     * @param a object representation of optional
     */
    static fromObject<T>(a: { some: T } | {  none: 0 }): Optional<T>


    /**
     * Turn value into some
     * @param value Value which must be defined
     */
    static some<T>(value: T): Optional<T>

    /**
     * None
     */
    static none<T = any>(): Optional<T>

    /**
     * Get some if value is defined or none
     * @param value Value
     */
    static of<T>(value?: T): Optional<T>

    /**
     * Check if object is of type Optional
     * @param a object to check
     */
    static isOptional<T = any>(a: any): a is Optional<T>

    /**
    * Turns map of optionals into resolved map
    * @param map Map of optionals
    */
    static mapAll<T extends {
        [key: string]: Optional<any>
    }>(map: T): Optional<{
        [key in keyof T]: OptionalType<T[key]>
    }>

    /**
     * Turns array of optionals into resolved array
     * @param map Map of optionals
     */
    static mapAll<T>(a: Optional<T>[]): Optional<T[]>

    /**
     * Filter out error from array
     * @param a array of values
     */
    static omitNone<T>(a: Optional<T>[]): T[]
    
    /**
     * Returns the optional's value if the optional is some, otherwise returns undefined
     * @param optional Optional
     */
    static getValue: <T>(optional: Optional<T>) => T

    /**
     * Returns the optional's value if the optional is some, otherwise returns the result of evaluating default.
     * @param defaultValue Default value
     * @param optional Optional
     */
    static getOrElse: <T>(defaultValue: T | (() => T)) => (optional: Optional<T>) => T

    /**
     * Returns the optional itself if it is some, otherwise returns the result of evaluating alternative.
     * @param alternative Alternative optional
     * @param optional Optional
     */
    static orElse: <T>(alternative: () => Optional<T>) => (optional: Optional<T>) => Optional<T>

    /**
     * Returns true if the optional's value is some, false otherwise.
     * @param optional Optional
     */
    static isSome: <T>(optional: Optional<T>) => boolean

    /**
     * Returns true if the optional's value is empty, false otherwise.
     * @param optional Optional
     */
    static isNone: <T>(optional: Optional<T>) => boolean

    /**
     * Builds a new optional by applying a function to value of this optional.
     * @param f Map functions
     * @param optional Optional
     */
    static map: <T, S>(f: (_: T) => S | Optional<S>) => (optional: Optional<T>) => Optional<S>

    /**
     * Builds a new optional by applying a function to value of this optional.
     * @param f Map functions
     * @param optional Optional
     */
    static mapAsync: <T, S>(f: (value: T) => Promise<Optional<S>> | Promise<S>) => (optional: Optional<T>) => Promise<Optional<S>>

    /**
     * Pattern match signature.
     * @param matcher Match object
     * @param optional Optional
     */
    static match: <T, S>(matcher: Matcher<T, S>) => (optional: Optional<T>) => S

    /**
     * Check if two optionals are equal
     * @param other Optional to compare to
     * @param optional Optional
     */
    static equals: <T>(other: Optional<T>) => (optional: Optional<T>) => boolean

    /**
     * Create object representation of optional
     * @param optional Optional
     */
    static toObject: <T>(optional: Optional<T>) => { none: 0 } | { some: T }
}



class Result<T, E = string> {
    /**
     * Returns the result's value if the result is okay, otherwise returns undefined
     */
    value: T | undefined

    /**
     * Returns the result's error if the result is error, otherwise returns undefined
     */
    error: E | undefined

    /**
     * Returns the result's value if the result is okay, otherwise returns the result of evaluating default.
     * @param defaultValue Default value
     */
    getOrElse(defaultValue: T | (() => T)): T

    /**
     * Returns the result itself if it is okay, otherwise returns the result of evaluating alternative.
     * @param alternative Alternative result
     */
    orElse(alternative: () => Result<T, E>): Result<T, E>

    /**
     * Returns true if the result's value is okay, false otherwise.
     */
    isOk(): boolean

    /**
     * Returns true if the result's value is an error, false otherwise.
     */
    isError(): boolean

    /**
     * Builds a new result by applying a function to all elements of this result.
     * @param f Map functions
     */
    map<R>(f: (value: T) => Result<R, E> | R): Result<R, E>

    /**
     * Builds a new result by applying a function to all elements of this result.
     * @param f Map functions
     */
    mapAsync<R>(f: (value: T) => Promise<Result<R, E>> | Promise<R>): Promise<Result<R, E>>

    /**
     * Pattern match signature.
     * @param matcher Matcher object
     */
    match<R>(matcher: ResultMatcher<T, E, R>): R

    /**
     * Create object representation of optional
     */
    toObject(): { ok: T } | { error: E }

    /**
     * Check if two results are equal
     * @param other Result to compare to
     */
    equals(other: Result<T, E>): boolean

    /**
     * Convert result to options
     */
    toOptional(): Optional<any>



    /**
     * Create on value
     * @param value Value
     */
    static ok<T, E = string>(value: T): Result<T, E>

    /**
     * Create error instance
     * @param value message or Error
     */
    static error<T, E = string>(value: E): Result<T, E>

    /**
     * Turn throwing block into result
     * @param tryFunc Function that can throw
     */
    static Try<T>(tryFunc: () => T): Result<T, Error>

    /**
     * Turn throwing promise into a result promise
     * @param p Promise
     */
    static fromPromise<T>(p: Promise<T>): Promise<Result<T, Error>>

    /**
     * Convert optional to result
     * @param optional Optional
     * @param message Error message in case optional is none
     */
    static fromOptional<T>(optional: T, message?: string): Result<any, string>

    /**
     * Create optional from object representation
     * @param a object representation of optional
     */
    static fromObject<T, E = string>(a: { ok: T } | { error: E  }): Result<T>

    /**
     * Turns map of result into resolved map
     * @param map Map of results
     */
    static mapAll<E, T extends {
        [key: string]: Result<any, E>
    }>(map: T): Result<{
        [key in keyof T]: ResultOkType<T[key]>
    }, E>

    /**
     * Turns array of result into resolved array
     * @param map Map of results
     */
    static mapAll<T, E>(a: Result<T, E>[]): Result<T[], E>

    /**
     * Filter out error from array
     * @param a array of values
     */
    static omitErrors<T>(a: Result<T, any>[]): T[]

    /**
     * Check if object is of type Result
     * @param a object to check
     */
    static isResult<T = any, E = string>(a: any): a is Result<T, E>

    /**
     * Returns the result's value if the result is okay, otherwise returns undefined
     * @param result Result
     */
    static getValue: <T>(result: Result<T, any>) => T

    /**
     * Returns the result's error if the result is error, otherwise returns undefined
     * @param result Result
     */
    static getError: <E>(result: Result<any, E>) => E

    /**
     * Returns the result's value if the result is okay, otherwise return the result of evaluating default.
     * @param defaultValue Default value
     * @param result Result
     */
    static getOrElse: <T>(defaultValue: T | (() => T)) => (result: Result<T, any>) => T

    /**
     * Returns the result itself if it is okay, otherwise return the result of evaluating alternative.
     * @param alternative Alternative result
     * @param result Result
     */
    static orElse: <T>(alternative: () => Result<T, string>) => (result: Result<T, any>) => Result<T, any>

    /**
     * Returns true if the result's value is okay, false otherwise.
     * @param result Result
     */
    static isOk: <T>(result: Result<T, any>) => boolean

    /**
     * Returns true if the result's value is an error, false otherwise.
     * @param result Result
     */
    static isError: <T>(result: Result<T, any>) => boolean

    /**
     * Builds a new result by applying a function to all elements of this result.
     * @param f Map functions
     * @param result Result
     */
    static map: <T, E, R>(f: (value: T) => R | Result<R, E>) => (result: Result<T, E>) => Result<R, E>

    /**
     * Builds a new result by applying a function to all elements of this result.
     * @param f Map functions
     * @param result Result
     */
    static mapAsync: <T, E, R>(f: (value: T) => Promise<Result<R, E>> | Promise<R>) => (result: Result<T, E>) => Promise<Result<R, E>>

    /**
     * Pattern match signature.
     * @param result Result
     */
    static match: <T, E, R>(matcher: ResultMatcher<T, E, R>) => (result: Result<T, E>) => R

    /**
     * Create object representation of optional
     * @param result Result
     */
    static toObject: <T, E>(result: Result<T, E>) => { ok: T } | { error: E }

    /**
     * Check if two results are equal
     * @param other Result to compare to
     * @param result Result
     */
    static equals: <T, E>(other: Result<T, E>) => (result: Result<T, E>) => boolean

    /**
     * Convert result to options
     */
    static toOptional: <T>(result: Result<T, any>) => Optional<any>
}
2.2.5

5 years ago

2.2.0

5 years ago

2.1.0

5 years ago

2.0.0

5 years ago

1.7.0

5 years ago

1.6.0

5 years ago

1.5.0

5 years ago

1.2.0

6 years ago

1.1.0

6 years ago

1.0.4

6 years ago

1.0.3

6 years ago

1.0.2

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago