@mrbarrysoftware/js-enumerize

1.1.0 • Public • Published

jsEnumerize

  • Simple - No tricks, not complicated code, just plain old javascript.
  • Consistent - Enforce checking against the real value.
  • Correct - Enum values shouldn't exist outside of your enum.
  • Modern - Uses latest javascript language features for a seamless experience.

Table of Contents

Getting Started

Install from npm or yarn:

npm i --save @mrbarrysoftware/js-enumerize

What sort of enumeration is this?

This is some sort of union enumeration type, made popular from languages like Elm and Haskell.

First and foremost, this is just a type that has an affinity to a set of constants. For instance, you could write a simple boolean enumeration like this: const bool = enumerize({ true: [], false: [] }) To use the bool enum type, bool exposes methods for each item passed into jsEnumerize. In this case, we have bool.true() and bool.false().

Second, each enumeration supports pattern matching. This makes it easy to handle the various ways the enum can be used in one handy function. For instance, using the above bool type, let's say we want to print something on the screen based on whether or not the bool value is true: const returnedString = bool.caseOf({ true: () => 'The value is true', false: () => 'The value is false' }, bool.true());

Usage

Import it

// es6/babel
import enumerize, { Any } from 'js-enumerize';

// from unpkg
import enumerize, { Any } from 'https://unpkg.com/@mrbarrysoftware/js-enumerize?module=1';

// from script tag
// <script src="https://unpkg.com/@mrbarrysoftware/js-enumerize"></script>
const { enumerize } = window;
const { Any } = enumerize;

// node
const enumerize = require('js-enumerize');
const { Any } = enumerize;

Simple

Let's make a simple enum type, Maybe, which can have a value, or have nothing.

const Maybe = enumerize({
  just: [Any],
  nothing: [],
});

const greet = value => Maybe.caseOf({
  just: name => `Hello ${name}`,
  nothing: () => `Nice to meet you, what's your name?`,
}, value);

console.log(greet(Maybe.just('mrozbarry'))); // Hello mrozbarry
console.log(greet(Maybe.nothing()));         // Nice to meet you, what's your name

In our case, we are saying that when our Maybe has a value, it has to be a singular Any value. This could be more specific, like String, a custom class you've made, or multiple type constructors.

Maybe.caseOf allows us to extract the values we store. For a Maybe, we can either extract the just value, or handle the case when we don't have data.

Important: YourEnumType.caseOf of any enumeration must account for all cases. This means each type key you declare, like just and nothing, must exist as keys in your .caseOf call. If you want to skip cases, use the _ fall-through.

Real-life Use Case

What if we want to track the progress of an action, and return the result of that at the end? Here's a progress enum type, and how we could render that with a JSX function component:

const Progress = enumerize({
  incomplete: [],
  partial: [Number, Number],
  complete: [Any],
  error: [Error],
});

const SomeComponent = ({ progress }) => Progress.caseOf({
  incomplete: () => (
    <section>
      <PendingIcon />
      <ProgressBar percent={0} />
    </section>
  ),
  partial: (current, total) => (
    <section>
      <ActiveIcon />
      <ProgressBar percent={current / total} />
    </section>
  ),
  complete: (resultingThing) => (
    <section>
      <CheckIcon />
      <DisplayThing thing={resultingThing} />
    </section>
  ),
  error: (error) => (
    <section>
      <Error message={error.toString()} />
    </section>
  ),
}, progress);

API

enumerize(definition[, name]) : class Enumeration


Create a new enumeration.

Parameters

definition (required)

An object with the following shape descriptor:

{
  nameOfUnionType: [String, Number, ...otherTypes],
  otherType: [Boolean, Object, Function],
}

Each key is a union type in this enumeration. For instance, if we were to make a boolean, the two keys would likely be true and false. Each key must have an array of type constructors. This array can be empty, contain built-in types, custom classes, or other enumerized() types.

name (optional)

A string name to assign the enumerization. This is handy for debugging using the two toString() methods off Enumeration. It defaults to 'Enumeration'.

Return value

Returns a unique Enumeration class.

Notes

None

Example

const MyEnumUnion = enumerize({
  foo: [String, Boolean],
  bar: [Function],
  baz: [],
}, 'MyEnumUnion');

