A small library aims to improve better tagged-unions/discriminated-unions supporting for TypeScript

Overview

coproduct

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

A small library aims to improve better tagged-unions/discriminated-unions 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

For redux app

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

// action type
type CounterAction =
  | {
      type: 'incre';
    }
  | {
      type: 'decre';
    }
  | {
      type: 'increBy';
      step: number;
    }
  | {
      type: 'decreBy';
      step: number;
    };

// reducer 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: ({ step }) => ({
      ...state,
      count: state.count + step,
    }),
    decreBy: ({ step }) => ({
      ...state,
      count: state.count - step,
    }),
  });
};

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

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

Basic usage

import { match } from 'coproduct';

export type Option<T> = {
  type: 'Some',
  value: T
} | {
  type: 'None'
}

export const None = {
  type: 'None' as const;
}
export const Some = <T>(value: T) => ({
  type: 'Some' as const,
  value,
});

const show = <T>(data: Option<T>) => {
  return match(data).case({
    Some: data => `some: ${data.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.type === 'Some') {
    return `some: ${data.some}`;
  } else if (data.type === '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: data => `some: ${data.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: data => `ok: ${data.value}`,
    Err: error => `err: ${error.info}`,
  });
};

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

Api

match(data).case(patterns)

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

Note: you can use _: () => R as default handler for unmatched case.

createMatch(tagField) => match

You can create your own match function with tagField to match your data.

The default match of coproduct was created via createMatch('type')

const match = createMatch('tag');

type Data =
  | {
      tag: 'a';
      value: string;
    }
  | {
      tag: 'b';
      value: number;
    };

const handleData = (data: Data) => {
  return match(data).case({
    a: data => `a: ${data.value}`,
    b: data => `b: ${data.value}`,
  });
};

handleData({ tag: 'a', value: 'hello' }); // 'a: hello'
handleData({ tag: 'b', value: 1 }); // 'b: 1'

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.

Caveats

  • The name $tag is reserved for $tag property of tagged object, it can't be used as a tag name.
  • The symbol _ can't be used as a tag name since it's a reserved filed in coproduct as placeholder for default case.

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.

You might also like...

Inter Process Communication Module for node supporting Unix sockets, TCP, TLS, and UDP. Giving lightning speed on Linux, Mac, and Windows. Neural Networking in Node.JS

Inter Process Communication Module for node supporting Unix sockets, TCP, TLS, and UDP. Giving lightning speed on Linux, Mac, and Windows. Neural Networking in Node.JS

Inter Process Communication Module for node supporting Unix sockets, TCP, TLS, and UDP. Giving lightning speed on Linux, Mac, and Windows. Neural Networking in Node.JS

Dec 9, 2022

A guide that teach you build a custom version of chromium on macOS/Windows/Linux that supporting hardware/software HEVC decoding.

enable-chromium-hevc-hardware-decoding A guide that teach you build a custom version of chromium on macOS/Windows/Linux that supports hardware/softwar

Jan 1, 2023

"Pizza Party!" - A Jovo V4 master template supporting a lot of features

"Pizza Party!" - Yet another Jovo V4 master template supporting a lot of features There are a lot of Jovo examples around but I did not find any proje

Aug 2, 2022

Syntax Highlighter supporting multiple languages, themes, fonts, highlighting from a URL, local file or post text.

Syntax Highlighter supporting multiple languages, themes, fonts, highlighting from a URL, local file or post text.

Crayon Syntax Highlighter Supports multiple languages, themes, fonts, highlighting from a URL, local file or post text. Written in PHP and jQuery. Cra

Nov 26, 2022

Phaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.

Phaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.

Phaser - HTML5 Game Framework Phaser is a fast, free, and fun open source HTML5 game framework that offers WebGL and Canvas rendering across desktop a

Jan 7, 2023

Superlight vanilla javascript plugin, for modern web dropdowns. Supporting multi-options, search and images. Designed to be seamlessly themed

Superlight vanilla javascript plugin, for modern web dropdowns. Supporting multi-options, search and images. Designed to be seamlessly themed

Superlight vanilla javascript dropdowns by LCweb Need to jump off of jQuery (or any other) dependency? Other packages are too heavy to just tweak sele

Dec 26, 2022

Serialize an HTML Form to a JavaScript Object, supporting nested attributes and arrays.

jquery.serializeJSON Adds the method .serializeJSON() to jQuery to serializes a form into a JavaScript Object. Supports the same format for nested par

Dec 12, 2022

A table component for your Mantine data-rich applications, supporting asynchronous data loading, column sorting, custom cell data rendering, row context menus, dark theme, and more.

A table component for your Mantine data-rich applications, supporting asynchronous data loading, column sorting, custom cell data rendering, row context menus, dark theme, and more.

Mantine DataTable A "dark-theme aware" table component for your Mantine UI data-rich applications, featuring asynchronous data loading support, pagina

Jan 4, 2023

URL Shortener API in NodeJS supporting pagination, sort params and lot more

URL Shortener API in NodeJS supporting pagination, sort params and lot more

node-url-shortener Built with ❤️ in NodeJS A simple URL Shortner REST API that uses shortid npm package to generate short endpoints for your long URL.

Sep 22, 2022
Owner
工业聚
Thinking, coding and writing for fun
工业聚
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
Generate tagged PDFs from your Eleventy site

eleventy-plugin-prince-pdf This plugin makes it easy to generate tagged PDFs from webpages in your Eleventy site, using Prince. What this does This pl

null 4 Feb 9, 2022
A small application to improve worklow of SkyTemple users.

SkyTemple Helper A small application to improve workflow of SkyTemple users. You can tell because the icon is brelpog. Some applications will require

null 3 Oct 4, 2022
A small javascript DOM manipulation library based on Jquery's syntax. Acts as a small utility library with the most common functions.

Quantdom JS Quantdom is a very small (about 600 bytes when ran through terser & gzipped) dom danipulation library that uuses a Jquery like syntax and

Sean McQuaid 7 Aug 16, 2022
Cross provider map drawing library, supporting Mapbox, Google Maps and Leaflet out the box

Terra Draw Frictionless map drawing across mapping providers. TerraDraw centralises map drawing logic and provides a host of out the box drawing modes

James Milner 106 Dec 31, 2022
'event-driven' library aims to simplify building backends in an event driven style

'event-driven' library aims to simplify building backends in an event driven style(event driven architecture). For message broker, light weight Redis Stream is used and for event store, the well known NoSQL database, MongoDB, is used.

Sihoon Kim 11 Jan 4, 2023
✏️ A small jQuery extension to turn a static HTML table into an editable one. For quickly populating a small table with JSON data, letting the user modify it with validation, and then getting JSON data back out.

jquery-editable-table A small jQuery extension to turn an HTML table editable for fast data entry and validation Demo ?? https://jsfiddle.net/torrobin

Tor 7 Jul 31, 2022
Next-gen mobile first analytics server (think Mixpanel, Google Analytics) with built-in encryption supporting HTTP2 and gRPC. Node.js, headless, API-only, horizontally scaleable.

Introduction to Awacs Next-gen behavior analysis server (think Mixpanel, Google Analytics) with built-in encryption supporting HTTP2 and gRPC. Node.js

Socketkit 52 Dec 19, 2022