ts-enum-util
Advanced tools
Comparing version 0.0.2 to 0.0.3
"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; | ||
} |
{ | ||
"name": "ts-enum-util", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"description": "TypeScript Enum Utilities", | ||
@@ -5,0 +5,0 @@ "repository": { |
386
src/index.ts
@@ -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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
60189
9
1063