GithubHelp home page GithubHelp logo

ts.data.maybe's Introduction

Maybe

Build Status npm version

Maybe encapsulates the idea of a value that might not be there.

A Maybe value can either be Just some value or Nothing.

type Maybe<T> = Just<T> | Nothing;

Where Nothing is an instance of Nothing, null or undefined, and Just represents any non Nothing value.

If this is new to you, you may want to read the introductory article Safer code with container types about why and how to use this library.

Install

npm install ts.data.maybe --save

Example 1

import { Maybe, just, withDefault, map2 } from 'ts.data.maybe';

interface User {
  email: string;
  name: Maybe<string>;
  surname: Maybe<string>;
}
const user: User = {
  email: '[email protected]',
  name: just('John'),
  surname: just('Doe')
};

const getFullName = (name: string, surname: string) => `${name} ${surname}`;
const maybeFullname = map2(getFullName, user.name, user.surname); // Just<string>('John Doe')
console.log(withDefault(maybeFullname, '')); // 'John Doe'

Example 2

const prices: Maybe<number>[] = [
  just(300),
  nothing(),
  just(500),
  just(150),
  nothing()
];
const sum = (a: number, b: number) => a + b;
const total = prices
  .filter(n => !equals(n, nothing()))
  .reduce((acc, current) => map2(sum, acc, current), just(0));
console.log(withDefault(total, 0)); // 950

Api

(Inspired by elm-lang)

just

just<T>(value: T): Maybe<T>;

Wraps a value in an instance of Just.

just(5); // Just(5) (Maybe<number>)

nothing

nothing<T>(): Maybe<T>;

Creates an instance of Nothing.

nothing<number>(); // Nothing (Maybe<number>)

It's recommended to parametrize the function, otherwise the resolved type will be Maybe<unknown> and type won't flow through map, andThen and so on.

isJust

isJust<T>(value: Maybe<T>): value is Just<T>;

Returns true if a value is an instance of Just.

isJust(nothing()); // false

isNothing

isNothing<T>(value: Maybe<T>): value is Nothing;

Returns true if a value is an instance of Nothing.

isNothing(just(5)); // false
isNothing(undefined); // true
isNothing(null); // true
isNothing(nothing()); // true

withDefault

withDefault<A>(value: Maybe<A>, defaultValue: A): A;

If value is an instance of Just it returns its wrapped value, if it's an instance of Nothing it returns the defaultValue.

withDefault(just(5), 0); // 5
withDefault(nothing(), 'hola'); // 'hola'

caseOf

caseOf<A, B>(caseof: {Just: (v: A) => B; Nothing: () => B;}, value: Maybe<A>): B;

Run different computations depending on whether a Maybe is Just or Nothing and returns the result.

caseOf(
  {
    Nothing: () => 'Do nothing',
    Just: n => `Launch ${n} missiles`
  },
  just(5)
); // 'Launch 5 missiles'

map

map<A, B>(f: (a: A) => B, value: Maybe<A>): Maybe<B>;

Transforms a Maybe value with a given function.

const add1 = (n: number) => n + 1;
map(add1, just(4)); // Just<number>(5)
map(add1, nothing()); // Nothing

There are map2, map3, map4, map5 and mapN functions too:

map2<A, B, C>(
  f: (a: A, b: B) => C,
  a: Maybe<A>, b: Maybe<B>
): Maybe<C>

An example with map2:

const safeParseInt = (num: string): Maybe<number> => {
  const n = parseInt(num, 10);
  return isNaN(n) ? nothing() : just(n);
};
const sum = (x: number, y: number) => x + y;
const safeStringSum = (x: string, y: string) =>
  map2(sum, safeParseInt(x), safeParseInt(y));
safeStringSum('1', '2'); // Just<number>(3)
safeStringSum('a', '2'); // Nothing

If you need to parametrize the function with more than one argument, use the map that matches your parametrization.

mapN only accepts arguments of the same type)

map3<A, B, C, D>(
  f: (a: A, b: B, c: C) => D,
  a: Maybe<A>, b: Maybe<B>, c: Maybe<C>
): Maybe<D>
map4<A, B, C, D, E>(
  f: (a: A, b: B, c: C, d: D) => E,
  a: Maybe<A>, b: Maybe<B>, c: Maybe<C>, d: Maybe<D>
): Maybe<E>
map5<A, B, C, D, E, F>(
  f: (a: A, b: B, c: C, d: D, e: E) => F,
  a: Maybe<A>, b: Maybe<B>, c: Maybe<C>, d: Maybe<D>, e: Maybe<E>
): Maybe<F>
mapN<A, B>(
  f: (...a: A[]) => B,
  ...a: Maybe<A>[]
): Maybe<B>

andThen

andThen<A, B>(f: (a: A) => Maybe<B>, v: Maybe<A>): Maybe<B>;

Chains together many computations that may fail.

const head = (arr: string[]) => (arr.length > 0 ? just(arr[0]) : nothing());
andThen(head, just(['a', 'b', 'c'])); // Just<string>('a')
andThen(head, just([])); // Nothing

equals

equals<T>(a: Maybe<T>, b: Maybe<T>): boolean;

Compares two Maybe instances and returns true when both are Nothing or their wrapped values are strictly equal (===), false otherwise.

equals(just(5), just(5); // true
equals(just(6), just(5); // false
equals(nothing(), just(5); // false
equals(nothing(), nothing(); // true
equals(null, nothing(); // true
equals(undefined, nothing(); // true

ts.data.maybe's People

Contributors

joanllenas avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

jorgeucano

ts.data.maybe's Issues

Issue with "Is" functions

This is a very nice library. But one issue I came across was the fact that isNothing and isJust are defined as:

typescript
export declare const isJust: (value: Maybe) => boolean;
export declare const isNothing: (value: Maybe) => boolean;


...when it would be much better if they were defined as:

```typescript
export declare const isJust: <T>(value: Maybe<T>) => value is Just<T>;
export declare const isNothing: <T>(value: Maybe<T>) => value is Nothing;

This would allow type narrowing. Unfortunately, I can't write these myself because of another issue which is that you don't export the types for Just and Nothing. So they can't be referred to outside the package. I realized that I can use caseOf as well to narrow types, sometimes it is better to do this in an imperative vs. functional way (although I appreciate the option).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.