enum-plus
Version:
A drop-in replacement for native enum. Like native enum but much better!
425 lines (424 loc) • 18.1 kB
TypeScript
import type { EnumItemClass } from './enum-item';
import type { ITEMS, KEYS, VALUES } from './utils';
/**
* **EN:** Enum initialization options
*
* **CN:** 枚举初始化选项
*/
export type EnumInitOptions<T extends EnumInit<K, V>, K extends EnumKey<T> = EnumKey<T>, V extends EnumValue = ValueTypeFromSingleInit<T[K], K>> = {
/**
* **EN:** The name of the field in the enumeration item that stores the value, or the function to
* get the key value, default is `value`
*
* **CN:** 枚举项的value字段名,或者获取key值的函数,默认为 `value`
*/
getValue?: keyof T | ((item: T) => V);
/**
* **EN:** The name of the field in the enumeration item that stores the label, or the function to
* get the key value, default is `label`
*
* **CN:** 枚举项的label字段名,或者获取key值的函数,默认为 `label`
*/
getLabel?: keyof T | ((item: T) => string);
/**
* **EN:** The name of the field in the enumeration item that stores the key, or the function to
* get the key value, default is `key`
*
* **CN:** 枚举项的key字段名,或者获取key值的函数,默认为 `key`
*/
getKey?: keyof T | ((item: T) => string);
} & EnumItemOptions;
export interface EnumItemOptions {
/**
* **EN:** Localization function, used to convert the text of the enumeration item to localized
* text
*
* **CN:** 本地化函数,用于把枚举项文本转换为本地化文本
*
* @param content Original text | 原始文本
*
* @returns Localized text, can return any type | 本地化文本,可以返回任意类型
*/
localize?: (content: EnumLocaleExtends['LocaleKeys'] | (string & {}) | undefined) => any;
}
/**
* **EN:** Enum collection interface
*
* Should directly use `EnumClass`, but TS does not allow custom index accessors in `class`, so you
* can only use `type`
*
* **CN:** 数组的类型声明
*
* 本来可以直接使用`EnumClass`, 但是TS不允许`class`中自定义索引访问器,只能使用`type`
*/
export type IEnum<T extends EnumInit<K, V>, K extends EnumKey<T> = EnumKey<T>, V extends EnumValue = ValueTypeFromSingleInit<T[K], K>> = IEnumItems<T, K, V> & {
[key in K]: ValueTypeFromSingleInit<T[key], key, T[K] extends number | undefined ? number : key>;
} & (T extends {
items: any;
} ? {
[ITEMS]: EnumItemClass<T[K], K, V>[] & IEnumItems<T, K, V>;
} : {
/**
* **EN:** All enumeration items in the array, can be used directly as the data source of
* the AntDesign component
*
* Only supports read-only methods in ReadonlyArray<T>, does not support push, pop, and any
* modification methods
*
* **CN:** 所有枚举项的数组,可以直接作为AntDesign组件的数据源
*
* 仅支持 ReadonlyArray<T> 中的只读方法,不支持push、pop等任何修改的方法
*/
items: EnumItemClass<T[K], K, V>[] & IEnumItems<T, K, V>;
}) & (T extends {
values: any;
} ? {
[VALUES]: EnumItemClass<T[K], K, V>[] & IEnumItems<T, K, V>;
} : {
/** @deprecated Use `items` instead */
values: EnumItemClass<T[K], K, V>[] & IEnumItems<T, K, V>;
}) & (T extends {
keys: any;
} ? {
[KEYS]: K[];
} : {
/**
* **EN:** Get the key list of the enumeration item
*
* Only supports read-only methods in ReadonlyArray<T>, does not support push, pop, and any
* modification methods
*
* **CN:** 获取枚举项的key列表
*
* 常在typescript作为类型声明使用,例如: `type Props = { week: typeof Week['keys'] }`
*/
keys: K[];
});
/**
* **EN:** Enum item collection interface, excluding members inherited from the array
*
* **CN:** 枚举项集合接口,不包含从数组集成的成员
*
* @template T Enum collection initialization data type | 枚举集合初始化数据的类型
*
* @interface IEnumItems
*/
export interface IEnumItems<T extends EnumInit<K, V>, K extends EnumKey<T> = EnumKey<T>, V extends EnumValue = ValueTypeFromSingleInit<T[K], K>> {
/**
* **EN:** Get the enumeration item by key or value
*
* **CN:** 获取某个枚举项的label显示名称
*
* @param value Enum item value or key | 枚举项的value或key
*
* @returns {string | undefined} Display name of the enumeration item | 枚举项的label显示名称
*/
label(keyOrValue?: string | number): string | undefined;
/**
* **EN:** Get the key corresponding to a certain enumeration item
*
* **CN:** 获取某个枚举项对应的key
*/
key(value?: string | number): K | undefined;
/**
* **EN:** Get the value corresponding to a certain enumeration item
*
* **CN:** 判断某个枚举项是否存在
*
* @param keyOrValue Enum item key or value | 枚举项的key或value
*/
has(keyOrValue?: string | number): boolean;
/**
* **EN:** Generate an array of objects that can be bound to those `options like` of components
* such as Select, Radio, and Checkbox, following the data specification of ant-design
*
* **CN:** 生成一个对象数组,可以绑定到 Select、Radio、Checkbox 等组件的`options`,遵循 ant-design 的数据规范
*
* @example
* [
* { value: 0, label: 'Sunday' },
* { value: 1, label: 'Monday' },
* ];
*
* @see https://ant.design/components/checkbox-cn#option
*/
toSelect(): EnumItemOptionData<K, V>[];
/**
* **EN:** Generate an array of objects that can be bound to those `options like` of components
* such as Select, Radio, and Checkbox, following the data specification of ant-design
*
* **CN:** 生成一个对象数组,可以绑定到 Select、Radio、Checkbox 等组件的`options`,遵循 ant-design 的数据规范
*
* @example
* [
* { value: 0, label: 'Sunday' },
* { value: 1, label: 'Monday' },
* ];
*
* @param config Custom options | 自定义选项
*
* @see https://ant.design/components/checkbox-cn#option
*/
toSelect(config: ToSelectConfig & BooleanFirstOptionConfig<V>): EnumItemOptionData<K | '', V | ''>[];
/**
* **EN:** Generate an array of objects that can be bound to those `options like` of components
* such as Select, Radio, and Checkbox, following the data specification of ant-design
*
* **CN:** 生成一个对象数组,可以绑定到 Select、Radio、Checkbox 等组件的`options`,遵循 ant-design 的数据规范
*
* @example
* [
* { value: 0, label: 'Sunday' },
* { value: 1, label: 'Monday' },
* ];
*
* @param config Custom options | 自定义选项
*
* @see https://ant.design/components/checkbox-cn#option
*/
toSelect<FK, FV>(config: ToSelectConfig & ObjectFirstOptionConfig<FK, FV>): EnumItemOptionData<K | (FK extends never ? FV : FK), V | (FV extends never ? V : FV)>[];
/** @deprecated Use `toSelect` instead */
options(): EnumItemOptionData<K, V>[];
/** @deprecated Use `toSelect` instead */
options(config: ToSelectConfig & BooleanFirstOptionConfig<V>): EnumItemOptionData<K | '', V | ''>[];
/** @deprecated Use `toSelect` instead */
options<FK, FV>(config: ToSelectConfig & ObjectFirstOptionConfig<FK, FV>): EnumItemOptionData<K | (FK extends never ? FV : FK), V | (FV extends never ? V : FV)>[];
/**
* **EN:** Generate an object array that can be bound to the data source of components such as
* Menu and Dropdown, following the data specification of ant-design
*
* **CN:** 生成一个对象数组,可以绑定到 Menu、Dropdown 等组件的数据源,遵循 ant-design 的数据规范
*
* @example
* [
* { key: 0, label: 'Sunday' },
* { key: 1, label: 'Monday' },
* ];
*
* @see https://ant.design/components/menu-cn#itemtype
*/
toMenu(): MenuItemOption<V>[];
/** @deprecated Use `toMenu` instead */
menus(): MenuItemOption<V>[];
/**
* **EN:** Generate an object array that can add filtering function to table columns, following
* the data specification of ant-design Table component
*
* **CN:** 生成一个对象数组,可以给表格列增加筛选功能,遵循 ant-design Table 组件的数据规范
*
* @example
* [
* { text: 'Sunday', value: 0 },
* { text: 'Monday', value: 1 },
* ];
*
* @see https://ant.design/components/table-cn#components-table-demo-head
* @see https://ant.design/components/table-cn#column
*/
toFilter(): ColumnFilterItem<V>[];
/** @deprecated Use `toFilter` instead */
filters(): ColumnFilterItem<V>[];
/**
* **EN:** Generate a Map object that can be used to bind Select, Checkbox and other form
* components, following the data specification of ant-design-pro
*
* **CN:** 生成一个Map对象,可以用来绑定Select、Checkbox等表单组件,遵循 ant-design-pro 的数据规范
*
* @example
* {
* "0": { "text": "Sunday" },
* "1": { "text": "Monday" }
* }
*
* @see https://procomponents.ant.design/components/schema#valueenum-1
* @see https://procomponents.ant.design/components/field-set#proformselect
*/
toValueMap(): ValueMap<V>;
/** @deprecated Use `toValueMap` instead */
valuesEnum(): ValueMap<V>;
/**
* **EN:** Get the enumeration item by key or value
*
* **CN:** 获取枚举集合的初始化对象
*
* @memberof IEnumValues
*
* @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
*/
raw<IK extends V | K | Exclude<EnumValue, string> | (string & {})>(keyOrValue: IK): IK extends K ? T[IK] : IK extends V ? T[FindEnumKeyByValue<T, IK>] : T[K] | undefined;
/**
* **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.
*
* **CN:** 枚举项原始初始化对象的类型,如果在枚举项上增加了自定义字段的话,可以用这种方式获取到。
*/
rawType: T[K];
}
/** @deprecated use `IEnumItems` instead */
export type IEnumValues<T extends EnumInit<K, V>, K extends EnumKey<T> = EnumKey<T>, V extends EnumValue = ValueTypeFromSingleInit<T[K], K>> = IEnumItems<T, K, V>;
export type EnumItemLabel = EnumLocaleExtends['LocaleKeys'] | (string & {});
export type EnumInit<K extends keyof any = string, V extends EnumValue = EnumValue> = NumberEnumInit<K> | StringEnumInit<K> | StringNumberEnumInit<K> | BooleanEnumInit<K> | DateEnumInit<K> | RegExpEnumInit<K> | StandardEnumInit<K, V> | ValueOnlyEnumInit<K, V> | LabelOnlyEnumInit<K> | CompactEnumInit<K> | OmitEnumInit<K>;
export type NumberEnumInit<K extends keyof any> = Record<K, number>;
export type StringEnumInit<K extends keyof any> = Record<K, string>;
export type StringNumberEnumInit<K extends keyof any> = Record<K, string | number>;
export type BooleanEnumInit<K extends keyof any> = Record<K, boolean>;
export type DateEnumInit<K extends keyof any> = Record<K, Date>;
export type RegExpEnumInit<K extends keyof any> = Record<K, RegExp>;
export type StandardEnumInit<K extends keyof any, V extends EnumValue> = Record<K, StandardEnumItemInit<V>>;
export type ValueOnlyEnumInit<K extends keyof any, V extends EnumValue> = Record<K, ValueOnlyEnumItemInit<V>>;
export type LabelOnlyEnumInit<K extends keyof any> = Record<K, LabelOnlyEnumItemInit>;
export type CompactEnumInit<K extends keyof any> = Record<K, CompactEnumItemInit>;
export type OmitEnumInit<K extends keyof any> = Record<K, undefined>;
export type EnumItemInit<V extends EnumValue = EnumValue> = EnumValue | StandardEnumItemInit<V> | ValueOnlyEnumItemInit<V> | LabelOnlyEnumItemInit | CompactEnumItemInit | undefined;
export interface StandardEnumItemInit<V extends EnumValue> {
value: V;
label: EnumItemLabel;
}
export interface ValueOnlyEnumItemInit<V extends EnumValue> {
value: V;
}
export interface LabelOnlyEnumItemInit {
label: EnumItemLabel;
}
export type CompactEnumItemInit = Record<string, never>;
/** Data structure of ant-design Select options */
export interface EnumItemOptionData<K, V> {
/** Option value */
value: V;
/** Option label */
label: string;
/** Option key, default is `value` */
key: K;
}
/** Data structure of column filter items of ant-design Table */
export interface ColumnFilterItem<V> {
/** Display name */
text: string;
/** Value */
value: V;
}
/** Data structure of ant-design Menu items */
export interface MenuItemOption<V> {
/** Key of menu item */
key: V;
/** Menu item text */
label: string;
}
export type ValueMap<V extends EnumValue> = Record<`${Exclude<V, symbol | RegExp | Date>}`, {
text: string;
}>;
/** Enum value type, support number, string, symbol */
export type EnumValue = keyof any | bigint | boolean | Date | RegExp;
/** Enum key collection */
export type EnumKey<T> = keyof T;
/** More options for the options method */
export type ToSelectConfig = object;
export interface BooleanFirstOptionConfig<V> {
/**
* **EN:** Add a default option at the top
*
* - `true`: the option uses the default value, `value` is `''`, `label` is `'All'`;
* - `false`: the default option is not added;
*
* **CN:** 在头部添加一个默认选项
*
* - `true`:选项使用默认值,`value`为`''`,`label`为`'全部'`
* - `false`:不添加默认选项
*
* @default false
*/
firstOption: boolean;
/**
* **EN:** Default option value, default is `''`
*
* **CN:** 默认选项的值,默认为`''`
*
* @default ''
*/
firstOptionValue?: V;
/**
* **EN:** Default option label, default is `'All'`. If a localization method is set, the
* localization method will be automatically called
*
* **CN:** 默认选项的显示文本,默认为`'All'`。如果设置了本地化方法,则会自动调用本地化方法
*/
firstOptionLabel?: string;
}
export interface ObjectFirstOptionConfig<K, V> {
/**
* **EN:** Configuration of the first option
*
* **CN:** 首行选项的配置
*/
firstOption?: EnumOptionConfig<K, V>;
/**
* **EN:** Add a default option at the top
*
* **CN:** 默认选项的值,默认为`''`
*/
firstOptionValue?: never;
/**
* **EN:** Default option label, default is `'All'`. If a localization method is set, the
* localization method will be automatically called
*
* **CN:** 默认选项的显示文本,默认为`'All'`。如果设置了本地化方法,则会自动调用本地化方法
*/
firstOptionLabel?: never;
}
/** Built-in resources */
export type BuiltInLocaleKeys = 'enum-plus.options.all';
export type EnumOptionConfig<K, V> = Omit<EnumItemOptionData<K, V>, 'key'> & Partial<Pick<EnumItemOptionData<K, V>, 'key'>>;
/** Infer the value type from the initialization object of the enumeration item */
export type ValueTypeFromSingleInit<T, Key = string, Fallback = Key> = T extends EnumValue ? T : T extends StandardEnumItemInit<infer V> ? V : T extends ValueOnlyEnumItemInit<infer V> ? V : T extends LabelOnlyEnumItemInit ? Key : T extends CompactEnumItemInit ? Key : T extends undefined ? Fallback : never;
/** Infer the value type from the initialization object of the enumeration collection */
export type ValueTypeFromEnumInit<T, K extends EnumKey<T> = EnumKey<T>> = T extends NumberEnumInit<K> ? number : T extends StringEnumInit<K> ? string : T extends BooleanEnumInit<K> ? string : T extends StringNumberEnumInit<K> ? string | number : T extends StandardEnumInit<K, infer V> ? V : T extends ValueOnlyEnumInit<K, infer V> ? V : T extends LabelOnlyEnumInit<K> ? K : T extends CompactEnumInit<K> ? K : T extends OmitEnumInit<K> ? K : K;
export type FindEnumKeyByValue<T, V extends EnumValue> = {
[K in keyof T]: T[K] extends V ? K : T[K]['value'] extends V ? K : object extends T[K] ? K extends V ? K : never : undefined extends T[K] ? K extends V ? K : never : never;
}[keyof T];