UNPKG

enum-plus

Version:

A drop-in replacement for native enum. Like native enum but much better!

170 lines (164 loc) 5.08 kB
import { EnumItemClass } from "./enum-item"; import { EnumItemsArray } from "./enum-values"; import { ENUM_COLLECTION, ITEMS, KEYS, VALUES } from "./utils"; /** * **EN:** Enum collection extension base class, used to extend the Enums * * **CN:** 枚举集合扩展基类,用于扩展枚举 */ // @ts-expect-error: because of typing extend in tests // eslint-disable-next-line @typescript-eslint/no-extraneous-class export class EnumExtensionClass {} /** * **EN:** Enum collection * * **CN:** 枚举项集合 */ export class EnumCollectionClass extends EnumExtensionClass { items; keys; /** * **EN:** A boolean value indicates that this is an enum collection instance. * * **CN:** 布尔值,表示这是一个枚举集合实例 */ [ENUM_COLLECTION] = true; constructor(init = {}, options) { super(); // exclude number keys with a "reverse mapping" value, it means those "reverse mapping" keys of number enums const keys = Object.keys(init).filter(k => !(/^-?\d+$/.test(k) && k === `${init[init[k]] ?? ''}`)); const parsed = keys.map(key => parseEnumItem(init[key], key)); keys.forEach((key, index) => { const { value } = parsed[index]; // @ts-expect-error: because of dynamically define property this[key] = value; }); Object.freeze(keys); // @ts-expect-error: because use KEYS to avoid naming conflicts in case of 'keys' field name is taken this[Object.keys(init).some(k => k === 'keys') ? KEYS : 'keys'] = keys; // Build enum item data const items = new EnumItemsArray(init, options, ...keys.map((key, index) => { const { value, label } = parsed[index]; return new EnumItemClass(key, value, label, init[key], options).readonly(); })); // @ts-expect-error: because use ITEMS to avoid naming conflicts in case of 'items' field name is taken this[Object.keys(init).some(k => k === 'items') ? ITEMS : 'items'] = items; // @ts-expect-error: because use VALUES to avoid naming conflicts in case of 'values' field name is taken this[Object.keys(init).some(k => k === 'values') ? VALUES : 'values'] = items; // Override the `instanceof` operator rule // @ts-expect-error: because override the instanceof operator this[Symbol.hasInstance] = instance => { // intentionally use == to support both number and string format value return this.items.some( // eslint-disable-next-line eqeqeq i => instance == i.value || instance === i.key); }; Object.freeze(this); Object.freeze(this.items); Object.freeze(this.keys); } key(value) { return this.items.key(value); } label(keyOrValue) { return this.items.label(keyOrValue); } has(keyOrValue) { return this.items.has(keyOrValue); } toSelect(config) { return this.items.toSelect(config); } /** @deprecated use `toSelect` instead */ options(config) { return this.items.options(config); } toMenu() { return this.items.toMenu(); } /** @deprecated use `toMenu` instead */ menus() { return this.items.menus(); } toFilter() { return this.items.toFilter(); } /** @deprecated use `toFilter` instead */ filters() { return this.items.filters(); } toValueMap() { return this.items.toValueMap(); } /** @deprecated use `toValueMap` instead */ valuesEnum() { return this.items.valuesEnum(); } // eslint-disable-next-line @typescript-eslint/ban-types raw(value) { if (value != null) { return this.items.raw(value); } else { return this.items.raw(); } } get valueType() { return this.items.valueType; } get keyType() { return this.items.keyType; } get rawType() { return this.items.rawType; } } function parseEnumItem(init, key) { let value; let label; if (init != null) { if (typeof init === 'number' || typeof init === 'string' || typeof init === 'symbol') { value = init; label = key; } else if (typeof init === 'object') { // Initialize using object if (Object.prototype.toString.call(init) === '[object Object]') { if ('value' in init && Object.keys(init).some(k => k === 'value')) { // type of {value, label} value = init.value ?? key; if ('label' in init && Object.keys(init).some(k => k === 'label')) { label = init.label; } else { label = key; } } else if ('label' in init && Object.keys(init).some(k => k === 'label')) { // typeof {label} value = key; label = init.label ?? key; } else { // {} empty object value = key; label = key; } } else { // Probably Date, RegExp and other primitive types value = init; label = key; } } else { throw new Error(`Invalid enum item: ${JSON.stringify(init)}`); } } else { value = key; label = key; } return { value, label }; } //# sourceMappingURL=enum-collection.js.map