Skip to content
This repository has been archived by the owner on Mar 23, 2020. It is now read-only.
/ ts-when Public archive

JavaScript functional implementation of switch/case written in TypeScript

License

Notifications You must be signed in to change notification settings

nawordar/ts-when

Repository files navigation

CircleCI codecov Maintainability devDependencies Status NPM version

ts-when

JavaScript functional implementation of switch/case written in TypeScript

Note

This is a fork of a great library when-switch which seems no longer maintained. Now I stopped maintaining this fork too. If you would like to have a similar behaviour built in JavaScript, please support the pattern matching proposal! This extension will never be as good as the native support.

Table of contents

Usage

You can use ts-when in a functional way, using a single expression:

Strict Equality

import when from 'ts-switch'

const getDrinkPrice = drink =>
  when(drink)
    .is('Coke', 1.5)
    .is('Pepsi', 1.8)
    .else(2.0)

Assertion-based Matching

You can return a value when given assertion is correct

const x = when
  .true(someVariable === true, "some variable is true")
  .else("some variable is false")

Structural Matching

You can use match method with any object exposing a test method.

Regular Expressions

const getCaseStyle = text =>
  when(text)
    .match(/^([A-Z][a-z]*)+$/, 'UpperCamelCase')
    .match(/^([a-z]+[A-Z][a-z]*)+$/, 'LowerCamelCase')
    .match(/^([a-z]+_[a-z]+)+$/, 'SnakeCase')
    .else('Unknown')

Custom Type Guard Matcher

type SpaceObject = { x: number; y: number; z: number }
type Cube = SpaceObject & { width: number }
type Sphere = SpaceObject & { radius: number }

const SpaceObjectSchema = {
  test: (_: any): _ is SpaceObject =>
    typeof _.x === 'number' &&
    typeof _.y === 'number' &&
    typeof _.z === 'number'
}

const CubeSchema = {
  test: (_: any): _ is Cube =>
    typeof _.width === 'number' && SpaceObjectSchema.test(_)
}

const SphereSchema = {
  test: (_: any): _ is Sphere =>
    typeof _.radius === 'number' && SpaceObjectSchema.test(_)
}

const getObjectVolume = (object: SpaceObject) =>
  // Each match handler will receive correct static type
  when(object)
    .match(CubeSchema, cube => cube.width ** 3)
    .match(SphereSchema, sphere => Math.PI * 3 / 4 * sphere.radius ** 3)
    .else(_ => null)

match and is can both be used in the same when expression.

TypeScript

when is fully compatible with TypeScript, and will check the types you return in each is expression:

const getDrinkPrice = (drink: 'Pepsi' | 'Coke' | 'Orangina'): number =>
  when(drink)
    .is('Coke', 1.5)
    .is('Pepsi', 1.8)
    .else(2.0)

Here the return type of the when expression will be number

Union types

For each is or else expression added to the current when expression, the type is added as an union to the previous type.

const getDrinkPrice = (drink: 'Pepsi' | 'Coke' | 'Orangina') =>
  when(drink)
    .is('Coke', 1.5)
    .is('Pepsi', true)
    .else('Free')

Here the return type of getDrinkPrice expression will be number | string | boolean

About

JavaScript functional implementation of switch/case written in TypeScript

Resources

License

Stars

Watchers

Forks

Packages

No packages published