enummer
A 'real' Enum implementation for JavaScript with typesafety, ordinal support and comparison support. inspired by Java. Typed with Flow and supports ES-modules.
Installation
Simply do: npm install enummer
.
What is it?
A proper Enum implementation for Javascript. Unlike other Enum implementations, this one follows the Java implementation very strongly and supports:
- Ranked Enum constants (ordinals)
- Support for
instanceof
andisPrototypeof
checks. - Support for native comparisons with the
<
,>
and=== operatiors
. - Typesafety. Built with flow and throws runtime exceptions.
- Immutability. All Enum constants are immutable and accesses happens through getters.
Example 1
; const Day = Enum; Day // Day { MONDAY, TUESDAY, WEDNESDAY }DayMONDAY instanceof Day // trueDayMONDAY < DayTUESDAY // trueDayWEDNESDAY === DayWEDNESDAY // trueDay // [ MONDAY {}, TUESDAY {}, WEDNESDAY {} ]DayMONDAY // Day { MONDAY, TUESDAY, WEDNESDAY }Enum // true
Example 2 - with explicit ordinals
; const FavoriteColor = Enum; FavoriteColor // FavoriteColor { MONDAY, TUESDAY, WEDNESDAY }FavoriteColorBLUE > FavoriteColorRED // true, Blue has higher ordinal than red.
Example 3 - as an object with explicit ordinals
; const FavoriteColor = Enum; FavoriteColor // FavoriteColor { MONDAY, TUESDAY, WEDNESDAY }FavoriteColorBLUE > FavoriteColorRED // true, Blue has higher ordinal than red.
Example 4 - with floating point numbers an 'Infinity'
; const FavoriteColor = Enum; FavoriteColorBLUE > FavoriteColorRED // true, Blue has higher ordinal than red.FavoriteColorYELLOW > FavoriteColorBLUE // true, no value would ever be larger than 'YELLOW'.
Changelog:
v0.1.0:
- Added support for browsers that doesn't support
Object.entries()
andObject.keys()
. Previous versions didn't work in Safari due to missing support forObject.entries()
.
v0.0.9:
- Fixed a few typing errors.
v0.0.6:
- Enummer now supports floating point numbers for ordinals as well as setting
Infinity
as ordinal value.
v0.0.5:
- Enummer now supports an alternative syntax for enum constants. They can now be written as objects. For instance:
Enum
Is now acceptable. Note that you need to declare ordinals (a number) for each key.
v0.0.4:
- Previous versions wouldn't work in environments without native
class
support. This is fixed now. Added a missing semicolon.
v0.0.3:
- Updated package dependency and keywords.
v0.0.2:
- First release!
Usage
Import it in your project like this:
// or // or // or // or
Documentation
Construction
The Enum
class is abstract and can't be instanced directly. Instead, use the static define
method for constructing enums:
const MyEnum = "MyEnum" "a" "b" "c" // Throws a SyntaxError, Enum is an abstract class. const MyEnum = Enum // Works!
Ordinals:
The ranking order of your Enum types will by default increase with 1 for each constant. For instance:
const MyEnum = Enum; MyEnumaordinal === 0; //trueMyEnumbordinal === 1; //trueMyEnumcordinal === 2; //true
However, you can change this ordering however you like. Consider the following:
const MyEnum = Enum; MyEnumaordinal === 2; //trueMyEnumbordinal === 3; //trueMyEnumcordinal === 4; //true
Simply attach (n)
to each constant where n
equals the rank (ordinal). For instance, a(2)
gets the ordinal 2
.
All remaining values will have an increasing order in relation to that.
You can also set the ordering however you like:
const MyEnum = Enum; MyEnumaordinal === 2; //trueMyEnumbordinal === 5; //trueMyEnumcordinal === 10; //true
And even:
const MyEnum = Enum; MyEnumaordinal === 2; //trueMyEnumbordinal === 5; //trueMyEnumcordinal === 6; //true
Note that you can define your enum constants with objects instead. Using that notation, all enum constants needs to have an associated ordinal:
const MyEnum = Enum;
Comparisons
The ordinals allows us to do classic comparisons between Enum constants. For instance, consider the following:
const FavoriteColor = Enum; FavoriteColorBLUE > FavoriteColorRED // true, BLUE has higher ordinal than RED.FavoriteColorYELLOW > FavoriteColorBLUE // true, YELLOW has higher ordinal than BLUE.
Two Enum constants cannot have the same ordinal. This is because the ordinal is often stored in a database as representative of the Enum constant. Thus, two enum constants are only equal if there is referential equality:
FavoriteColorBLUE === FavoriteColorBLUE // true
Type safety
You can only construct a new Enum Type with strings. This is because the strings will be used as the names of the inner classes.
For instance, this will throw a TypeError
:
const MyEnum = Enum; // Throws a TypeErrorconst MyEnum = Enum // Throws a TypeError, first argument must be a string.
instanceof
and isPrototypeOf
Because the static define
method on the abstract Enum class generates a new Baseclass with subclasses for each given Enum constant, enummer generates 'real' enums that makes it possible to do type assertions. For instance, consider this Flow example:
const Day = Enum;DayMONDAY instanceof Day // true. { if !day instanceof Day throw ; console;}; // Prints 'wee!' to the console.
Generated Enum types has Enum
as their prototype. That means that the following is true:
const MyEnum = Enum;Enum // true