enumerated_types

1.1.0 • Public • Published

Table of Contents

  1. Enumerated Types for Javascript
    1. Getting Started
      1. Installing
    2. Usage
      1. Enumerated constants with Enum
      2. Enumerated constants with EnumObjects
      3. Binary options with Flags
      4. Constrained values with EnumeratedRange

Enumerated Types for Javascript

Full featured, extensible enumerations for javascript.

Getting Started

Installing

  1. Node

    npm install enumerated_types
    
  2. Browser

    Download the package from here.

    The js folder contains two files: enumerated_types.js and enumerated_module.js.

    To use enumerated_types.js load it from an HTML script tag:

    <script type='text/javascript' src='/js/enumerated_types.js'></script>
    

    To use enumerated_module.js import the required objects/functions:

    import * as enumeration from '/js/enumerated_module.js'
    import {Enum} from '/js/enumerated_module.js'
    

Usage

The enumeration package provides a base object, EnumerationBase, on which to base enumerated types.

The following methods are available on all enumerated types:

Method Description Default Implementation
first() Returns the first value in the enumeration no
fromInt(i) Returns an enumeration given an integer no
isEqualTo(other) Tests two enumerations for equality yes
isGreater(other) Test if one enumeration is greater than another yes
isGreaterOrEqualTo(other) Test if one enumeration is greater than or equal to another yes
isLess(other) Test if one enumeration is less than another yes
isLessOrEqualTo(other) Test if one enumeration is less than or equal to another yes
iterator(from, to) Gives an iterator between the (optional) given enumeration values yes
last() Returns the last value of the enumeration no
methods(methodsobject) Adds additional methods to the enumerated type yes
next() Returns the next enumeration value in the sequence yes
previous() Returns the previous enumeration value in the sequence yes
toInt() Converts an enumeration value to its integer representation no
toString() Converts an enumeration value to a string representation no

When creating your own enumerated types, the methods marks "no" under 'Default Implementation' must be implemented. All other methods may be overridden if required.

Enumerated constants with Enum

Use the Enum function to create a set of constants:

Color = Enum(
    'RED',
    'ORANGE',
    'YELLOW',
    'GREEN',
    'BLUE',
    'INDIGO',
    'VIOLET'
)

Constants can be converted to and from their interger equivalents:

Color.fromInt(3)    // Color.GREEN
Color.GREEN.toInt() // 3

And you can also get the string representation:

Color.RED.toString()    // 'RED'
Color.VIOLET.toString() // 'VIOLET'

This allows you to use the constants as if they were object keys.

someObj = {
    Color.RED : 'Something having to do with red.',
    Color.BLUE : 'Something to do with blue.',
}

In the above example the actual keys are the strings RED and BLUE because javascript calls toString() automatically when an object is used as a key.

You can navigate forwards and backwards through the sequence using next() and previous(). Going past the end of the sequence throws and error:

Color.RED.next()        // Color.ORANGE
Color.INDIGO.previous() // Color.BLUE
Color.RED.previous()    // Error!
Color.VIOLET.next()     // Error!

To get around that you can get an iterator() and loop through the values with a for loop or with forEach.

// Prints all the colors to the console.
for (let color of Color.iterator()) {
    ; console.log(color.toString()) 
}

// Also prints all the colors to the console.
Color.iterator().forEach(color => console.log(color.toString()))

The iterator() method takes two parameters from and to, both optional, so you can iterate though a subset of the values.

Color.iterator(Color.GREEN, Color.INDIGO)
    .forEach(color => console.log(color.toString()))

And can even be used to iterate though the values in reverse order if desired.

Color.iterator(Color.last(), Color.first())
    .forEach(color => console.log(color.toString()))

The constants can be compared in a number of ways.

Color.RED.isLess(Color.BLUE)                // true
Color.VIOLET.isLess(Color.BLUE)             // false
Color.VIOLET.isGreater(Color.BLUE)          // true
Color.VIOLET.isGreater(Color.VIOLET)        // false
Color.VIOLET.isGreaterOrEqual(Color.VIOLET) // true
Color.RED.isEqual(Color.GREEN)              // false
Color.RED.isEqual(Color.RED)                // true
Color.RED === Color.GREEN                   // false
Color.RED === Color.RED                     // true

Finally, the type can be extended with addtional methods:

Answers = Enum('YES', 'NO', 'MAYBE').methods({
    toLowerCase() {
	return this.toString().toLowerCase();
    },
    capitalize() {
	const as_string = this.toString();
	const first = as_string[0];
	const rest = as_string.substring(1).toLowerCase();
	return `${first}${rest}`;
    }
})

console.log(Answers.YES.toLowerCase());  // yes
console.log(Answers.Maybe.capitalize()); // Maybe

You can call methods at most once. After that the prototype object is frozen and can't be modified further.

Enumerated constants with EnumObjects

The EnumObjects function works in much the same way as Enum but instead of a list of strings it takes an object as input. Each key becomes a constant and, unlike Enum each contant can have its own additional properties and methods.

Animal = E.EnumObjects({
    DOG : {
	speak() {
	    console.log('woof!');
	}
    },
    CAT : {
	speak() {
	    console.log('meow!');
	}
    },
    GIRAFFE : {}
}).methods({
    speak() {
	console.log('...');
    }
})

Animal.DOG.speak()     // woof!
Animal.CAT.speak()     // meow!
Animal.GIRAFFE.speak() // ...
Animal.iterator().forEach(a => a.speak())

In particular, notice that we can use methods to define default methods which will apply to all constants that don't specifically override it: DOG and CAT use their own behaviour while GIRAFFE uses the default.

Binary options with Flags

Flags are like enumerated constants except, instead of being sequential, each flag's value is a power of 2.

Options = Flags('A', 'B', 'C', 'D')
Options.A.toInt() // 1
Options.B.toInt() // 2
Options.C.toInt() // 4
Options.D.toInt() // 8

This means you can combine multiple flags into a single integer value using the bitwise OR (|) operator:

Options.A | Options.B | Options.D;  // 11

Flag types have an additional method, listFromInt(), which returns a list of all options represented by a given integer.

Options.listFromInt(Options.A | Options.B | Options.D);  // [Options.A, Options.B, Options.D]
Options.listFromInt(12)                                  // [Options.C, Options.D]
Options.listFromInt(0)                                   // []
Options.listFromInt(16)                                  // Error! Out of range.

Constrained values with EnumeratedRange

Another type of enumeration are values constrained to a particular range: values between 1 and 10, for instance. In this case it's actually the number we're interested in not a symbolic name and there are, generally, too many possible values to create them as contants. Instead we can create an EnumeratedRange.

SmallNum = EnumeratedRange(1, 10, 'SmallNum')

The resulting value, SmallNum in this example, can then be used to construct values in this range. The third parameter is optional and is only relevant when calling toString(). Trying to create a value outside of the allowed range throws an error.

x = SmallNum(1)
y = SmallNum(5)
z = SmallNum(10)
error1 = SmallNum(0)  // Error!
error2 = SmallNum(11) // Error!

Even though the values don't exist as constants you can still get an iterator over all the possible values:

// Prints all SmallNum values from 1 to 10
SmallNum.iterator().forEach(n => console.log(n))

Package Sidebar

Install

npm i enumerated_types

Weekly Downloads

2

Version

1.1.0

License

BSD-3-Clause

Unpacked Size

70.5 kB

Total Files

7

Last publish

Collaborators

  • jasondelaat