ts-enum-util
Advanced tools
Comparing version
"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
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
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
-8.47%9
-57.14%1063
-5.26%