maybe-baby
    TypeScript icon, indicating that this package has built-in type declarations

    2.0.3 • Public • Published

    maybe-baby

    2.x will be maintained, however, if possible for your repository, you should opt to use TypeScript's optional chaining, which was introduced in 3.7

    Minimize defensive coding. A JavaScript implementation of the Maybe monad.

    npm version build status coverage status dependency status devDependency status

    Install

    • npm install --save maybe-baby
    • yarn add maybe-baby

    Getting Started

    What if we need the zipCode of the user below, which lives on the address object?

    const user = { 
      email: 'foo@bar.com',
      address: null,
      name: {
         first: 'John',
         last: null,
         middle: null
      }
    };

    Accessing it via dot notation will result in an error:

    const zipCode = user.address.zipCode;  // Uncaught TypeError: Cannot read property 'zipCode' of undefined

    Possible Solutions?

    1. Write some ugly null checks that don't scale well:
    const getZipCode = (user) => {
      if (user !== null && user !== undefined) {
        if (user.address !== null && user.address !== undefined) {
          return user.address.zipCode
        }
      }
    }
    1. Use _.get() or something similar, but these libraries have large footprints, and most likely won't be implementing the monadic structure.

    2. Wait for optional chaining to be approved in ECMA, or use babel-plugin-transform-optional-chaining.

    3. Use TypeScript's optional chaining

    A Better Solution?

    1. Use maybe-baby to minimize defensive coding:
    import Maybe from 'maybe-baby';
    
    // Use a function getter
    const getZipCode = (user) => Maybe.of(() => user.address.zipCode).join();

    Now we can safely get the zipCode without worrying about the shape of the object, or encountering TypeErrors:

    const zipCode = getZipCode(user);
    console.log(zipCode);  // undefined

    Docs

    Documentation generated via JSDoc.


    Migrating from 1.x to 2.x

    Breaking changes were introduced in 2.0.0; the following redundant function were removed.

    Maybe.of() can replicate the behavior of prop, props, and path.

    prop(val: string | number)

    const obj = Maybe.of({ 
      foo: { 
        bar: [123, 456] 
      } 
    });
    
    // Incorrect
    const bar = obj.prop("foo").join(); // { bar: [123, 456] }
    
    // Correct
    Maybe.of(() => obj.join().foo).join(); // { bar: [123, 456] }
    
    // Incorrect
    obj
      .prop("foo")
      .prop("bar")
      .prop(1)
      .join(); // 456
    
    // Correct
    Maybe.of(() => obj.join().foo.bar[1]).join() // 456

    props(...args)

    const obj = Maybe.of({
      foo: 'bar',
      baz: [1,2,3]
    });
    
    // Incorrect
    obj.props('baz', 0).join(); // 1
    
    // Correct
    Maybe.of(() => obj.join().baz[0]).join(); // 1

    props(val: string)

    const obj = Maybe.of({
      foo: 'bar',
      baz: [1,2,3]
    });
    
    // Incorrect
    obj.path('baz.0').join() // 1
    
    // Correct
    Maybe.of(() => obj.join().baz[0]).join(); // 1

    API

    Check out the API below, or the complete documentation.

    of(val: unknown | OfTypeFunc<T>)

    Accepts a value of any type, and returns a monad:

    const str = Maybe.of('foo');
    const num = Maybe.of(123);
    const bool = Maybe.of(true);
    const obj = Maybe.of({});
    const arr = Maybe.of([]);
    const empty = Maybe.of(null);
    const undef = Maybe.of(undefined);

    Accepts a function, and sets the function's return value as the monad's value, returns a monad.

    If the function results in an error, the monad's value is set to undefined.

    type OfTypeFunc<T> = () => T;
    
    const user = {};
    const mZipCode = Maybe.of(() => user.address.zipCode);
    
    console.log(mZipCode.join()); // undefined

    isJust(): boolean

    Returns true if the value is not null or undefined:

    Maybe.of(123).isJust();   // true
    Maybe.of(null).isJust();  // false

    isNothing(): boolean

    Returns true if the value is null or undefined:

    Maybe.of(123).isNothing();   // false
    Maybe.of(null).isNothing();  // true

    join(): T

    Returns the value:

    Maybe.of(123).join();   // 123
    Maybe.of(null).join();  // null

    orElse(defaultValue: unknown): Maybe

    Chain to the end of a monad to return as the default value if isNothing() is true:

    Maybe.of(undefined)
      .orElse('No Value')
      .join();  // 'No Value'

    map(transform: (val: T) => T | Maybe<T>): Maybe

    Apply a transformation to the monad, and return a new monad:

    const val = 1;
    const newVal = Maybe.of(val).map(val => val + 1);
    
    newVal.join(); // 2;

    chain(chain: (val: T) => Maybe<T>): Maybe

    Chain together functions that return Maybe monads:

    function addOne (val) {
      return Maybe.of(val + 1);
    }
    
    const three = Maybe.of(1)
     .chain(addOne)
     .chain(addOne);
    
     three.join(); // 3

    Credit

    Credit to James Sinclair for writing The Marvellously Mysterious JavaScript Maybe Monad.

    Install

    npm i maybe-baby

    DownloadsWeekly Downloads

    243

    Version

    2.0.3

    License

    MIT

    Unpacked Size

    22.6 kB

    Total Files

    7

    Last publish

    Collaborators

    • avatar