UNPKG

enum-plus

Version:

A drop-in replacement for native enum. Like native enum but much better!

377 lines (376 loc) 22.4 kB
import type { EnumItemOptions } from './enum-item'; import { EnumItemClass } from './enum-item'; import type { EnumInit, EnumKey, EnumValue, ExactEqual, FindEnumKeyByValue, FindKeyByMeta, FindLabelByValue, FindValueByKey, FindValueByMeta, ListItem, PrimitiveOf, StandardEnumInit, StandardEnumItemInit, ValueTypeFromSingleInit } from './types'; import { IS_ENUM_ITEMS, KEYS, VALUES } from './utils'; /** * Enum items array, mostly are simple wrappers for EnumCollectionClass * * @template T Type of the initialization data of the enum collection * * @class EnumItemsArray * * @extends {EnumItemClass<T, K, V>[]} * * @implements {IEnumItems<T, K, V>} */ export declare class EnumItemsArray<const T extends EnumInit<K, V>, K extends EnumKey<T> = EnumKey<T>, V extends EnumValue = ValueTypeFromSingleInit<T[K], K>, const P = any> extends Array<EnumItemClass<T[K], K, V, P>> implements IEnumItems<T, K, V, P> { private __raw__; /** * - **EN:** A boolean value indicates that this is an enum items array. * - **CN:** 布尔值,表示这是一个枚举项数组 */ get [IS_ENUM_ITEMS](): true; readonly [KEYS]: K[]; readonly [VALUES]: V[]; readonly labels: string[]; readonly named: { [key in keyof T]: EnumItemClass<T[key], key, ValueTypeFromSingleInit<T[key], key, T[key] extends number | undefined ? number : key>, P>; }; readonly meta: IEnumItems<T, K, V, P>['meta']; private _runtimeError; /** * Instantiate an enum items array * * @memberof EnumItemsArray * * @param {T} raw Original initialization data object * @param {EnumItemOptions<T[K], K, V, P> | undefined} options Enum item options */ constructor(raw: T, options: EnumItemOptions<T[K], K, V, P> | undefined); [Symbol.hasInstance]<T>(instance: T): instance is Extract<T, K | V>; label<KV extends V | K | NonNullable<PrimitiveOf<V>> | NonNullable<PrimitiveOf<K>> | undefined>(keyOrValue: KV): (undefined extends KV ? undefined : never) | (KV extends undefined ? undefined : NonNullable<KV> extends K ? T[NonNullable<KV>] extends { label: unknown; } ? T[NonNullable<KV>]['label'] extends undefined ? NonNullable<KV> : string : NonNullable<KV> : NonNullable<KV> extends V ? FindLabelByValue<T, NonNullable<KV>> : PrimitiveOf<K> extends KV ? string | undefined : PrimitiveOf<V> extends KV ? string | undefined : undefined); key<IV extends V | NonNullable<PrimitiveOf<V>> | undefined>(value?: IV): (undefined extends IV ? undefined : never) | (IV extends undefined ? undefined : NonNullable<IV> extends V ? FindEnumKeyByValue<T, NonNullable<IV>> : PrimitiveOf<V> extends NonNullable<IV> ? K | undefined : undefined); raw(): T; raw<IK extends V | K | Exclude<EnumValue, string> | NonNullable<string>>(keyOrValue: IK): IK extends K ? T[IK] : IK extends V ? T[FindEnumKeyByValue<T, IK>] : T[K] | undefined; has<KV>(keyOrValue?: KV): keyOrValue is Extract<KV, K | V>; findBy<FK extends 'key' | 'value' | 'label' | Exclude<keyof T[keyof T], 'key' | 'value' | 'label'>, FV>(field: FK, value: FV): FK extends 'key' ? FV extends K ? EnumItemClass<T[FV], FV, FindValueByKey<T, FV>> : EnumItemClass<T[K], K, V, P> | undefined : FK extends 'value' ? FV extends V ? EnumItemClass<T[FindEnumKeyByValue<T, FV>], FindEnumKeyByValue<T, FV>, FV> : EnumItemClass<T[K], K, V, P> | undefined : FK extends 'label' ? EnumItemClass<T[K], K, V, P> | undefined : FV extends T[keyof T][FK] ? EnumItemClass<T[FindKeyByMeta<T, FK, FV>], FindKeyByMeta<T, FK, FV>, FindValueByMeta<T, FK, FV>> : EnumItemClass<T[K], K, V, P> | undefined; toList(): ListItem<V, 'value', 'label'>[]; toList<FOV extends string | ((item: EnumItemClass<T[K], K, V, P>) => string), FOL extends string | ((item: EnumItemClass<T[K], K, V, P>) => string), R extends Record<string, unknown> = never>(config: ToListConfig<T, FOV, FOL, K, V, R, P>): ListItem<V, FOV extends (item: EnumItemClass<T[K], K, V, P>) => infer R ? R : FOV, FOL extends (item: EnumItemClass<T[K], K, V, P>) => infer R ? R : FOL, R>[]; toMap(): MapResult<T, 'value', 'label', K, V, P>; toMap<KS extends EnumItemFields | ((item: EnumItemClass<T[K], K, V, P>) => any), VS extends EnumItemFields | ((item: EnumItemClass<T[K], K, V, P>) => any)>(config: ToMapConfig<T, KS, VS, K, V, P>): MapResult<T, KS, VS, K, V, P>; /** Stub method, only for typing usages, not for runtime calling */ get valueType(): V; /** Stub method, only for typing usages, not for runtime calling */ get keyType(): K; /** Stub method, only for typing usages, not for runtime calling */ get rawType(): T[K]; } /** * - **EN:** Enum item collection interface, excluding members inherited from the array * - **CN:** 枚举项集合接口,不包含从数组集成的成员 * * @template T The type of enum initialization | 枚举初始化的类型 * @template K The type of enum keys | 枚举键的类型 * @template V The type of enum values | 枚举值的类型 * * @interface IEnumItems */ export interface IEnumItems<T extends EnumInit<K, V>, K extends EnumKey<T> = EnumKey<T>, V extends EnumValue = ValueTypeFromSingleInit<T[K], K>, P = any> extends InheritableEnumItems<T, K, V, P> { /** * - **EN:** A boolean value indicates that this is an enum items array. * - **CN:** 布尔值,表示这是一个枚举项数组 */ [IS_ENUM_ITEMS]: true; /** * - **EN:** Get all keys of the enumeration items as an array * * > Only supports read-only methods in `ReadonlyArray<T>`, does not support push, pop, and any * > modification methods * * - **CN:** 获取枚举项的全部keys列表 * * > 仅支持 `ReadonlyArray<T>` 中的只读方法,不支持push、pop等任何修改的方法 */ readonly [KEYS]: K[]; /** * - **EN:** Get all values of the enumeration items as an array * * > Only supports read-only methods in `ReadonlyArray<T>`, does not support push, pop, and any * > modification methods * * - **CN:** 获取枚举项的全部values列表 * * > 仅支持 `ReadonlyArray<T>` 中的只读方法,不支持push、pop等任何修改的方法 */ readonly [VALUES]: V[]; /** * - **EN:** Get all labels of the enumeration items as an array * * > Only supports read-only methods in `ReadonlyArray<T>`, does not support push, pop, and any * > modification methods * * - **CN:** 获取枚举项的全部labels列表 * * > 仅支持 `ReadonlyArray<T>` 中的只读方法,不支持push、pop等任何修改的方法 */ readonly labels: string[]; /** * - **EN:** A mapping of enum keys to their corresponding enum item classes. This is useful for * quick access to specific enum items. * - **CN:** 枚举键到其对应的枚举项类的映射,对于快速访问枚举项非常有用 */ named: { [key in keyof T]: EnumItemClass<T[key], key, ValueTypeFromSingleInit<T[key], key, T[key] extends number | undefined ? number : key>, P>; }; /** * - **EN:** Get all custom meta fields of the enumeration items as an object, where the keys are * the field names, and values are the raw values of each field * - **CN:** 获取枚举项的全部自定义元字段,返回一个对象,其中key为字段名,value为每个字段的原始值数组 */ readonly meta: T extends StandardEnumInit<K, V> ? { [K in Exclude<keyof T[keyof T], 'key' | 'value' | 'label'>]: T[keyof T][K][]; } : {}; } export interface InheritableEnumItems<T extends EnumInit<K, V>, K extends EnumKey<T> = EnumKey<T>, V extends EnumValue = ValueTypeFromSingleInit<T[K], K>, P = any> { /** * - **EN:** A method that determines if a constructor object recognizes an object as one of the * constructor’s instances. Called by the semantics of the `instanceof` operator. * - **CN:** 一个方法,用于确定构造函数对象是否将对象识别为构造函数的实例之一。由 `instanceof` 运算符的语义调用。 */ [Symbol.hasInstance]<T>(instance: T): instance is Extract<T, K | V>; /** * - **EN:** The enum collection name, supports localization. * * > Note that it usually returns a string, but if a custom `localize` function is set, the return * > value may vary depending on the implementation of the method. * * - **CN:** 枚举集合显示名称,支持本地化。 * * > 注意,通常情况下返回的是字符串,但如果设置了自定义的 `localize` 函数,则返回值可能有所不同,取决于方法的实现 * * @returns {string | undefined} The localized name of the enum collection, or undefined if not * set | 枚举集合的本地化名称,如果未设置则为 undefined */ readonly name?: string; /** * - **EN:** Get the label (also known as display name) of the enumeration item, supports getting by * value or key * - **CN:** 获取枚举项的标签(亦称显示名称),支持通过枚举项的 value 或 key 获取 * * @param keyOrValue - The value or key of the enumeration item | 枚举项的 value 或 key * * @returns The label of the enumeration item or the key if the label is not defined | 枚举项的标签或 * key(如果标签未定义) */ label<KV extends V | K | NonNullable<PrimitiveOf<V>> | NonNullable<PrimitiveOf<K>> | undefined>(keyOrValue: KV): (undefined extends KV ? undefined : never) | (KV extends undefined ? undefined : NonNullable<KV> extends K ? T[NonNullable<KV>] extends { label: unknown; } ? T[NonNullable<KV>]['label'] extends undefined ? NonNullable<KV> : string : NonNullable<KV> : NonNullable<KV> extends V ? FindLabelByValue<T, NonNullable<KV>> : PrimitiveOf<K> extends KV ? string | undefined : PrimitiveOf<V> extends KV ? string | undefined : undefined); /** * - **EN:** Get the key of the enumeration item by its value * - **CN:** 根据枚举项的 value 获取其 key * * @param value The value of the enumeration item | 枚举项的 value * * @returns The key of the enumeration item, or undefined if not found | 枚举项的 key,如果未找到则返回 * undefined */ key<IV extends V | NonNullable<PrimitiveOf<V>> | undefined>(value: IV): (undefined extends IV ? undefined : never) | (IV extends undefined ? undefined : NonNullable<IV> extends V ? FindEnumKeyByValue<T, NonNullable<IV>> : PrimitiveOf<V> extends NonNullable<IV> ? K | undefined : undefined); /** * - **EN:** Get the enumeration item by key or value * - **CN:** 获取枚举集合的初始化对象 * * @returns {T} Enum collection initialization object | 初始化对象集合 */ raw(): T; /** * - **EN:** Get the original initialization object of a certain enumeration item. If custom fields * are added to the enumeration item, you can use this method to get them. * - **CN:** 获取某个枚举项的原始初始化对象。如果在枚举项上增加了自定义字段的话,可以用这种方式获取到。 * * @param keyOrValue Enum key or value | 枚举key或value * * @returns The original initialization object of the enumeration item, or undefined if not found * | 枚举项的原始初始化对象,如果未找到则返回 undefined */ raw<KV extends V | K | NonNullable<PrimitiveOf<V>> | NonNullable<PrimitiveOf<K>> | undefined>(keyOrValue: KV): (undefined extends KV ? undefined : never) | (KV extends undefined ? undefined : NonNullable<KV> extends K ? T[NonNullable<KV>] : NonNullable<KV> extends V ? T[FindEnumKeyByValue<T, NonNullable<KV>>] : PrimitiveOf<K> extends KV ? T[K] | undefined : PrimitiveOf<V> extends KV ? T[K] | undefined : undefined); /** * - **EN:** Get the value corresponding to a certain enumeration item * - **CN:** 判断某个枚举项是否存在 * * @param keyOrValue Enum item key or value | 枚举项的key或value * * @returns {boolean} Whether the enumeration item exists | 枚举项是否存在 */ has<KV>(keyOrValue?: KV): keyOrValue is Extract<KV, K | V>; /** * **EN:** Find an enumeration item by key or value, or by custom meta fields * * **CN:** 通过key或value查找枚举项,或通过自定义元字段查找 * * @param field The field to search by | 要查找的字段 * @param value The value to search | 要查找的值 * * @returns The found enumeration item or `undefined` if not found | 找到的枚举项,如果未找到则返回 `undefined` */ findBy<FK extends 'key' | 'value' | 'label' | Exclude<keyof T[keyof T], 'key' | 'value' | 'label'>, const FV>(field: FK, value: FV): FK extends 'key' ? FV extends K ? EnumItemClass<T[FV], FV, FindValueByKey<T, FV>> : EnumItemClass<T[K], K, V, P> | undefined : FK extends 'value' ? FV extends V ? EnumItemClass<T[FindEnumKeyByValue<T, FV>], FindEnumKeyByValue<T, FV>, FV> : EnumItemClass<T[K], K, V, P> | undefined : FK extends 'label' ? EnumItemClass<T[K], K, V, P> | undefined : FV extends T[keyof T][FK] ? EnumItemClass<T[FindKeyByMeta<T, FK, FV>], FindKeyByMeta<T, FK, FV>, FindValueByMeta<T, FK, FV>> : EnumItemClass<T[K], K, V, P> | undefined; /** * - **EN:** Generate an object array containing all enumeration items * - **CN:** 生成一个对象数组,包含所有的枚举项 * * @example * [ * { value: 0, label: 'Sunday' }, * { value: 1, label: 'Monday' }, * ]; * * @returns An object array of all enumeration items | 所有枚举项的对象数组 */ toList(): ListItem<V, 'value', 'label'>[]; /** * - **EN:** Generate an object array containing all enumeration items, with customizable value and * label field names * - **CN:** 生成一个对象数组,包含所有的枚举项,可自定义值和标签字段名 * * @example * Week.toList({ * valueField: 'id', * labelField: 'name', * }); * * [ * { id: 0, name: 'Sunday' }, * { id: 1, name: 'Monday' }, * ]; * * @param config Custom options, supports customizing value and label field names | * 自定义选项,支持自定义值和标签字段名 * * @returns An object array of all enumeration items in the specified value and label fields | * 所有枚举项的对象数组,按照指定的值和标签字段格式 */ toList<FOV extends string | ((item: EnumItemClass<T[K], K, V, P>) => string), FOL extends string | ((item: EnumItemClass<T[K], K, V, P>) => string), R extends Record<string, unknown> = never>(config: ToListConfig<T, FOV, FOL, K, V, R, P>): ListItem<V, FOV extends (item: EnumItemClass<T[K], K, V, P>) => infer R ? R : FOV, FOL extends (item: EnumItemClass<T[K], K, V, P>) => infer R ? R : FOL, R>[]; /** * - **EN:** Generate a mapping object of all enum items, where the keys are the values of the enum * and the values are the labels of the enum * - **CN:** 生成一个映射对象,包含所有的枚举项,key为枚举值,value为枚举标签 * * @example * { * "0": "Sunday", * "1": "Monday" * } * * @returns A mapping object of all enum items | 所有枚举项的映射对象 */ toMap(): MapResult<T, 'value', 'label', K, V, P>; /** * - **EN:** Generate a mapping object of all enum items, with customizable key and value fields * - **CN:** 生成一个映射对象,包含所有的枚举项,可自定义键和值字段 * * @example * Week.toMap({ key: 'value', value: 'label' }); * * ({ '0': 'Sunday', '1': 'Monday' }); * * /// Allow custom function, and meta fields can be used * Week.toMap({ * key: 'key', * value: (item) => ({ id: item.value, name: item.label, foo: item.raw.foo }), * }); * * ({ * Sunday: { id: 0, name: 'Sunday', foo: 'bar' }, * Monday: { id: 1, name: 'Monday', foo: 'b' }, * }); * * @param config Custom options, supports customizing key and value fields | 自定义选项,支持自定义键和值字段 * * @returns A mapping object of all enum items in the specified key and value fields | * 所有枚举项的映射对象,按照指定的键和值字段格式 */ toMap<FOK extends EnumItemFields | ((item: EnumItemClass<T[K], K, V, P>) => any), FOV extends EnumItemFields | ((item: EnumItemClass<T[K], K, V, P>) => any)>(config: ToMapConfig<T, FOK, FOV, K, V, P>): MapResult<T, FOK, FOV, K, V, P>; /** * - **EN:** The data type of all enumeration values * * > 📣 Note: Can only be used as a type declaration, cannot be called at runtime * * - **CN:** 所有枚举值的数据类型 * * > 📣 注意:仅可作为类型声明使用,不可在运行时调用 * * @example * // Declare the type of the variable | 声明变量的类型 * const week: typeof Week.valueType = Week.Monday; // 0 * * // Declare type field | 声明类型字段 * type Props = { * week: typeof Week.valueType; // 0 | 1 * }; */ valueType: V; /** * - **EN:** The data type of all enumeration keys * * > 📣 Note: Can only be used as a type declaration, cannot be called at runtime * * - **CN:** 所有枚举key的数据类型 * * > 📣 注意:仅可作为类型声明使用,不可在运行时调用 * * @example * // Declare the type of the variable | 声明变量的类型 * const weekName: typeof Week.keyType = 'Sunday'; // "Sunday" | "Monday" * * // Declare type field | 声明类型字段 * type Props = { * weekName: typeof Week.keyType; // "Sunday" | "Monday" * }; */ keyType: K; /** * - **EN:** The type of the original initialization object of the enumeration item. If custom * fields are added to the enumeration item, you can use this method to get them. * * > 📣 Note: Can only be used as a type declaration, cannot be called at runtime * * - **CN:** 枚举项原始初始化对象的类型,如果在枚举项上增加了自定义字段的话,可以用这种方式获取到。 * * > 📣 注意:仅可作为类型声明使用,不可在运行时调用 */ rawType: T[K]; } /** More options for the options method */ export interface ToListConfig<T extends EnumInit<K, V>, FOV extends string | ((item: EnumItemClass<T[K], K, V, P>) => string), FOL extends string | ((item: EnumItemClass<T[K], K, V, P>) => string), K extends EnumKey<T> = EnumKey<T>, V extends EnumValue = ValueTypeFromSingleInit<T[K], K>, R extends Record<string, unknown> = never, P = any> { /** * - **EN:** The name of the value field in the output object, or a function to get the field name, * default is `value` * - **CN:** 输出对象的value字段名,或者获取字段名的函数,默认为 `value` */ valueField?: FOV; /** * - **EN:** The name of the label field in the output object, or a function to get the field name, * default is `label` * - **CN:** 输出对象的label字段名,或者获取字段名的函数,默认为 `label` */ labelField?: FOL; /** * - **EN:** A function to add extra fields to each item in the output object * - **CN:** 一个函数,用于为输出对象中的每个项添加额外的字段 */ extra?: (item: EnumItemClass<T[K], K, V, P>) => R; } export interface ToMapConfig<T extends EnumInit<K, V>, KS extends EnumItemFields | ((item: EnumItemClass<T[K], K, V, P>) => any), VS extends EnumItemFields | ((item: EnumItemClass<T[K], K, V, P>) => any), K extends EnumKey<T> = EnumKey<T>, V extends EnumValue = ValueTypeFromSingleInit<T[K], K>, P = any> { /** * - **EN:** A field of `EnumItem` as the key of the output object, or a function to get the key of * items, default is `key` * - **CN:** 作为输出对象key的`EnumItem`字段名,或者获取输出对象key的函数,默认为 `key` */ keySelector?: KS; /** * - **EN:** A field of `EnumItem` as the value of the output object, or a function to get the value * of items, default is `value` * - **CN:** 作为输出对象value的`EnumItem`字段名,或者获取输出对象value的函数,默认为 `value` */ valueSelector?: VS; } export type MapResult<T extends EnumInit<K, V>, KS extends EnumItemFields | ((item: EnumItemClass<T[K], K, V, P>) => string | symbol), VS extends EnumItemFields | ((item: EnumItemClass<T[K], K, V, P>) => any), K extends EnumKey<T> = EnumKey<T>, V extends EnumValue = ValueTypeFromSingleInit<T[K], K>, P = any> = { [key in ExactEqual<KS, EnumItemFields | ((item: EnumItemClass<T[K], K, V, P>) => string | symbol)> extends true ? // eslint-disable-next-line @typescript-eslint/no-explicit-any EnumItemClass<T[K], K, V, P>['value'] & keyof any : KS extends EnumItemFields ? // eslint-disable-next-line @typescript-eslint/no-explicit-any EnumItemClass<T[K], K, V, P>[KS] & keyof any : KS extends (item: any) => infer R ? R : never]: ExactEqual<VS, EnumItemFields | ((item: EnumItemClass<T[K], K, V, P>) => unknown)> extends true ? ExactEqual<KS, EnumItemFields | ((item: EnumItemClass<T[K], K, V, P>) => string | symbol)> extends true ? FindLabelByValue<T, key> : EnumItemClass<T[K], K, V, P>['label'] : VS extends EnumItemFields ? EnumItemClass<T[K], K, V, P>[VS] : VS extends (item?: any) => infer R ? R : never; }; export type EnumItemFields = Exclude<{ [key in keyof EnumItemClass<StandardEnumItemInit<string>>]: EnumItemClass<StandardEnumItemInit<string>>[key] extends (...args: any[]) => unknown ? never : key; }[keyof EnumItemClass<StandardEnumItemInit<string>>] & string, 'raw'>; export declare function parseKeys<const T extends EnumInit<K, V>, K extends EnumKey<T> = EnumKey<T>, V extends EnumValue = ValueTypeFromSingleInit<T[K], K>>(raw: EnumInit<K, V>): K[];