enum-fp
v1.0.2
Published
Functional enum type for javascript with simple pattern matching
Downloads
6
Maintainers
Readme
Enum-FP
Functional Enum type / Sum type for javascript with simple pattern matching
Checkout the docs for more information
Medium article on SumTypes using EnumFP
Install
To add the project to your project
yarn add enum-fp
Usage
Import it to your file
import Enum from 'enum-fp';
Create an enum type
const Action = Enum([ 'Add', 'Edit', 'Delete', 'Get' ]);
// Or with a fixed number of arguments
const Maybe = Enum({
Just: [ 'value' ],
Nothing: [],
});
Create an instance of the type using one of the contructors
const action = Action.Edit(2, 'Hello world');
Pattern matching
const Action = Enum([ 'Add', 'Edit', 'Delete', 'DeleteAll', 'Get' ]);
const logMessage = action => console.log('>>',
Action.match(action, {
Edit: (id, message) => `Editing [${id}] to "${message}"`,
Add: message => `Adding "${message}"`,
Delete: id => `Deleting [${id}]`,
DeleteAll: () => 'Deleting all entries',
_: () => 'Unknown action', // To handle default cases, use _
})
);
logMessage(Action.Add('Earth')); // >> Adding "Earth"
logMessage(Action.Add('Earth 2')); // >> Adding "Earth 2"
logMessage(Action.Add('Pluto')); // >> Adding "Pluto"
logMessage(Action.Edit(1, 'Mars')); // >> Editing [2] to "Mars"
logMessage(Action.Delete(2)); // >> Deleting [3]
logMessage(Action.Add('Pluto')); // >> Adding "Pluto"
logMessage(Action.DeleteAll()); // >> Deleting all entries
// As Get action is not handled in the pattern, it will execute the default
logMessage(Action.Get()); // >> Unknown action
Type validation
You can add strict type validation instead of argument descriptions. You can read more about types module here
import T from 'enum-fp/types';
const TodoAction = Enum({
Add: [ T.String('message') ],
SetChecked: [ T.Number('id'), T.Bool('isChecked') ],
Delete: [ T.Number('id') ],
Edit: [ T.Number('id'), T.String('message') ],
DeleteAll: [],
});
NOTE: The string passed to the functions are just for documentation purposes and are optional. It won't affect the behavior of the type in any way.
Enum use cases
In the react world
You can use it to manage react component state! Checkout the documentation
Safely work with empty/invalid states
- Working with invalid values
// Just an example. You should use `Maybe` functor in cases like these
const Value = Enum({ Invalid: [], Valid: ['value'] });
const getName = user => user && user.name
? Value.Valid(user.name)
: Value.Invalid();
const splitBySpace = Value.cata({
Valid: name => name.split(' '),
Invalid: () => [],
});
const [ firstName, lastName ] = compose(splitBySpace, getName, getUser)();
In the functional world
- Maybe
const Maybe = Enum({ Just: ['value'], Nothing: [] });
const fmap = fn => Maybe.cata({
Just: compose(Maybe.Just, fn),
Nothing: Maybe.Nothing,
});
- Either
const Either = Enum({ Left: ['error'], Right: ['value'] });
const fmap = fn => Either.cata({
Left: Either.Left,
Right: compose(Either.Right, fn),
});
const fmapFail = fn => Either.cata({
Left: compose(Either.Left, fn),
Right: Either.Right,
});