Code Monkey home page Code Monkey logo

coproduct's Introduction

coproduct

npm version coproduct workflow Documentation Maintenance License: MIT Twitter: guyingjie129

A small library improve better tagged-union supporting for TypeScript

Benefits

  • Small bundled size(just 1kb)
  • Easy to use with just a few apis to learn
  • Improving Type-Safety for your TypeScript Project via exhaustive pattern-matching

Installation

yarn add coproduct
npm install --save coproduct

Usage

Basic usage

import { Tagged, TaggedData, match } from 'coproduct';

export type Option<T> = TaggedData<'some', T> | Tagged<'none'>;

export const None = Tagged('none');
export const Some = TaggedData('some');

const show = <T>(data: Option<T>) => {
  return match(data).case({
    some: value => `some: ${value}`,
    none: () => 'none',
  });
};

const value0 = Some(1);
const value1 = None;

expect(show(value0)).toBe('some: 1');
expect(show(value1)).toBe('none');

// you can use if/else to match manually if you want
const show = <T>(data: Option<T>) => {
  if (data.tag === 'some') {
    return `some: ${data.some}`;
  } else if ((data.tag = 'none')) {
    return 'none';
  }
  throw new Error(`Unexpected data: ${data}`);
};

You don't need to define your own option type, coproduct has built-in Option and Result.

import { match, Option, Some, None, Result, Ok, Err } from 'coproduct';

const show = <T>(data: Option<T>) => {
  return match(data).case({
    some: value => `some: ${value}`,
    none: () => 'none',
  });
};

expect(show(Some(1))).toBe('some: 1');
expect(show(None)).toBe('none');

const showResult = <T>(result: Result<T>) => {
  return match(result).case({
    ok: value => `ok: ${value}`,
    err: value => `err: ${value}`,
  });
};

expect(showResult(Ok(1))).toBe('ok: 1');
expect(showResult(Err('error'))).toBe('err: error');

For redux app

// state type
type CounterState = {
  count: number;
};

// action type
type CounterAction =
  | Tagged<'incre'>
  | Tagged<'decre'>
  | TaggedData<'increBy', number>
  | TaggedData<'decreBy', number>;

// reducer type with match
const counterReducer = (
  state: CounterState,
  action: CounterAction
): CounterState => {
  return match(action).case({
    incre: () => ({
      ...state,
      count: state.count + 1,
    }),
    decre: () => ({
      ...state,
      count: state.count - 1,
    }),
    increBy: (value: number) => ({
      ...state,
      count: state.count + value,
    }),
    decreBy: (value: number) => ({
      ...state,
      count: state.count - value,
    }),
  });
};

// reducer type without match
const counterReducer = (
  state: CounterState,
  action: CounterAction
): CounterState => {
  if (action.tag === 'incre') {
    return {
      ...state,
      count: state.count + 1,
    };
  } else if (action.tag === 'decre') {
    return {
      ...state,
      count: state.count - 1,
    };
  } else if (action.tag === 'increBy') {
    return {
      ...state,
      count: state.count + action.increBy,
    };
  } else if (action.tag === 'decreBy') {
    return {
      ...state,
      count: state.count - action.decreBy,
    };
  }

  throw new Error(`Unexpected action: ${action}`);
};

Api

Tagged(string)

Tagged(tag) return a tagged object with { tag: tag } structure. It's useful for nullary case.

TaggedData(string)

TaggedData(tag) return a factory function with (data: T) => TaggedData<tag, T> signature. It's useful for the case that carried data

match(data).case(patterns)

match(data).case(patterns) perform exhaustive pattern-matching for data, every case in data should has its own visitor function.

match(data).partial(patterns)

match(data).partial(patterns) perform non-exhaustive pattern-matching for data.

Some(value)

Some(value) return the value with the Some<T> case of Option Type.

None

None is the value with the None case of Option Type

Ok(value)

Ok(value) return the value with the Ok<T> case of Result Type.

Err(message)

Err(message) return the value with the Err<E> case of Result Type.

Contribution Guide

# test
npm run test

# build
npm run build

Author

๐Ÿ‘ค Jade Gu

๐Ÿค Contributing

Contributions, issues and feature requests are welcome!

Feel free to check issues page.

Show your support

Give a โญ๏ธ if this project helped you!

๐Ÿ“ License

Copyright ยฉ 2022 Jade Gu.

This project is MIT licensed.

coproduct's People

Contributors

lucifier129 avatar

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.