Socket
Socket
Sign inDemoInstall

ts-enum-util

Package Overview
Dependencies
Maintainers
1
Versions
40
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ts-enum-util - npm Package Compare versions

Comparing version 0.0.2 to 0.0.3

261

dist/commonjs/index.js
"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
__export(require("./Enum"));
__export(require("./EnumWrapper"));
/**
* A generic wrapper for any enum-like value (see {@link EnumLike} type for more explanation).
* Provides utilities for runtime processing of an enum's values and keys, with strict compile-time
* type safety.
*
* Enum cannot be directly instantiated. Use one of the following to get/create an Enum
* instance:
* - {@link Enum.get}
* - {@link Enum.create}
*
* @template V - Type of the enum value.
* @template T - Type of the enum-like object that is being wrapped.
*/
var Enum = /** @class */ (function () {
/**
* Create a new Enum instance.
* This is for internal use only.
* Use one of the following to publicly get/create an Enum
* instance:
* - {@link Enum.get}
* - {@link Enum.create}
*
* @param enumObj - An enum-like object. See the {@link EnumLike} type for more explanation.
*/
function Enum(enumObj) {
var _this = this;
this.enumObj = enumObj;
/**
* Set of all values for this enum.
*/
this.valueSet = new Set();
/**
* Map of enum value -> enum key.
* Used for reverse key lookups.
*/
this.keysByValueMap = new Map();
this.keySet = new Set(Object.keys(enumObj).filter(
// Need to include only keys that cannot be parsed as numbers.
// This is necessary to ignore the reverse-lookup entries that are automatically added
// to numeric enums.
function (key) { return isNaN(parseInt(key, 10)); }));
this.keySet.forEach(function (key) {
var value = enumObj[key];
_this.valueSet.add(value);
_this.keysByValueMap.set(value, key);
});
}
/**
* Creates a new Enum for an enum-like object.
* You probably want to use {@link Enum.get} for any typical enums, because it will
* cache the result.
* This method may be useful if you want an Enum for an enum-like object that is dynamically
* built at runtime, is used only within a limited/tranient context in the application, and is likely
* to clutter the cache without ever being reused.
* @param enumObj - An enum-like object.
* @return A new instance of Enum for the provided enumObj.
*/
Enum.create = function (enumObj) {
return new Enum(enumObj);
};
/**
* Creates a new Enum, or returns a cached Enum if one has already been created for the same
* object via {@link Enum.get}.
* This is most useful for typical enums that are statically defined, because the cached Enum instance
* will be quickly retrieved/reused on every sebsequent call to get() for the same enum object.
* Use {@link Enum.create} if you don't want the Enum to be cached.
* @param enumObj - An enum-like object.
* @return An instance of Enum for the provided enumObj.
*/
Enum.get = function (enumObj) {
var result = this.instancesCache.get(enumObj);
if (!result) {
result = this.create(enumObj);
this.instancesCache.set(enumObj, result);
}
return result;
};
Object.defineProperty(Enum.prototype, "size", {
/**
* The number of entries in this enum.
*/
get: function () {
return this.keySet.size;
},
enumerable: true,
configurable: true
});
/**
* Get a list of this enum's keys.
* @return A list of this enum's keys.
*/
Enum.prototype.getKeys = function () {
return Array.from(this.keySet.values());
};
/**
* Get a list of this enum's values.
* NOTE: If this enum has any duplicate values, only unique values will be returned, and the
* length of the list will be less than {@link Enum#size}.
* @return A list of this enum's values.
*/
Enum.prototype.getValues = function () {
return Array.from(this.valueSet.values());
};
/**
* Get a list of this enum's entries as [key, value] tuples.
* @return A list of this enum's entries as [key, value] tuples.
*/
Enum.prototype.getEntries = function () {
return Array.from(this);
};
/**
* Get an iterator for this enum's keys.
* @return An iterator that iterates over this enum's keys.
*/
Enum.prototype.keys = function () {
return this.keySet.values();
};
/**
* Get an iterator for this enum's values.
* NOTE: If this enum has any duplicate values, only unique values will be iterated, and the
* number of values iterated will be less than {@link Enum#size}.
* @return An iterator that iterates over this enum's values.
*/
Enum.prototype.values = function () {
return this.valueSet.values();
};
/**
* Get an iterator for this enum's entries as [key, value] tuples.
* @return An iterator that iterates over this enum's entries as [key, value] tuples.
*/
Enum.prototype.entries = function () {
var _this = this;
var keyIterator = this.keys();
return _a = {
next: function () {
var nextKey = keyIterator.next();
return {
done: nextKey.done,
// "as any" cast is necessary to work around this bug:
// https://github.com/Microsoft/TypeScript/issues/11375
value: nextKey.done ? undefined : [nextKey.value, _this.enumObj[nextKey.value]]
};
}
},
_a[Symbol.iterator] = function () {
return this;
},
_a;
var _a;
};
/**
* Get an iterator for this enum's entries as [key, value] tuples.
* @return An iterator that iterates over this enum's entries as [key, value] tuples.
*/
Enum.prototype[Symbol.iterator] = function () {
return this.entries();
};
/**
* Calls the provided iteratee on each item in this enum.
* See {@link Enum.Iteratee} for the signature of the iteratee.
* The return value of the iteratee is ignored.
* @param iteratee - The iteratee.
* @param context - If provided, then the iteratee will be called with the context as its "this" value.
*/
Enum.prototype.forEach = function (iteratee, context) {
var _this = this;
this.keySet.forEach(function (key) {
iteratee.call(context, _this.enumObj[key], key, _this.enumObj);
});
};
/**
* Maps this enum's entries to a new list of values.
* Builds a new array containing the results of calling the provided iteratee on each item in this enum.
* See {@link Enum.Iteratee} for the signature of the iteratee.
* @param iteratee - The iteratee.
* @param context - If provided, then the iteratee will be called with the context as its "this" value.
* @return A new array containg the results of the iteratee.
*/
Enum.prototype.map = function (iteratee, context) {
var _this = this;
var result = [];
this.keySet.forEach(function (key) {
result.push(iteratee.call(context, _this.enumObj[key], key, _this.enumObj));
});
return result;
};
Enum.prototype.isKey = function (key) {
return key !== undefined && this.keySet.has(key);
};
Enum.prototype.asKey = function (key) {
if (this.isKey(key)) {
return key;
}
else {
throw new Error("Unexpected key: " + key + ". Expected one of: " + Array.from(this.keySet));
}
};
Enum.prototype.asKeyOrDefault = function (key, defaultKey) {
if (this.isKey(key)) {
return key;
}
else {
return defaultKey;
}
};
Enum.prototype.isValue = function (value) {
return value !== undefined && this.valueSet.has(value);
};
Enum.prototype.asValue = function (value) {
if (this.isValue(value)) {
return value;
}
else {
throw new Error("Unexpected value: " + value + ". Expected one of: " + Array.from(this.valueSet));
}
};
Enum.prototype.asValueOrDefault = function (value, defaultValue) {
if (this.isValue(value)) {
return value;
}
else {
return defaultValue;
}
};
Enum.prototype.getKey = function (value) {
return this.keysByValueMap.get(this.asValue(value));
};
Enum.prototype.getKeyOrDefault = function (value, defaultKey) {
if (this.isValue(value)) {
return this.keysByValueMap.get(value);
}
else {
return defaultKey;
}
};
Enum.prototype.getValue = function (key) {
return this.enumObj[this.asKey(key)];
};
Enum.prototype.getValueOrDefault = function (key, defaultValue) {
if (this.isKey(key)) {
// type cast to "keyof T" is necessary until this bug is fixed:
// https://github.com/Microsoft/TypeScript/issues/21950
return this.enumObj[key];
}
else {
return defaultValue;
}
};
/**
* Map of enum object -> Enum instance.
* Used as a cache for {@link Enum.get}.
*/
Enum.instancesCache = new Map();
return Enum;
}());
exports.Enum = Enum;
//# sourceMappingURL=index.js.map

