We could use a plain object to simulate an enumeration type. It's fine that if we just need to use this to store the value of a key and access the predefined value by a key. What if we need to store and read more informations by a key or read some information by value ?
Take the api documentation described by protocol buffers
as an example:
message SearchRequest {
enum Corpus {
UNIVERSAL = 0;
WEB = 1;
IMAGES = 2;
LOCAL = 3;
NEWS = 4;
PRODUCTS = 5;
VIDEO = 6;
}
Corpus corpus = 4;
}
In the above example, it define an value corpus
of enum
type Corpus
. When we communicate with the back end api, wo need to passed something like this:
const Corpus = {
UNIVERSAL: 0,
WEB: 1,
IMAGES: 2,
LOCAL: 3,
NEWS: 4,
PRODUCTS: 5,
VIDEO: 6,
}
const request = {
corpus: Corpus.UNIVERSAL,
}
In the context of communicating with the back end API, we can create an object to map the key like UNIVERSAL
to the value 0
and other enumeration values the same way. But if we want to add more information to the enumeration value? Such as detailed description and any other extra pieces of information. For example, we have a value 0
and we want to know which enumeration item has the value 0
, we also want to display the corresponding description for this value.
const CorpusText = {
[Corpus.UNIVERSAL]: 'Universal',
//...
[Corpus.VIDEO]: 'Video',
}
CorpusText[corpusValue]
The solution the above provided can meet our needs, but it's too troublesome. So we take rich-enum
as the more great solution.
This solution is apparent when we define the enum value, we attach more information with it, then through the key and extensible API to use the enumeration value in the form we need.
This module is distributed via npm which is bundled with node and
should be installed as one of your project's dependencies
:
npm install --save rich-enum
Define a powerful enumeration:
import RichEnum from 'rich-enum'
const CorpusEnum = new RichEnum({
UNIVERSAL: {
value: 0,
text: 'Universal',
},
WEB: {
value: 1,
text: 'Web',
},
IMAGES: {
value: 2,
text: 'Images',
},
LOCAL: {
value: 3,
text: 'Local',
},
NEWS: {
value: 4,
text: 'News',
},
PRODUCTS: {
value: 5,
text: 'Products',
},
VIDEO: {
value: 6,
text: 'Video',
},
})
Then use this:
const {value: Corpus} = CorpusEnum
/* read the value by key */
Corpus.UNIVERSAL // 0
Corpus.VIDEO // 6
/* read the text by value */
CorpusEnum.text[Corpus.UNIVERSAL] // 'Universal'
CorpusEnum.text[Corpus.VIDEO] // 'Video'
/* read the all details of one element */
CorpusEnum.UNIVERSAL // { key: 'UNIVERSAL', value: 0, text: 'UNIVERSAL' }
CorpusEnum.VIDEO // { key: 'VIDEO', value: 6, text: 'Video' }
/* loop the all enumerations with detailed information */
CorpusEnum.collection.forEach(({key, value, text}) => {
console.log({key, value, text})
// { key: 'UNIVERSAL', value: 0, text: 'Universal' }
// ...
// { key: 'VIDEO', value: 6, text: 'Video' }
})
The RichEnum
instance has properties whose key is the value
of an enumeration item, and the value is the property value
of the enumeration item for every property defined for enumeration items except property value
.
The property value
is the object whose key is the key
of an item, and value is the value of property value
in the properties.
For Example:
const enumeration = new RichEnumeration({
TYPE_A: {
value: 0,
text: 'Type A',
extra: 'Extra info',
xxx: 'xxx',
},
})
enumeration.value.TYPE_A // 0
enumeration.text[0] // 'Type A'
enumeration.extra[0] // 'Extra info'
enumeration.xxx[0] // 'xxx'
if you defined a rich enumeration object, it's fine for your most scenes to be used. What if you have some extra information need to be bound with the same key only for a specified scene ?
You're allowed to extend it to generate a new RichEnum
instance object, for example:
const SpecifiedCorpusEnum = CorpusEnum.extend({
UNIVERSAL: {
extra: 'Extra information of the universal',
},
})
CorpusEnum.UNIVERSAL // { key: 'UNIVERSAL', value: 0, text: 'Universal', extra: 'Extra information of the universal' }
CorpusEnum.UNIVERSAL.extra // 'Extra information of the universal'
The instance method new RichEnum().extend()
will merge the new detail object with the older one shallowly per key. And return a new instance, so it will not pollute the original instance.
I'm not aware of any, if you are please make a pull request and add it here!
Thanks goes to these people (emoji key):
Jianhua Cheng 💻 📖 🚇 |
---|
This project follows the all-contributors specification. Contributions of any kind welcome!
MIT