@mrbarrysoftware/js-enumerize
v1.1.0
Published
- **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 feature
Downloads
2
Readme
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:
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, likejust
andnothing
, 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>)