@@ -1,3 +0,257 @@

export * from "./Enum";
export * from "./EnumWrapper";
/**
* A generic wrapper for any enum-like value (see {@link EnumLike} type for more explanation).
* Provides utilities for runtime processing of an enum's values and keys, with strict compile-time
* type safety.
*
* Enum cannot be directly instantiated. Use one of the following to get/create an Enum
* instance:
* - {@link Enum.get}
* - {@link Enum.create}
*
* @template V - Type of the enum value.
* @template T - Type of the enum-like object that is being wrapped.
*/
var Enum = /** @class */ (function () {
/**
* Create a new Enum instance.
* This is for internal use only.
* Use one of the following to publicly get/create an Enum
* instance:
* - {@link Enum.get}
* - {@link Enum.create}
*
* @param enumObj - An enum-like object. See the {@link EnumLike} type for more explanation.
*/
function Enum(enumObj) {
var _this = this;
this.enumObj = enumObj;
/**
* Set of all values for this enum.
*/
this.valueSet = new Set();
/**
* Map of enum value -> enum key.
* Used for reverse key lookups.
*/
this.keysByValueMap = new Map();
this.keySet = new Set(Object.keys(enumObj).filter(
// Need to include only keys that cannot be parsed as numbers.
// This is necessary to ignore the reverse-lookup entries that are automatically added
// to numeric enums.
function (key) { return isNaN(parseInt(key, 10)); }));
this.keySet.forEach(function (key) {
var value = enumObj[key];
_this.valueSet.add(value);
_this.keysByValueMap.set(value, key);
});
}
/**
* Creates a new Enum for an enum-like object.
* You probably want to use {@link Enum.get} for any typical enums, because it will
* cache the result.
* This method may be useful if you want an Enum for an enum-like object that is dynamically
* built at runtime, is used only within a limited/tranient context in the application, and is likely
* to clutter the cache without ever being reused.
* @param enumObj - An enum-like object.
* @return A new instance of Enum for the provided enumObj.
*/
Enum.create = function (enumObj) {
return new Enum(enumObj);
};
/**
* Creates a new Enum, or returns a cached Enum if one has already been created for the same
* object via {@link Enum.get}.
* This is most useful for typical enums that are statically defined, because the cached Enum instance
* will be quickly retrieved/reused on every sebsequent call to get() for the same enum object.
* Use {@link Enum.create} if you don't want the Enum to be cached.
* @param enumObj - An enum-like object.
* @return An instance of Enum for the provided enumObj.
*/
Enum.get = function (enumObj) {
var result = this.instancesCache.get(enumObj);
if (!result) {
result = this.create(enumObj);
this.instancesCache.set(enumObj, result);
}
return result;
};
Object.defineProperty(Enum.prototype, "size", {
/**
* The number of entries in this enum.
*/
get: function () {
return this.keySet.size;
},
enumerable: true,
configurable: true
});
/**
* Get a list of this enum's keys.
* @return A list of this enum's keys.
*/
Enum.prototype.getKeys = function () {
return Array.from(this.keySet.values());
};
/**
* Get a list of this enum's values.
* NOTE: If this enum has any duplicate values, only unique values will be returned, and the
* length of the list will be less than {@link Enum#size}.
* @return A list of this enum's values.
*/
Enum.prototype.getValues = function () {
return Array.from(this.valueSet.values());
};
/**
* Get a list of this enum's entries as [key, value] tuples.
* @return A list of this enum's entries as [key, value] tuples.
*/
Enum.prototype.getEntries = function () {
return Array.from(this);
};
/**
* Get an iterator for this enum's keys.
* @return An iterator that iterates over this enum's keys.
*/
Enum.prototype.keys = function () {
return this.keySet.values();
};
/**
* Get an iterator for this enum's values.
* NOTE: If this enum has any duplicate values, only unique values will be iterated, and the
* number of values iterated will be less than {@link Enum#size}.
* @return An iterator that iterates over this enum's values.
*/
Enum.prototype.values = function () {
return this.valueSet.values();
};
/**
* Get an iterator for this enum's entries as [key, value] tuples.
* @return An iterator that iterates over this enum's entries as [key, value] tuples.
*/
Enum.prototype.entries = function () {
var _this = this;
var keyIterator = this.keys();
return _a = {
next: function () {
var nextKey = keyIterator.next();
return {
done: nextKey.done,
// "as any" cast is necessary to work around this bug:
// https://github.com/Microsoft/TypeScript/issues/11375
value: nextKey.done ? undefined : [nextKey.value, _this.enumObj[nextKey.value]]
};
}
},
_a[Symbol.iterator] = function () {
return this;
},
_a;
var _a;
};
/**
* Get an iterator for this enum's entries as [key, value] tuples.
* @return An iterator that iterates over this enum's entries as [key, value] tuples.
*/
Enum.prototype[Symbol.iterator] = function () {
return this.entries();
};
/**
* Calls the provided iteratee on each item in this enum.
* See {@link Enum.Iteratee} for the signature of the iteratee.
* The return value of the iteratee is ignored.
* @param iteratee - The iteratee.
* @param context - If provided, then the iteratee will be called with the context as its "this" value.
*/
Enum.prototype.forEach = function (iteratee, context) {
var _this = this;
this.keySet.forEach(function (key) {
iteratee.call(context, _this.enumObj[key], key, _this.enumObj);
});
};
/**
* Maps this enum's entries to a new list of values.
* Builds a new array containing the results of calling the provided iteratee on each item in this enum.
* See {@link Enum.Iteratee} for the signature of the iteratee.
* @param iteratee - The iteratee.
* @param context - If provided, then the iteratee will be called with the context as its "this" value.
* @return A new array containg the results of the iteratee.
*/
Enum.prototype.map = function (iteratee, context) {
var _this = this;
var result = [];
this.keySet.forEach(function (key) {
result.push(iteratee.call(context, _this.enumObj[key], key, _this.enumObj));
});
return result;
};
Enum.prototype.isKey = function (key) {
return key !== undefined && this.keySet.has(key);
};
Enum.prototype.asKey = function (key) {
if (this.isKey(key)) {
return key;
}
else {
throw new Error("Unexpected key: " + key + ". Expected one of: " + Array.from(this.keySet));
}
};
Enum.prototype.asKeyOrDefault = function (key, defaultKey) {
if (this.isKey(key)) {
return key;
}
else {
return defaultKey;
}
};
Enum.prototype.isValue = function (value) {
return value !== undefined && this.valueSet.has(value);
};
Enum.prototype.asValue = function (value) {
if (this.isValue(value)) {
return value;
}
else {
throw new Error("Unexpected value: " + value + ". Expected one of: " + Array.from(this.valueSet));
}
};
Enum.prototype.asValueOrDefault = function (value, defaultValue) {
if (this.isValue(value)) {
return value;
}
else {
return defaultValue;
}
};
Enum.prototype.getKey = function (value) {
return this.keysByValueMap.get(this.asValue(value));
};
Enum.prototype.getKeyOrDefault = function (value, defaultKey) {
if (this.isValue(value)) {
return this.keysByValueMap.get(value);
}
else {
return defaultKey;
}
};
Enum.prototype.getValue = function (key) {
return this.enumObj[this.asKey(key)];
};
Enum.prototype.getValueOrDefault = function (key, defaultValue) {
if (this.isKey(key)) {
// type cast to "keyof T" is necessary until this bug is fixed:
// https://github.com/Microsoft/TypeScript/issues/21950
return this.enumObj[key];
}
else {
return defaultValue;
}
};
/**
* Map of enum object -> Enum instance.
* Used as a cache for {@link Enum.get}.
*/
Enum.instancesCache = new Map();
return Enum;
}());
export { Enum };
//# sourceMappingURL=index.js.map

