New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

ts-union

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ts-union

ADT sum types in ts that look similar to swift enums

  • 1.1.0
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
1.1K
increased by0.56%
Maintainers
1
Weekly downloads
 
Created
Source

ts-union

Tiny library (<1Kb gzipped) for algebraic sum types that looks similar to swift enums. Inspired by unionize and F# discriminated-unions

Installation

npm add ts-union

NOTE: uses features from typescript 2.8

Usage

Create

import { Union, t } from 'ts-union';

const PaymentMethod = Union({
  Cash: t(),
  Check: t<CheckNumber>(),
  CreditCard: t<CardType, CardNumber>()
});

type CheckNumber = number;
type CardType = 'MasterCard' | 'Visa';
type CardNumber = string;

Type constructors

const cash = PaymentMethod.Cash();
const check = PaymentMethod.Check(15566909);
const card = PaymentMethod.CreditCard('Visa', '1111-566-...');

// or destructure for simplicity
const { Cash, Check, CreditCard } = PaymentMethod;
const anotherCheck = Check(566541123);

Matching

const str = PaymentMethod.match(cash, {
  Cash: () => 'cash',
  Check: n => `check num: ${n.toString()}`,
  CreditCard: (type, n) => `${type} ${n}`
}); // cash

Also supports deferred (curried) matching and default case.

const toStr = PaymentMethod.match({
  Cash: () => 'cash',
  default: _v => 'not cash' // _v is the union obj
});

const str = toStr(card); //not cash

if (aka simplified match)

const str = PaymentMethod.if.Cash(cash, () => 'cash'); //cash
// typeof str === string | undefined

You can provide else case as well. In that case 'undefined' type will be removed.

// typeof str === string
const str = PaymentMethod.if.Check(
  cash,
  n => `check num: ${n.toString()}`,
  _v => 'not check' // _v is the union obj that is passed in
); // str === 'not check'

Type of resulted objects

At the moment types of cash, check, card are opaque.

type CashType = typeof cash;
// OpaqueUnion<{Cash:..., Check:..., CreditCard:...}>
// and it is the same for card and check

The OpaqueUnion<...> type for PaymentMethod is accessible via T phantom property

type PaymentMethodType = typeof PaymentMethod.T;
// OpaqueUnion<{Cash:..., Check:..., CreditCard:...}>

Api and implementation details

If you will try to log the value for check you will see an array.

console.log(PaymentMethod.Check(15566909));
// ['Check', 15566909]

All values are arrays. The first element is the key to match against and the rest is payload. I decided not to expose that through typings but I might reconsider that in the future. Although you cannot use it for redux action you can safely use it for redux state.

Api

How to define shape

const U = Union({
  Simple: t(), // no payload
  One: t<string>(), // one argument
  Const: t(3), // one constant argument that is baked in
  Two: t<string, number>(), // two arguments
  Three: t<string, number, boolean>() // three
});

Let's take a closer look at t function

export declare type Types = {
  (): NoData;
  <T>(): One<T>;
  <T>(val: T): Const<T>;
  <T1, T2>(): Two<T1, T2>;
  <T1, T2, T3>(): Three<T1, T2, T3>;
};
export declare const t: Types;

the actual implementation is pretty simple:

export const t: Types = ((val: any) => val) as any;

We just capture the constant and don't really care about the rest. Typescript will guide us to provide proper number of args for each case.

match accepts either a full set of props or a subset with default case.

// typedef for match function. Note there is a curried version
export type MatchFunc<Record> = {
  <Result>(cases: MatchCases<Record, Result>): (
    val: OpaqueUnion<Record>
  ) => Result;
  <Result>(val: OpaqueUnion<Record>, cases: MatchCases<Record, Result>): Result;
};

if either accepts a function that will be invoked (with a match) and/or else case.

// typedef for if case for one argument.
// Note it doesn't throw but can return undefined
{
    <R>(val: OpaqueUnion<Rec>, f: (a: A) => R): R | undefined;
    <R>(val: OpaqueUnion<Rec>, f: (a: A) => R, els: (v: OpaqueUnion<Rec>) => R): R;
}

Keywords

FAQs

Package last updated on 09 Apr 2018

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc