isEnumValue function
Checks whether a value is one of the values of an enum, in O(1): the values of each enum are read once.
Cache
The values of each enum, in a WeakMap: nothing is kept once the enum is unused.
ts
import { isEnumValue } from 'utils';Signature
ts
export function isEnumValue<E extends EnumObject>(enumObject: E, value: unknown): value is E[keyof E]Parameters
| Name | Description |
|---|---|
E | The type of the enum object. |
enumObject | The enum to search, such as Direction. |
value | The value to look for. |
Returns
true when the value is one of the enum's values.
Example
ts
enum Direction { Up, Down }
isEnumValue(Direction, 0); // true
isEnumValue(Direction, 'Up'); // false (a name, not a value)Tests
Line coverage: 100 %.
- ✅ accepts the values of a numeric enum, not its names
- ✅ accepts the values of a string enum, not its keys
- ✅ handles numeric enums with explicit values
- ✅ handles const objects used as enums
Source
src/enum/is-enum-value.ts (on GitHub)
Uses
EnumObject: Any TypeScript enum, or aconstobject used as one.getEnumValues: Lists the values of an enum, without the names of the reverse mapping of numeric enums.
Used by
toEnumValue: Returns a value typed as an enum member: the value itself when it belongs to the enum, the fallback otherwise.
Files it needs
src/enum/is-enum-value.ts imports, directly or not:
Source code
ts
import type { EnumObject } from './enum-object';
import { getEnumValues } from './get-enum-values';
const valuesByEnum = new WeakMap<object, ReadonlySet<unknown>>();
/**
* Checks whether a value is one of the values of an enum, in O(1): the values of each enum are read once.
*
* @template E - The type of the enum object.
* @param enumObject - The enum to search, such as `Direction`.
* @param value - The value to look for.
* @returns `true` when the value is one of the enum's values.
* @cached The values of each enum, in a `WeakMap`: nothing is kept once the enum is unused.
* @example
* enum Direction { Up, Down }
* isEnumValue(Direction, 0); // true
* isEnumValue(Direction, 'Up'); // false (a name, not a value)
*/
export function isEnumValue<E extends EnumObject>(enumObject: E, value: unknown): value is E[keyof E] {
let values = valuesByEnum.get(enumObject);
if (!values) {
values = new Set(getEnumValues(enumObject));
valuesByEnum.set(enumObject, values);
}
return values.has(value);
}Test file
ts
import { isEnumValue } from './is-enum-value';
enum Direction {
Up = 0,
Down = 1,
}
enum Color {
Red = 'red',
Green = 'green',
}
enum Sparse {
Low = 1,
High = 10,
}
describe(isEnumValue, () => {
it('accepts the values of a numeric enum, not its names', () => {
expect(isEnumValue(Direction, 0)).toBe(true);
expect(isEnumValue(Direction, Direction.Down)).toBe(true);
expect(isEnumValue(Direction, 'Up')).toBe(false);
expect(isEnumValue(Direction, '0')).toBe(false);
expect(isEnumValue(Direction, 2)).toBe(false);
});
it('accepts the values of a string enum, not its keys', () => {
expect(isEnumValue(Color, 'red')).toBe(true);
expect(isEnumValue(Color, 'Red')).toBe(false);
expect(isEnumValue(Color, undefined)).toBe(false);
});
it('handles numeric enums with explicit values', () => {
expect(isEnumValue(Sparse, 10)).toBe(true);
expect(isEnumValue(Sparse, 'High')).toBe(false);
expect(isEnumValue(Sparse, 5)).toBe(false);
});
it('handles const objects used as enums', () => {
const status = { idle: 'idle', running: 'running' } as const;
expect(isEnumValue(status, 'running')).toBe(true);
expect(isEnumValue(status, 'stopped')).toBe(false);
});
});Keywords: is, enum, value, enums, function