@@ -1,2 +0,203 @@

export * from "./Enum";
export * from "./EnumWrapper";
/**
* Used internally to verify that some type is enum-like.
* A type is enum-like if all its properties are of type number or string.
* @template V - Type of the enum value.
* @template K - String literal union of all keys of the enum-like type.
*/
export declare type EnumLike<V extends number | string, K extends string> = {
[P in K]: V;
};
/**
* A generic wrapper for any enum-like value (see {@link EnumLike} type for more explanation).
* Provides utilities for runtime processing of an enum's values and keys, with strict compile-time
* type safety.
*
* Enum cannot be directly instantiated. Use one of the following to get/create an Enum
* instance:
* - {@link Enum.get}
* - {@link Enum.create}
*
* @template V - Type of the enum value.
* @template T - Type of the enum-like object that is being wrapped.
*/
export declare class Enum<V extends number | string = number | string, T extends EnumLike<V, keyof T> = any> implements Iterable<Enum.Entry<T>> {
private readonly enumObj;
/**
* Map of enum object -> Enum instance.
* Used as a cache for {@link Enum.get}.
*/
private static readonly instancesCache;
/**
* Set of all keys for this enum.
*/
private readonly keySet;
/**
* Set of all values for this enum.
*/
private readonly valueSet;
/**
* Map of enum value -> enum key.
* Used for reverse key lookups.
*/
private readonly keysByValueMap;
/**
* Creates a new Enum for an enum-like object.
* You probably want to use {@link Enum.get} for any typical enums, because it will
* cache the result.
* This method may be useful if you want an Enum for an enum-like object that is dynamically
* built at runtime, is used only within a limited/tranient context in the application, and is likely
* to clutter the cache without ever being reused.
* @param enumObj - An enum-like object.
* @return A new instance of Enum for the provided enumObj.
*/
static create<T extends EnumLike<number, keyof T>>(enumObj: T): Enum<number, T>;
/**
* Creates a new Enum for an enum-like object.
* You probably want to use {@link Enum.get} for any typical enums, because it will
* cache the result.
* This method may be useful if you want an Enum for an enum-like object that is dynamically
* built at runtime, is used only within a limited/tranient context in the application, and is likely
* to clutter the cache without ever being reused.
* @param enumObj - An enum-like object.
* @return A new instance of Enum for the provided enumObj.
*/
static create<T extends EnumLike<string, keyof T>>(enumObj: T): Enum<string, T>;
/**
* Creates a new Enum for an enum-like object.
* You probably want to use {@link Enum.get} for any typical enums, because it will
* cache the result.
* This method may be useful if you want an Enum for an enum-like object that is dynamically
* built at runtime, is used only within a limited/tranient context in the application, and is likely
* to clutter the cache without ever being reused.
* @param enumObj - An enum-like object.
* @return A new instance of Enum for the provided enumObj.
*/
static create<T extends EnumLike<number | string, keyof T>>(enumObj: T): Enum<number | string, T>;
/**
* Creates a new Enum, or returns a cached Enum if one has already been created for the same
* object via {@link Enum.get}.
* This is most useful for typical enums that are statically defined, because the cached Enum instance
* will be quickly retrieved/reused on every sebsequent call to get() for the same enum object.
* Use {@link Enum.create} if you don't want the Enum to be cached.
* @param enumObj - An enum-like object.
* @return An instance of Enum for the provided enumObj.
*/
static get<T extends EnumLike<number, keyof T>>(enumObj: T): Enum<number, T>;
/**
* Creates a new Enum, or returns a cached Enum if one has already been created for the same
* object via {@link Enum.get}.
* This is most useful for typical enums that are statically defined, because the cached Enum instance
* will be quickly retrieved/reused on every sebsequent call to get() for the same enum object.
* Use {@link Enum.create} if you don't want the Enum to be cached.
* @param enumObj - An enum-like object.
* @return An instance of Enum for the provided enumObj.
*/
static get<T extends EnumLike<string, keyof T>>(enumObj: T): Enum<string, T>;
/**
* Creates a new Enum, or returns a cached Enum if one has already been created for the same
* object via {@link Enum.get}.
* This is most useful for typical enums that are statically defined, because the cached Enum instance
* will be quickly retrieved/reused on every sebsequent call to get() for the same enum object.
* Use {@link Enum.create} if you don't want the Enum to be cached.
* @param enumObj - An enum-like object.
* @return An instance of Enum for the provided enumObj.
*/
static get<T extends EnumLike<number | string, keyof T>>(enumObj: T): Enum<number | string, T>;
/**
* Create a new Enum instance.
* This is for internal use only.
* Use one of the following to publicly get/create an Enum
* instance:
* - {@link Enum.get}
* - {@link Enum.create}
*
* @param enumObj - An enum-like object. See the {@link EnumLike} type for more explanation.
*/
private constructor();
/**
* The number of entries in this enum.
*/
readonly size: number;
/**
* Get a list of this enum's keys.
* @return A list of this enum's keys.
*/
getKeys(): (keyof T)[];
/**
* Get a list of this enum's values.
* NOTE: If this enum has any duplicate values, only unique values will be returned, and the
* length of the list will be less than {@link Enum#size}.
* @return A list of this enum's values.
*/
getValues(): T[keyof T][];
/**
* Get a list of this enum's entries as [key, value] tuples.
* @return A list of this enum's entries as [key, value] tuples.
*/
getEntries(): Enum.Entry<T>[];
/**
* Get an iterator for this enum's keys.
* @return An iterator that iterates over this enum's keys.
*/
keys(): IterableIterator<keyof T>;
/**
* Get an iterator for this enum's values.
* NOTE: If this enum has any duplicate values, only unique values will be iterated, and the
* number of values iterated will be less than {@link Enum#size}.
* @return An iterator that iterates over this enum's values.
*/
values(): IterableIterator<T[keyof T]>;
/**
* Get an iterator for this enum's entries as [key, value] tuples.
* @return An iterator that iterates over this enum's entries as [key, value] tuples.
*/
entries(): IterableIterator<Enum.Entry<T>>;
/**
* Get an iterator for this enum's entries as [key, value] tuples.
* @return An iterator that iterates over this enum's entries as [key, value] tuples.
*/
[Symbol.iterator](): IterableIterator<Enum.Entry<T>>;
/**
* Calls the provided iteratee on each item in this enum.
* See {@link Enum.Iteratee} for the signature of the iteratee.
* The return value of the iteratee is ignored.
* @param iteratee - The iteratee.
* @param context - If provided, then the iteratee will be called with the context as its "this" value.
*/
forEach(iteratee: Enum.Iteratee<V, T, void>, context?: any): void;
/**
* Maps this enum's entries to a new list of values.
* Builds a new array containing the results of calling the provided iteratee on each item in this enum.
* See {@link Enum.Iteratee} for the signature of the iteratee.
* @param iteratee - The iteratee.
* @param context - If provided, then the iteratee will be called with the context as its "this" value.
* @return A new array containg the results of the iteratee.
*/
map<R>(iteratee: Enum.Iteratee<V, T, R>, context?: any): R[];
isKey(key: string | undefined): key is keyof T;
asKey(key: string | undefined): keyof T;
asKeyOrDefault(key: string | undefined, defaultKey?: keyof T): keyof T | undefined;
asKeyOrDefault(key: string | undefined, defaultKey: keyof T): keyof T;
asKeyOrDefault(key: string | undefined, defaultKey: string): keyof T | string;
asKeyOrDefault(key: string | undefined, defaultKey: string | undefined): keyof T | string | undefined;
isValue(value: V | undefined): value is T[keyof T];
asValue(value: V | undefined): T[keyof T];
asValueOrDefault(value: V | undefined, defaultValue?: T[keyof T]): T[keyof T] | undefined;
asValueOrDefault(value: V | undefined, defaultValue: T[keyof T]): T[keyof T];
asValueOrDefault(value: V | undefined, defaultValue: V): T[keyof T] | V;
asValueOrDefault(value: V | undefined, defaultValue: V | undefined): T[keyof T] | V | undefined;
getKey(value: V | undefined): keyof T;
getKeyOrDefault(value: V | undefined, defaultKey?: keyof T): keyof T | undefined;
getKeyOrDefault(value: V | undefined, defaultKey: keyof T): keyof T;
getKeyOrDefault(value: V | undefined, defaultKey: string): keyof T | string;
getKeyOrDefault(value: V | undefined, defaultKey: string | undefined): keyof T | string | undefined;
getValue(key: string | undefined): T[keyof T];
getValueOrDefault(key: string | undefined, defaultValue?: T[keyof T]): T[keyof T] | undefined;
getValueOrDefault(key: string | undefined, defaultValue: T[keyof T]): T[keyof T];
getValueOrDefault(key: string | undefined, defaultValue: V): T[keyof T] | V;
getValueOrDefault(key: string | undefined, defaultValue: V | undefined): T[keyof T] | V | undefined;
}
export declare namespace Enum {
type Entry<T> = [keyof T, T[keyof T]];
type Iteratee<V extends number | string, T extends EnumLike<V, keyof T>, R> = (this: any, value: V, key: keyof T, enumObj: T) => R;
}

