@ncoderz/superenum
Version:
Simple, typesafe enums in TypeScript, fully compatible with standard JavaScript
205 lines (203 loc) • 7.61 kB
TypeScript
/**
* Create an enum type from an enum like object or array.
*/
type EnumType<T> = T[keyof T];
/**
* Options for the {@link Superenum.fromValue} function
*/
interface FromValueOptions {
/**
* Ignore case when validating the enum value
*/
ignoreCase?: boolean;
}
/**
* Options for the {@link Superenum.fromKey} function
*/
interface FromKeyOptions {
/**
* Ignore case when getting the enum value from the key
*/
ignoreCase?: boolean;
}
/**
* Options for the {@link Superenum.keyFromValue} function
*/
interface KeyFromValueOptions {
/**
* Ignore case when getting the enum key from the value
*/
ignoreCase?: boolean;
}
/**
* Options for the {@link Superenum.hasKey} function
*/
interface HasKeyOptions {
/**
* Ignore case when getting the enum key from the value
*/
ignoreCase?: boolean;
}
/**
* Options for the {@link Superenum.hasValue} function
*/
interface HasValueOptions {
/**
* Ignore case when getting the enum key from the value
*/
ignoreCase?: boolean;
}
/**
* i18n labels for enum values.
*/
interface Labels {
[key: string]: string;
}
/**
* Array Enum declaration
*/
type ArrayEnum<KV extends EnumKey> = ReadonlyArray<KV>;
/**
* Convert an ArrayEnum type to an ObjectEnum
*/
type ArrayEnumToObjectEnum<T extends ReadonlyArray<string>> = {
[K in T[number]]: K;
};
interface Superenum<K extends EnumKey = EnumKey, V extends EnumValue = EnumValue, T extends ObjectEnum<K, V> = ObjectEnum<K, V>> {
/**
* Validate a possible enum value, returning the enum value if valid, otherwise undefined.
*
* Since an enum value is just the value, then all this function does is check to see if the value exists on the enum, and if
* so returns it cast to the enum type, otherwise it returns undefined.
*
* Note: If the enum has duplicate values when lower-cased and
* {@link FromValueOptions.ignoreCase} is true, the data returned when when values clash will be indeterminate.
*
* @param value - the enum value to validate
* @param options - options for the function
* @returns the enum value, or undefined if the value cannot be matched to the enum
*/
fromValue(value: unknown | null | undefined, options?: FromValueOptions): EnumType<T> | undefined;
/**
* Get an enum value from its key, returning the value if key valid, otherwise undefined.
*
* Note: If the enum has duplicate keys when lower-cased and
* {@link FromKeyOptions.ignoreCase} is true, the data returned when when keys clash will be indeterminate.
*
* @param key - the enum key to convert to enum value
* @param options - options for the function
* @returns the enum represented by the key, or undefined if the key cannot be matched to the enum
*/
fromKey(key: EnumKey | number | null | undefined, options?: FromKeyOptions): EnumType<T> | undefined;
/**
* Get an enum key from its value, returning the key if value valid, otherwise undefined.
*
* Note: If the enum has duplicate values when lower-cased and
* {@link FromValueOptions.ignoreCase} is true, the data returned when when values clash will be indeterminate.
*
* @param value - the enum value to convert to enum key
* @param options - options for the function
* @returns the enum key represented by the value, or undefined if the value cannot be matched to the enum
*/
keyFromValue(value: unknown | null | undefined, options?: KeyFromValueOptions): string | undefined;
/**
* Check if an enum has a value, returning true if yes, otherwise false.
*
* Note: If the enum has duplicate values (or duplicate values when lower-cased if
* {@link HasValueOptions.ignoreCase} is true), the data returned when when values clash will be indeterminate.
*
* @param value - the enum value to check
* @param options - options for the function
* @returns true if the enum has the value, otherwise false
*/
hasValue(value: EnumType<T> | null | undefined, options?: HasValueOptions): boolean;
/**
* Check if an enum has a key, returning true if yes, otherwise false.
*
* Note: If the enum has duplicate keys when lower-cased and
* {@link FromKeyOptions.ignoreCase} is true, the data returned when when keys clash will be indeterminate.
*
* @param key - the enum key to check
* @param options - options for the function
* @returns true if the enum has the key, otherwise false
*/
hasKey(key: EnumKey | null | undefined, options?: HasKeyOptions): boolean;
/**
* Get an array of the enum values.
*
* @returns iterator over the enum values
*/
values(): readonly EnumType<T>[];
/**
* Get an array of the enum keys.
*
* @returns iterator over the enum values
*/
keys(): readonly ExtractEnumKey<K, V, T>[];
/**
* Get an array of the enum entries.
*
* @returns iterator over the enum values
*/
entries(): readonly [ExtractEnumKey<K, V, T>, EnumType<T>][];
/**
* An iterator that iterates the enum values.
*
* @returns iterator over the enum values
*/
[Symbol.iterator](): IterableIterator<EnumType<T>>;
/**
* Set i18n labels for all enum values.
*
* @param allLabels - an object containing i18n labels for each enum value
*/
setAllLabels(allLabels: {
[key: EnumValue]: Labels;
}): void;
/**
* Set i18n labels for a specific enum value.
*
* @param value - the enum value to set i18n labels for
* @param labels - an object containing i18n labels for the enum value
*/
setLabels(value: EnumType<T>, labels: Labels): void;
/**
* Get i18n labels for a specific enum value.
*
* @param value - the enum value to get i18n labels for
* @returns an object containing i18n labels for the enum value
*/
getLabels(value: EnumType<T>): Labels;
/**
* Get a label for a specific enum value in a specific locale.
*
* If no locale is provided, it will return the first label that was set.
* If no label is found for the value, it will return the value as a string.
*
* @param value - the enum value to get the label for
* @param locale - the locale to get the label for
* @returns the label for the enum value in the specified locale
*/
getLabel(value: EnumType<T>, locale?: string): string;
}
type EnumKey = string;
type EnumValue = string | number;
type ExtractEnumKey<K extends EnumKey, V extends EnumValue, T extends ObjectEnum<K, V>> = keyof T;
type ObjectEnum<K extends EnumKey, V extends EnumValue> = {
[key in K]: V;
};
/**
* Wraps an enum or enum-like object to provide methods for interacting with it.
*
* Uses a WeakMap and lazy instantiation to cache the enum's keys, values, and labels
* for fast performance while keeping memory footprint small.
*
* @param enm - an enum or enum like object
* @returns a Superenum object that provides methods to interact with the enum
*/
declare function Enum<K extends string, V extends string | number, T extends ObjectEnum<K, V>>(enm: T): Superenum<K, V, T>;
declare namespace Enum {
var fromArray: <KV extends Readonly<EnumKey>, T extends ArrayEnum<KV>>(enumeration: T) => ArrayEnumToObjectEnum<T>;
}
type EnumFunc = typeof Enum;
export { Enum, type EnumFunc, type EnumType, type FromKeyOptions, type FromValueOptions, type HasKeyOptions, type HasValueOptions, type KeyFromValueOptions, type Labels };