class Enumeration


A class representing a enumerated union type. Each instance is a union value of this type.

Enumeration.toString() : String

A string representation of an enumeration.

Parameters

None

Return Value

Will take the form of Maybe<just|nothing>.

Notes

None

Example

const MyEnumUnion = enumerize({
  foo: [String, Boolean],
  bar: [Function],
  baz: [],
}, 'MyEnumUnion');

console.log(MyEnumUnion.toString()) // Output: MyEnumUnion<foo|bar|baz>

Enumeration.caseOf(objectOfDefinitionKeys, enumerationValue) : Any

A method that acts like a decode/switch statement of the various union types of an enumeration. Given a value generated from your enumeration, it will call the supplied keyed function in objectOfDefinitionKeys and return that value.

Parameters

objectOfDefinitionKeys (required)

An object taking a shape similar to the definition in a union. Instead of arrays with constructors as values, the values should be functions that accept the ordered parameters reflected in the definition. These functions can return a value that is piped to the return value of the caseOf function. All keys from the definition are required to be present, but it is possible to create a fall-through using the _ key.

valueFromEnumeration (required)

A value generated from your enumeration. This will typically take the form of YourEnumUnion.someType(...parameters). The types of your parameters must match the expected type constructors given to your enumerize call.

Return Value

The value returned from the appropriate keyed function.

Notes

This function will throw under the following conditions:

  • If you have missing definition keys and do not supply a _.
  • If you have definition keys that do not exist in the original enumerize definition.
  • If you pass a value that is not of the same enumeration type.

Example

Using all definition keys:

const greet = maybeName => Maybe.caseOf({
  just: name => `Hello ${name}`,
  nothing: () => 'Hey stranger',
}, maybeName);

console.log(greet(Maybe.just('Alex'))); // Hello Alex
console.log(greet(Maybe.nothing()));    // Hey stranger

Using a _ fall-through:

const greet = maybeName => Maybe.caseOf({
  nothing: () => 'Hey stranger',
  _: () => `Hello friend`,
}, maybeName);

console.log(greet(Maybe.just('Alex'))); // Hello friend
console.log(greet(Maybe.nothing()));    // Hey stranger

Enumeration.{{type}}(...params) : Enumeration instance

When you create an enumerization with union types, each type gets a function to create that union type.

Parameters

A dynamic list of parameters that must match the constructor types provided in your enumerize definition.

Return value

An instance of your enumeration.

Notes

If the params don't match their respective type, an error will be thrown.

Example

const MyType = enumerize({
  foo: [String, Number],
  bar: [Boolean],
}, 'MyType');

console.log(MyType.foo('hello', 42)); // Outputs: MyType.foo(hello, 42)
console.log(MyType.bar(true));        // Outputs: MyType.bar(true)
console.log(MyType.foo({}, false));   // Throws a TypeError

const isInstanceOfMyType = MyType.foo('hello', 42) instanceof MyType;
console.log(isInstanceOfMyType);      // Outputs: true

Enumeration#toString() : String

Output the type and values of an Enumeration instance.

Parameters

None

Return value

Returns a string representation of your enumeration value.

Notes

None

Example

const MyType = enumerize({
  foo: [String, Number],
  bar: [Boolean],
}, 'MyType');

const value = MyType.foo('hello', 42);
console.log(value.toString()); // Outputs: MyType.foo(hello, 42)

Enumeration#toTypeString() : String

Output the type and parameter types of an enumeration instance.

Parameters

None

Return value

A string representation of your enumeration type's parameter types.

Notes

None

Examples

const MyType = enumerize({
  foo: [String, Number],
  bar: [Boolean],
}, 'MyType');

const value = MyType.foo('hello', 42);
console.log(value.toTypeString()); // Outputs: MyType.foo(<String>, <Number>)

Other Important Stuff

  • Check out the license here
  • And other cool stuff here

Readme

Keywords

none

Package Sidebar

Install

npm i @mrbarrysoftware/js-enumerize

Weekly Downloads

0

Version

1.1.0

License

MIT

Unpacked Size

40.8 kB

Total Files

22

Last publish

Collaborators

  • mrozbarry