2

package.json
{
"name": "ts-enum-util",
"version": "0.0.2",
"version": "0.0.3",
"description": "TypeScript Enum Utilities",

@@ -5,0 +5,0 @@ "repository": {

@@ -1,2 +0,384 @@

export * from "./Enum";
export * from "./EnumWrapper";
/**
* Used internally to verify that some type is enum-like.
* A type is enum-like if all its properties are of type number or string.
* @template V - Type of the enum value.
* @template K - String literal union of all keys of the enum-like type.
*/
export type EnumLike<V extends number | string, K extends string> = {
[P in K]: V;
};
/**
* A generic wrapper for any enum-like value (see {@link EnumLike} type for more explanation).
* Provides utilities for runtime processing of an enum's values and keys, with strict compile-time
* type safety.
*
* Enum cannot be directly instantiated. Use one of the following to get/create an Enum
* instance:
* - {@link Enum.get}
* - {@link Enum.create}
*
* @template V - Type of the enum value.
* @template T - Type of the enum-like object that is being wrapped.
*/
export class Enum<
V extends number | string = number | string,
T extends EnumLike<V, keyof T> = any
> implements Iterable<Enum.Entry<T>> {
/**
* Map of enum object -> Enum instance.
* Used as a cache for {@link Enum.get}.
*/
private static readonly instancesCache = new Map<object, Enum>();
/**
* Set of all keys for this enum.
*/
private readonly keySet: Set<keyof T>;
/**
* Set of all values for this enum.
*/
private readonly valueSet = new Set<T[keyof T]>();
/**
* Map of enum value -> enum key.
* Used for reverse key lookups.
*/
private readonly keysByValueMap = new Map<V, keyof T>();
/**
* Creates a new Enum for an enum-like object.
* You probably want to use {@link Enum.get} for any typical enums, because it will
* cache the result.
* This method may be useful if you want an Enum for an enum-like object that is dynamically
* built at runtime, is used only within a limited/tranient context in the application, and is likely
* to clutter the cache without ever being reused.
* @param enumObj - An enum-like object.
* @return A new instance of Enum for the provided enumObj.
*/
public static create<T extends EnumLike<number, keyof T>>(enumObj: T): Enum<number, T>;
/**
* Creates a new Enum for an enum-like object.
* You probably want to use {@link Enum.get} for any typical enums, because it will
* cache the result.
* This method may be useful if you want an Enum for an enum-like object that is dynamically
* built at runtime, is used only within a limited/tranient context in the application, and is likely
* to clutter the cache without ever being reused.
* @param enumObj - An enum-like object.
* @return A new instance of Enum for the provided enumObj.
*/
public static create<T extends EnumLike<string, keyof T>>(enumObj: T): Enum<string, T>;
/**
* Creates a new Enum for an enum-like object.
* You probably want to use {@link Enum.get} for any typical enums, because it will
* cache the result.
* This method may be useful if you want an Enum for an enum-like object that is dynamically
* built at runtime, is used only within a limited/tranient context in the application, and is likely
* to clutter the cache without ever being reused.
* @param enumObj - An enum-like object.
* @return A new instance of Enum for the provided enumObj.
*/
public static create<T extends EnumLike<number | string, keyof T>>(enumObj: T): Enum<number | string, T>;
/**
* Creates a new Enum for an enum-like object.
* You probably want to use {@link Enum.get} for any typical enums, because it will
* cache the result.
* This method may be useful if you want an Enum for an enum-like object that is dynamically
* built at runtime, is used only within a limited/tranient context in the application, and is likely
* to clutter the cache without ever being reused.
* @param enumObj - An enum-like object.
* @return A new instance of Enum for the provided enumObj.
*/
public static create(enumObj: any): Enum {
return new Enum(enumObj);
}
/**
* Creates a new Enum, or returns a cached Enum if one has already been created for the same
* object via {@link Enum.get}.
* This is most useful for typical enums that are statically defined, because the cached Enum instance
* will be quickly retrieved/reused on every sebsequent call to get() for the same enum object.
* Use {@link Enum.create} if you don't want the Enum to be cached.
* @param enumObj - An enum-like object.
* @return An instance of Enum for the provided enumObj.
*/
public static get<T extends EnumLike<number, keyof T>>(enumObj: T): Enum<number, T>;
/**
* Creates a new Enum, or returns a cached Enum if one has already been created for the same
* object via {@link Enum.get}.
* This is most useful for typical enums that are statically defined, because the cached Enum instance
* will be quickly retrieved/reused on every sebsequent call to get() for the same enum object.
* Use {@link Enum.create} if you don't want the Enum to be cached.
* @param enumObj - An enum-like object.
* @return An instance of Enum for the provided enumObj.
*/
public static get<T extends EnumLike<string, keyof T>>(enumObj: T): Enum<string, T>;
/**
* Creates a new Enum, or returns a cached Enum if one has already been created for the same
* object via {@link Enum.get}.
* This is most useful for typical enums that are statically defined, because the cached Enum instance
* will be quickly retrieved/reused on every sebsequent call to get() for the same enum object.
* Use {@link Enum.create} if you don't want the Enum to be cached.
* @param enumObj - An enum-like object.
* @return An instance of Enum for the provided enumObj.
*/
public static get<T extends EnumLike<number | string, keyof T>>(enumObj: T): Enum<number | string, T>;
/**
* Creates a new Enum, or returns a cached Enum if one has already been created for the same
* object via {@link Enum.get}.
* This is most useful for typical enums that are statically defined, because the cached Enum instance
* will be quickly retrieved/reused on every sebsequent call to get() for the same enum object.
* Use {@link Enum.create} if you don't want the Enum to be cached.
* @param enumObj - An enum-like object.
* @return An instance of Enum for the provided enumObj.
*/
public static get(enumObj: any): Enum {
let result = this.instancesCache.get(enumObj);
if (!result) {
result = this.create(enumObj);
this.instancesCache.set(enumObj, result);
}
return result;
}
/**
* Create a new Enum instance.
* This is for internal use only.
* Use one of the following to publicly get/create an Enum
* instance:
* - {@link Enum.get}
* - {@link Enum.create}
*
* @param enumObj - An enum-like object. See the {@link EnumLike} type for more explanation.
*/
private constructor(private readonly enumObj: T) {
this.keySet = new Set<keyof T>(
Object.keys(enumObj).filter(
// Need to include only keys that cannot be parsed as numbers.
// This is necessary to ignore the reverse-lookup entries that are automatically added
// to numeric enums.
(key) => isNaN(parseInt(key, 10))
)
);
this.keySet.forEach((key) => {
const value = enumObj[key];
this.valueSet.add(value);
this.keysByValueMap.set(value, key);
});
}
/**
* The number of entries in this enum.
*/
public get size(): number {
return this.keySet.size;
}
/**
* Get a list of this enum's keys.
* @return A list of this enum's keys.
*/
public getKeys(): (keyof T)[] {
return Array.from(this.keySet.values());
}
/**
* Get a list of this enum's values.
* NOTE: If this enum has any duplicate values, only unique values will be returned, and the
* length of the list will be less than {@link Enum#size}.
* @return A list of this enum's values.
*/
public getValues(): T[keyof T][] {
return Array.from(this.valueSet.values());
}
/**
* Get a list of this enum's entries as [key, value] tuples.
* @return A list of this enum's entries as [key, value] tuples.
*/
public getEntries(): Enum.Entry<T>[] {
return Array.from(this);
}
/**
* Get an iterator for this enum's keys.
* @return An iterator that iterates over this enum's keys.
*/
public keys(): IterableIterator<keyof T> {
return this.keySet.values();
}
/**
* Get an iterator for this enum's values.
* NOTE: If this enum has any duplicate values, only unique values will be iterated, and the
* number of values iterated will be less than {@link Enum#size}.
* @return An iterator that iterates over this enum's values.
*/
public values(): IterableIterator<T[keyof T]> {
return this.valueSet.values();
}
/**
* Get an iterator for this enum's entries as [key, value] tuples.
* @return An iterator that iterates over this enum's entries as [key, value] tuples.
*/
public entries(): IterableIterator<Enum.Entry<T>> {
const keyIterator = this.keys();
return {
next: (): IteratorResult<Enum.Entry<T>> => {
const nextKey = keyIterator.next();
return {
done: nextKey.done,
// "as any" cast is necessary to work around this bug:
// https://github.com/Microsoft/TypeScript/issues/11375
value: nextKey.done ? undefined as any : [nextKey.value, this.enumObj[nextKey.value]]
};
},
[Symbol.iterator]: function(): IterableIterator<Enum.Entry<T>> {
return this;
}
};
}
/**
* Get an iterator for this enum's entries as [key, value] tuples.
* @return An iterator that iterates over this enum's entries as [key, value] tuples.
*/
public [Symbol.iterator](): IterableIterator<Enum.Entry<T>> {
return this.entries();
}
/**
* Calls the provided iteratee on each item in this enum.
* See {@link Enum.Iteratee} for the signature of the iteratee.
* The return value of the iteratee is ignored.
* @param iteratee - The iteratee.
* @param context - If provided, then the iteratee will be called with the context as its "this" value.
*/
public forEach(iteratee: Enum.Iteratee<V, T, void>, context?: any): void {
this.keySet.forEach((key) => {
iteratee.call(context, this.enumObj[key], key, this.enumObj);
});
}
/**
* Maps this enum's entries to a new list of values.
* Builds a new array containing the results of calling the provided iteratee on each item in this enum.
* See {@link Enum.Iteratee} for the signature of the iteratee.
* @param iteratee - The iteratee.
* @param context - If provided, then the iteratee will be called with the context as its "this" value.
* @return A new array containg the results of the iteratee.
*/
public map<R>(iteratee: Enum.Iteratee<V, T, R>, context?: any): R[] {
const result: R[] = [];
this.keySet.forEach((key) => {
result.push(iteratee.call(context, this.enumObj[key], key, this.enumObj));
});
return result;
}
public isKey(key: string | undefined): key is keyof T {
return key !== undefined && this.keySet.has(key);
}
public asKey(key: string | undefined): keyof T {
if (this.isKey(key)) {
return key;
} else {
throw new Error(`Unexpected key: ${key}. Expected one of: ${Array.from(this.keySet)}`);
}
}
public asKeyOrDefault(key: string | undefined, defaultKey?: keyof T): keyof T | undefined;
public asKeyOrDefault(key: string | undefined, defaultKey: keyof T): keyof T;
public asKeyOrDefault(key: string | undefined, defaultKey: string): keyof T | string;
public asKeyOrDefault(key: string | undefined, defaultKey: string | undefined): keyof T | string | undefined;
public asKeyOrDefault(key: string | undefined, defaultKey?: keyof T | string): keyof T | string | undefined {
if (this.isKey(key)) {
return key;
} else {
return defaultKey;
}
}
public isValue(value: V | undefined): value is T[keyof T] {
return value !== undefined && this.valueSet.has(value);
}
public asValue(value: V | undefined): T[keyof T] {
if (this.isValue(value)) {
return value;
} else {
throw new Error(`Unexpected value: ${value}. Expected one of: ${Array.from(this.valueSet)}`);
}
}
public asValueOrDefault(value: V | undefined, defaultValue?: T[keyof T]): T[keyof T] | undefined;
public asValueOrDefault(value: V | undefined, defaultValue: T[keyof T]): T[keyof T];
public asValueOrDefault(value: V | undefined, defaultValue: V): T[keyof T] | V;
public asValueOrDefault(value: V | undefined, defaultValue: V | undefined): T[keyof T] | V | undefined;
public asValueOrDefault(value: V | undefined, defaultValue?: T[keyof T] | V): T[keyof T] | V | undefined {
if (this.isValue(value)) {
return value;
} else {
return defaultValue;
}
}
public getKey(value: V | undefined): keyof T {
return this.keysByValueMap.get(this.asValue(value));
}
public getKeyOrDefault(value: V | undefined, defaultKey?: keyof T): keyof T | undefined;
public getKeyOrDefault(value: V | undefined, defaultKey: keyof T): keyof T;
public getKeyOrDefault(value: V | undefined, defaultKey: string): keyof T | string;
public getKeyOrDefault(value: V | undefined, defaultKey: string | undefined): keyof T | string | undefined;
public getKeyOrDefault(value: V | undefined, defaultKey?: keyof T | string): keyof T | string | undefined {
if (this.isValue(value)) {
return this.keysByValueMap.get(value);
} else {
return defaultKey;
}
}
public getValue(key: string | undefined): T[keyof T] {
return this.enumObj[this.asKey(key)];
}
public getValueOrDefault(key: string | undefined, defaultValue?: T[keyof T]): T[keyof T] | undefined;
public getValueOrDefault(key: string | undefined, defaultValue: T[keyof T]): T[keyof T];
public getValueOrDefault(key: string | undefined, defaultValue: V): T[keyof T] | V;
public getValueOrDefault(key: string | undefined, defaultValue: V | undefined): T[keyof T] | V | undefined;
public getValueOrDefault(key: string | undefined, defaultValue?: T[keyof T] | V): T[keyof T] | V | undefined {
if (this.isKey(key)) {
// type cast to "keyof T" is necessary until this bug is fixed:
// https://github.com/Microsoft/TypeScript/issues/21950
return this.enumObj[key as keyof T];
} else {
return defaultValue;
}
}
}
export namespace Enum {
export type Entry<T> = [
keyof T,
T[keyof T]
];
export type Iteratee<
V extends number | string,
T extends EnumLike<V, keyof T>,
R
> = (this: any, value: V, key: keyof T, enumObj: T) => R;
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc