ts-enum-util
Advanced tools
Comparing version 0.2.0 to 0.2.1
@@ -29,3 +29,2 @@ "use strict"; | ||
function EnumWrapper(enumObj) { | ||
var _this = this; | ||
this.enumObj = enumObj; | ||
@@ -37,18 +36,16 @@ /** | ||
this.keysByValueMap = new Map(); | ||
this.keySet = new Set(Object.keys(enumObj) | ||
.filter( | ||
// If after converting the key to an integer, then back to a string, the result is different | ||
// than the original key, then the key is NOT an integer index. | ||
// See ECMAScript spec section 15.4: http://www.ecma-international.org/ecma-262/5.1/#sec-15.4 | ||
function (key) { return key !== String(parseInt(key, 10)); }) | ||
.sort()); | ||
var index = 0; | ||
this.keySet.forEach(function (key) { | ||
this.keysList = Object.keys(enumObj) | ||
.filter(isNonIndexKey) | ||
.sort(); | ||
var length = this.keysList.length; | ||
this.valuesList = new Array(length); | ||
for (var index = 0; index < length; ++index) { | ||
var key = this.keysList[index]; | ||
var value = enumObj[key]; | ||
_this.keysByValueMap.set(value, key); | ||
this.valuesList[index] = value; | ||
this.keysByValueMap.set(value, key); | ||
// type casting necessary to bypass readonly index signature for initialization | ||
_this[index] = [key, value]; | ||
++index; | ||
}); | ||
this.size = this.length = this.keySet.size; | ||
this[index] = [key, value]; | ||
} | ||
this.size = this.length = length; | ||
} | ||
@@ -98,3 +95,22 @@ /** | ||
EnumWrapper.prototype.keys = function () { | ||
return this.keySet.values(); | ||
var _this = this; | ||
var index = 0; | ||
return _a = { | ||
next: function () { | ||
var isDone = index >= _this.length; | ||
var result = { | ||
done: isDone, | ||
// "as any" cast is necessary to work around this bug: | ||
// https://github.com/Microsoft/TypeScript/issues/11375 | ||
value: isDone ? undefined : _this.keysList[index] | ||
}; | ||
++index; | ||
return result; | ||
} | ||
}, | ||
_a[Symbol.iterator] = function () { | ||
return this; | ||
}, | ||
_a; | ||
var _a; | ||
}; | ||
@@ -119,3 +135,3 @@ /** | ||
// https://github.com/Microsoft/TypeScript/issues/11375 | ||
value: isDone ? undefined : _this[index][1] | ||
value: isDone ? undefined : _this.valuesList[index] | ||
}; | ||
@@ -178,8 +194,7 @@ ++index; | ||
EnumWrapper.prototype.forEach = function (iteratee, context) { | ||
var _this = this; | ||
// Taking advantage of "this" being ArrayLike<EnumWrapper.Entry>, so we can call | ||
// non-mutating Array.prototype methods on it. | ||
Array.prototype.forEach.call(this, function (entry, index) { | ||
iteratee.call(context, entry[1], entry[0], _this, index); | ||
}); | ||
var length = this.length; | ||
for (var index = 0; index < length; ++index) { | ||
var entry = this[index]; | ||
iteratee.call(context, entry[1], entry[0], this, index); | ||
} | ||
}; | ||
@@ -198,8 +213,9 @@ /** | ||
EnumWrapper.prototype.map = function (iteratee, context) { | ||
var _this = this; | ||
// Taking advantage of "this" being ArrayLike<EnumWrapper.Entry>, so we can call | ||
// non-mutating Array.prototype methods on it. | ||
return Array.prototype.map.call(this, function (entry, index) { | ||
return iteratee.call(context, entry[1], entry[0], _this, index); | ||
}); | ||
var length = this.length; | ||
var result = new Array(length); | ||
for (var index = 0; index < length; ++index) { | ||
var entry = this[index]; | ||
result[index] = iteratee.call(context, entry[1], entry[0], this, index); | ||
} | ||
return result; | ||
}; | ||
@@ -212,7 +228,4 @@ /** | ||
EnumWrapper.prototype.getKeys = function () { | ||
// Taking advantage of "this" being ArrayLike<EnumWrapper.Entry>, so we can call | ||
// non-mutating Array.prototype methods on it. | ||
return Array.prototype.map.call(this, function (entry) { | ||
return entry[0]; | ||
}); | ||
// return defensive copy | ||
return this.keysList.slice(); | ||
}; | ||
@@ -227,7 +240,4 @@ /** | ||
EnumWrapper.prototype.getValues = function () { | ||
// Taking advantage of "this" being ArrayLike<EnumWrapper.Entry>, so we can call | ||
// non-mutating Array.prototype methods on it. | ||
return Array.prototype.map.call(this, function (entry) { | ||
return entry[1]; | ||
}); | ||
// return defensive copy | ||
return this.valuesList.slice(); | ||
}; | ||
@@ -240,8 +250,10 @@ /** | ||
EnumWrapper.prototype.getEntries = function () { | ||
// Taking advantage of "this" being ArrayLike<EnumWrapper.Entry>, so we can call | ||
// non-mutating Array.prototype methods on it. | ||
return Array.prototype.map.call(this, function (entry) { | ||
var length = this.length; | ||
var result = new Array(length); | ||
for (var index = 0; index < length; ++index) { | ||
var entry = this[index]; | ||
// Create a defensive copy of the entry | ||
return [entry[0], entry[1]]; | ||
}); | ||
result[index] = [entry[0], entry[1]]; | ||
} | ||
return result; | ||
}; | ||
@@ -255,3 +267,3 @@ /** | ||
EnumWrapper.prototype.isKey = function (key) { | ||
return this.keySet.has(key); | ||
return key != null && isNonIndexKey(key) && this.enumObj.hasOwnProperty(key); | ||
}; | ||
@@ -415,2 +427,13 @@ /** | ||
exports.$enum = $enum; | ||
/** | ||
* Return true if the specified object key value is NOT an integer index key. | ||
* @param key - An object key. | ||
* @return true if the specified object key value is NOT an integer index key. | ||
*/ | ||
function isNonIndexKey(key) { | ||
// If after converting the key to an integer, then back to a string, the result is different | ||
// than the original key, then the key is NOT an integer index. | ||
// See ECMAScript spec section 15.4: http://www.ecma-international.org/ecma-262/5.1/#sec-15.4 | ||
return key !== String(parseInt(key, 10)); | ||
} | ||
//# sourceMappingURL=index.js.map |
@@ -27,3 +27,2 @@ /** | ||
function EnumWrapper(enumObj) { | ||
var _this = this; | ||
this.enumObj = enumObj; | ||
@@ -35,18 +34,16 @@ /** | ||
this.keysByValueMap = new Map(); | ||
this.keySet = new Set(Object.keys(enumObj) | ||
.filter( | ||
// If after converting the key to an integer, then back to a string, the result is different | ||
// than the original key, then the key is NOT an integer index. | ||
// See ECMAScript spec section 15.4: http://www.ecma-international.org/ecma-262/5.1/#sec-15.4 | ||
function (key) { return key !== String(parseInt(key, 10)); }) | ||
.sort()); | ||
var index = 0; | ||
this.keySet.forEach(function (key) { | ||
this.keysList = Object.keys(enumObj) | ||
.filter(isNonIndexKey) | ||
.sort(); | ||
var length = this.keysList.length; | ||
this.valuesList = new Array(length); | ||
for (var index = 0; index < length; ++index) { | ||
var key = this.keysList[index]; | ||
var value = enumObj[key]; | ||
_this.keysByValueMap.set(value, key); | ||
this.valuesList[index] = value; | ||
this.keysByValueMap.set(value, key); | ||
// type casting necessary to bypass readonly index signature for initialization | ||
_this[index] = [key, value]; | ||
++index; | ||
}); | ||
this.size = this.length = this.keySet.size; | ||
this[index] = [key, value]; | ||
} | ||
this.size = this.length = length; | ||
} | ||
@@ -96,3 +93,22 @@ /** | ||
EnumWrapper.prototype.keys = function () { | ||
return this.keySet.values(); | ||
var _this = this; | ||
var index = 0; | ||
return _a = { | ||
next: function () { | ||
var isDone = index >= _this.length; | ||
var result = { | ||
done: isDone, | ||
// "as any" cast is necessary to work around this bug: | ||
// https://github.com/Microsoft/TypeScript/issues/11375 | ||
value: isDone ? undefined : _this.keysList[index] | ||
}; | ||
++index; | ||
return result; | ||
} | ||
}, | ||
_a[Symbol.iterator] = function () { | ||
return this; | ||
}, | ||
_a; | ||
var _a; | ||
}; | ||
@@ -117,3 +133,3 @@ /** | ||
// https://github.com/Microsoft/TypeScript/issues/11375 | ||
value: isDone ? undefined : _this[index][1] | ||
value: isDone ? undefined : _this.valuesList[index] | ||
}; | ||
@@ -176,8 +192,7 @@ ++index; | ||
EnumWrapper.prototype.forEach = function (iteratee, context) { | ||
var _this = this; | ||
// Taking advantage of "this" being ArrayLike<EnumWrapper.Entry>, so we can call | ||
// non-mutating Array.prototype methods on it. | ||
Array.prototype.forEach.call(this, function (entry, index) { | ||
iteratee.call(context, entry[1], entry[0], _this, index); | ||
}); | ||
var length = this.length; | ||
for (var index = 0; index < length; ++index) { | ||
var entry = this[index]; | ||
iteratee.call(context, entry[1], entry[0], this, index); | ||
} | ||
}; | ||
@@ -196,8 +211,9 @@ /** | ||
EnumWrapper.prototype.map = function (iteratee, context) { | ||
var _this = this; | ||
// Taking advantage of "this" being ArrayLike<EnumWrapper.Entry>, so we can call | ||
// non-mutating Array.prototype methods on it. | ||
return Array.prototype.map.call(this, function (entry, index) { | ||
return iteratee.call(context, entry[1], entry[0], _this, index); | ||
}); | ||
var length = this.length; | ||
var result = new Array(length); | ||
for (var index = 0; index < length; ++index) { | ||
var entry = this[index]; | ||
result[index] = iteratee.call(context, entry[1], entry[0], this, index); | ||
} | ||
return result; | ||
}; | ||
@@ -210,7 +226,4 @@ /** | ||
EnumWrapper.prototype.getKeys = function () { | ||
// Taking advantage of "this" being ArrayLike<EnumWrapper.Entry>, so we can call | ||
// non-mutating Array.prototype methods on it. | ||
return Array.prototype.map.call(this, function (entry) { | ||
return entry[0]; | ||
}); | ||
// return defensive copy | ||
return this.keysList.slice(); | ||
}; | ||
@@ -225,7 +238,4 @@ /** | ||
EnumWrapper.prototype.getValues = function () { | ||
// Taking advantage of "this" being ArrayLike<EnumWrapper.Entry>, so we can call | ||
// non-mutating Array.prototype methods on it. | ||
return Array.prototype.map.call(this, function (entry) { | ||
return entry[1]; | ||
}); | ||
// return defensive copy | ||
return this.valuesList.slice(); | ||
}; | ||
@@ -238,8 +248,10 @@ /** | ||
EnumWrapper.prototype.getEntries = function () { | ||
// Taking advantage of "this" being ArrayLike<EnumWrapper.Entry>, so we can call | ||
// non-mutating Array.prototype methods on it. | ||
return Array.prototype.map.call(this, function (entry) { | ||
var length = this.length; | ||
var result = new Array(length); | ||
for (var index = 0; index < length; ++index) { | ||
var entry = this[index]; | ||
// Create a defensive copy of the entry | ||
return [entry[0], entry[1]]; | ||
}); | ||
result[index] = [entry[0], entry[1]]; | ||
} | ||
return result; | ||
}; | ||
@@ -253,3 +265,3 @@ /** | ||
EnumWrapper.prototype.isKey = function (key) { | ||
return this.keySet.has(key); | ||
return key != null && isNonIndexKey(key) && this.enumObj.hasOwnProperty(key); | ||
}; | ||
@@ -412,2 +424,13 @@ /** | ||
} | ||
/** | ||
* Return true if the specified object key value is NOT an integer index key. | ||
* @param key - An object key. | ||
* @return true if the specified object key value is NOT an integer index key. | ||
*/ | ||
function isNonIndexKey(key) { | ||
// If after converting the key to an integer, then back to a string, the result is different | ||
// than the original key, then the key is NOT an integer index. | ||
// See ECMAScript spec section 15.4: http://www.ecma-international.org/ecma-262/5.1/#sec-15.4 | ||
return key !== String(parseInt(key, 10)); | ||
} | ||
//# sourceMappingURL=index.js.map |
@@ -32,6 +32,10 @@ /** | ||
/** | ||
* Set of all keys for this enum. | ||
* List of all keys for this enum, in sorted order. | ||
*/ | ||
private readonly keySet; | ||
private readonly keysList; | ||
/** | ||
* List of all values for this enum, in sorted key order. | ||
*/ | ||
private readonly valuesList; | ||
/** | ||
* Map of enum value -> enum key. | ||
@@ -38,0 +42,0 @@ * Used for reverse key lookups. |
{ | ||
"name": "ts-enum-util", | ||
"version": "0.2.0", | ||
"version": "0.2.1", | ||
"description": "TypeScript Enum Utilities", | ||
@@ -5,0 +5,0 @@ "repository": { |
@@ -339,5 +339,3 @@ [![npm version](https://img.shields.io/npm/v/ts-enum-util.svg)](https://www.npmjs.com/package/ts-enum-util) | ||
## Requirements | ||
- *ES5/ES6 Features*: The following ES5/ES6 features are used by `ts-enum-util`, so they must exist (either natively or via polyfill) in the run-time environment: | ||
- `Array.prototype.forEach` | ||
- `Array.prototype.map` | ||
- *ES6 Features*: The following ES6 features are used by `ts-enum-util`, so they must exist (either natively or via polyfill) in the run-time environment: | ||
- `Map` | ||
@@ -344,0 +342,0 @@ - `Set` |
158
src/index.ts
@@ -36,7 +36,12 @@ /** | ||
/** | ||
* Set of all keys for this enum. | ||
* List of all keys for this enum, in sorted order. | ||
*/ | ||
private readonly keySet: Set<keyof T>; | ||
private readonly keysList: (keyof T)[]; | ||
/** | ||
* List of all values for this enum, in sorted key order. | ||
*/ | ||
private readonly valuesList: T[keyof T][]; | ||
/** | ||
* Map of enum value -> enum key. | ||
@@ -197,28 +202,25 @@ * Used for reverse key lookups. | ||
private constructor(private readonly enumObj: T) { | ||
this.keySet = new Set<keyof T>( | ||
Object.keys(enumObj) | ||
// Exclude integer indexes. | ||
// This is necessary to ignore the reverse-lookup entries that are automatically added | ||
// by TypeScript to numeric enums. | ||
.filter( | ||
// If after converting the key to an integer, then back to a string, the result is different | ||
// than the original key, then the key is NOT an integer index. | ||
// See ECMAScript spec section 15.4: http://www.ecma-international.org/ecma-262/5.1/#sec-15.4 | ||
(key) => key !== String(parseInt(key, 10)) | ||
) | ||
// Order of Object.keys() is implementation-dependent, so sort the keys to guarantee | ||
// a consistent order for iteration. | ||
.sort() | ||
); | ||
this.keysList = Object.keys(enumObj) | ||
// Include only keys that are not index keys. | ||
// This is necessary to ignore the reverse-lookup entries that are automatically added | ||
// by TypeScript to numeric enums. | ||
.filter(isNonIndexKey) | ||
// Order of Object.keys() is implementation-dependent, so sort the keys to guarantee | ||
// a consistent order for iteration. | ||
.sort(); | ||
let index = 0; | ||
this.keySet.forEach((key) => { | ||
const length = this.keysList.length; | ||
this.valuesList = new Array<T[keyof T]>(length); | ||
for (let index = 0; index < length; ++index) { | ||
const key = this.keysList[index]; | ||
const value = enumObj[key]; | ||
this.valuesList[index] = value; | ||
this.keysByValueMap.set(value, key); | ||
// type casting necessary to bypass readonly index signature for initialization | ||
(this as any as EnumWrapper.Entry<V, T>[])[index] = [key, value]; | ||
++index; | ||
}); | ||
} | ||
this.size = this.length = this.keySet.size; | ||
this.size = this.length = length; | ||
} | ||
@@ -240,3 +242,23 @@ | ||
public keys(): IterableIterator<keyof T> { | ||
return this.keySet.values(); | ||
let index = 0; | ||
return { | ||
next: () => { | ||
const isDone = index >= this.length; | ||
const result: IteratorResult<keyof T> = { | ||
done: isDone, | ||
// "as any" cast is necessary to work around this bug: | ||
// https://github.com/Microsoft/TypeScript/issues/11375 | ||
value: isDone ? undefined as any : this.keysList[index] | ||
}; | ||
++index; | ||
return result; | ||
}, | ||
[Symbol.iterator](): IterableIterator<keyof T> { | ||
return this; | ||
} | ||
}; | ||
} | ||
@@ -256,9 +278,9 @@ | ||
return { | ||
next: (): IteratorResult<T[keyof T]> => { | ||
next: () => { | ||
const isDone = index >= this.length; | ||
const result = { | ||
const result: IteratorResult<T[keyof T]> = { | ||
done: isDone, | ||
// "as any" cast is necessary to work around this bug: | ||
// https://github.com/Microsoft/TypeScript/issues/11375 | ||
value: isDone ? undefined as any : this[index][1] | ||
value: isDone ? undefined as any : this.valuesList[index] | ||
}; | ||
@@ -326,10 +348,8 @@ | ||
public forEach(iteratee: EnumWrapper.Iteratee<void, V, T>, context?: any): void { | ||
// Taking advantage of "this" being ArrayLike<EnumWrapper.Entry>, so we can call | ||
// non-mutating Array.prototype methods on it. | ||
Array.prototype.forEach.call( | ||
this, | ||
(entry: EnumWrapper.Entry<V, T>, index: number): void => { | ||
iteratee.call(context, entry[1], entry[0], this, index); | ||
} | ||
); | ||
const length = this.length; | ||
for (let index = 0; index < length; ++index) { | ||
const entry = this[index]; | ||
iteratee.call(context, entry[1], entry[0], this, index); | ||
} | ||
} | ||
@@ -349,10 +369,11 @@ | ||
public map<R>(iteratee: EnumWrapper.Iteratee<R, V, T>, context?: any): R[] { | ||
// Taking advantage of "this" being ArrayLike<EnumWrapper.Entry>, so we can call | ||
// non-mutating Array.prototype methods on it. | ||
return Array.prototype.map.call( | ||
this, | ||
(entry: EnumWrapper.Entry<V, T>, index: number): R => { | ||
return iteratee.call(context, entry[1], entry[0], this, index); | ||
} | ||
); | ||
const length = this.length; | ||
const result = new Array<R>(length); | ||
for (let index = 0; index < length; ++index) { | ||
const entry = this[index]; | ||
result[index] = iteratee.call(context, entry[1], entry[0], this, index); | ||
} | ||
return result; | ||
} | ||
@@ -366,10 +387,4 @@ | ||
public getKeys(): (keyof T)[] { | ||
// Taking advantage of "this" being ArrayLike<EnumWrapper.Entry>, so we can call | ||
// non-mutating Array.prototype methods on it. | ||
return Array.prototype.map.call( | ||
this, | ||
(entry: EnumWrapper.Entry<V, T>): keyof T => { | ||
return entry[0]; | ||
} | ||
); | ||
// return defensive copy | ||
return this.keysList.slice(); | ||
} | ||
@@ -385,10 +400,4 @@ | ||
public getValues(): T[keyof T][] { | ||
// Taking advantage of "this" being ArrayLike<EnumWrapper.Entry>, so we can call | ||
// non-mutating Array.prototype methods on it. | ||
return Array.prototype.map.call( | ||
this, | ||
(entry: EnumWrapper.Entry<V, T>): T[keyof T] => { | ||
return entry[1]; | ||
} | ||
); | ||
// return defensive copy | ||
return this.valuesList.slice(); | ||
} | ||
@@ -402,11 +411,12 @@ | ||
public getEntries(): EnumWrapper.Entry<V, T>[] { | ||
// Taking advantage of "this" being ArrayLike<EnumWrapper.Entry>, so we can call | ||
// non-mutating Array.prototype methods on it. | ||
return Array.prototype.map.call( | ||
this, | ||
(entry: EnumWrapper.Entry<V, T>): EnumWrapper.Entry<V, T> => { | ||
// Create a defensive copy of the entry | ||
return [entry[0], entry[1]]; | ||
} | ||
); | ||
const length = this.length; | ||
const result = new Array<EnumWrapper.Entry<V, T>>(length); | ||
for (let index = 0; index < length; ++index) { | ||
const entry = this[index]; | ||
// Create a defensive copy of the entry | ||
result[index] = [entry[0], entry[1]]; | ||
} | ||
return result; | ||
} | ||
@@ -421,3 +431,3 @@ | ||
public isKey(key: string | null | undefined): key is keyof T { | ||
return this.keySet.has(key); | ||
return key != null && isNonIndexKey(key) && this.enumObj.hasOwnProperty(key); | ||
} | ||
@@ -892,1 +902,13 @@ | ||
} | ||
/** | ||
* Return true if the specified object key value is NOT an integer index key. | ||
* @param key - An object key. | ||
* @return true if the specified object key value is NOT an integer index key. | ||
*/ | ||
function isNonIndexKey(key: string): boolean { | ||
// If after converting the key to an integer, then back to a string, the result is different | ||
// than the original key, then the key is NOT an integer index. | ||
// See ECMAScript spec section 15.4: http://www.ecma-international.org/ecma-262/5.1/#sec-15.4 | ||
return key !== String(parseInt(key, 10)); | ||
} |
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
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
152385
2226
697