enum-plus
Version:
A drop-in replacement for native enum. Like native enum but much better!
102 lines (101 loc) • 6.77 kB
TypeScript
import type { EnumLocaleExtends } from 'enum-plus/extension';
export type { LocalizeInterface } from './localize-interface';
export type EnumItemLabel = EnumLocaleExtends['LocaleKeys'] & NonNullable<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> | MetaOnlyEnumInit<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 MetaOnlyEnumInit<K extends keyof any> = Record<K, MetaOnlyEnumItemInit>;
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 | MetaOnlyEnumItemInit | CompactEnumItemInit | undefined;
export interface StandardEnumItemInit<V extends EnumValue> {
value: V;
label: EnumItemLabel;
}
export interface ValueOnlyEnumItemInit<V extends EnumValue> {
value: V;
label?: never;
}
export interface LabelOnlyEnumItemInit {
label: EnumItemLabel;
value?: never;
}
export interface MetaOnlyEnumItemInit {
value?: never;
label?: never;
[meta: string]: unknown;
}
export type CompactEnumItemInit = Record<string, never>;
/**
* - **EN:** Data structure of enumeration item options, used in `toList` method
* - **CN:** 枚举项选项的数据结构,用于`toList`方法
*
* @template V Value type of the enumeration item | 枚举项的值类型
* @template FOL Field name of the label, default is `label` | 标签字段名,默认为 `label`
* @template FOV Field name of the value, default is `value` | 值字段名,默认为 `value`
*/
export type ListItem<V extends EnumValue = EnumValue, FOV extends string = 'value', FOL extends string = 'label', R extends Record<string, unknown> = never> = Record<FOV, V> & Record<FOL, string> & (IsNever<R> extends true ? {} : R);
/** 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;
/** 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 MetaOnlyEnumItemInit ? 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 MetaOnlyEnumInit<K> ? K : T extends CompactEnumInit<K> ? K : T extends OmitEnumInit<K> ? K : K;
/**
* - **EN:** Find the key of the enumeration item by value
* - **CN:** 通过值查找枚举项的key
*
* @template T Enum collection initialization data type | 枚举集合初始化数据的类型
* @template V Enum value type | 枚举值的类型
*/
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];
/**
* - **EN:** Find the label of the enumeration item by value
* - **CN:** 通过值查找枚举项的label显示名称
*
* @template T Enum collection initialization data type | 枚举集合初始化数据的类型
* @template V Enum value type | 枚举值的类型
*/
export type FindLabelByValue<T, V extends EnumValue, RAW = T[FindEnumKeyByValue<T, V>]> = RAW extends {
label: unknown;
} ? string : FindEnumKeyByValue<T, V>;
/**
* - **EN:** Find the value of the enumeration item by key
* - **CN:** 通过key查找枚举项的值
*
* @template T Enum collection initialization data type | 枚举集合初始化数据的类型
* @template K Enum key type | 枚举key的类型
*/
export type FindValueByKey<T, K extends EnumKey<T>> = T[K] extends EnumValue ? T[K] : T[K] extends StandardEnumItemInit<infer V> ? V : T[K] extends ValueOnlyEnumItemInit<infer V> ? V : T[K] extends LabelOnlyEnumItemInit ? K : T[K] extends MetaOnlyEnumItemInit ? K : T[K] extends CompactEnumItemInit ? K : T[K] extends undefined ? K : never;
export type FindKeyByMeta<T, MK extends keyof T[keyof T], MV> = {
[K in keyof T]: T[K] extends Record<MK, MV> ? K : never;
}[keyof T];
export type FindValueByMeta<T, MK extends keyof T[keyof T], MV> = {
[K in keyof T]: T[K] extends Record<MK, MV> ? T[K][MK] : never;
}[keyof T];
export type PrimitiveOf<T> = T extends string ? string : T extends number ? number : T extends boolean ? boolean : T extends bigint ? bigint : T extends symbol ? symbol : T extends undefined ? undefined : T extends null ? null : never;
/**
* - **EN:** Convert an array of objects to a Map-like object, where the key is the `key` field of the
* object, and the value is the `value` field of the object
* - **CN:** 将对象数组转换为类似Map的对象,其中key为对象的`key`字段,value为对象的`value`字段
*
* @template A Array type | 数组类型
*/
export type ArrayToMap<A extends Record<string, any>[] | readonly Record<string, any>[]> = {
[K in A[number]['key']]: Extract<A[number], {
key?: K;
}>;
};
export type ExactEqual<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false;
export type IsNever<T> = [T] extends [never] ? true : false;