Skip to content

Commit 79ee248

Browse files
committed
feat: expand the AnyEnum type to be compatible with all enumeration types
1 parent f837c8d commit 79ee248

File tree

4 files changed

+78
-26
lines changed

4 files changed

+78
-26
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
# enum-plus Changelog
44

5+
## 3.1.6
6+
7+
2025-11-26
8+
9+
### Features
10+
11+
- ✨ Expand the AnyEnum type to be compatible with all enumeration types.
12+
513
## 3.1.5
614

715
2025-11-20

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "enum-plus",
3-
"version": "3.1.5",
3+
"version": "3.1.6",
44
"description": "A drop-in replacement for native enum. Like native enum but much better!",
55
"keywords": [
66
"enum",

src/enum.ts

Lines changed: 67 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type {
99
EnumItemLabel,
1010
EnumKey,
1111
EnumValue,
12+
IsAny,
1213
LocalizeInterface,
1314
ValueTypeFromSingleInit,
1415
} from './types';
@@ -277,7 +278,8 @@ export interface EnumInterface {
277278
* - **EN:** A generic enum type that can be used to represent any enum collection
278279
* - **CN:** 一个通用枚举类型,可以用来表示任何枚举集合
279280
*/
280-
export type AnyEnum = IEnum<EnumInit<string, EnumValue>> & NativeEnumMembers<EnumInit<string, EnumValue>>;
281+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
282+
export type AnyEnum = IEnum<any>;
281283
// @ts-expect-error: because T does not satisfy EnumInit<K, V>
282284
// eslint-disable-next-line @typescript-eslint/no-explicit-any
283285
export type GenericAnyEnum<T extends EnumInit<keyof any, EnumValue>> = IEnum<T> &
@@ -311,7 +313,13 @@ export interface IEnum<
311313
* all enum items through this alias
312314
* - **CN:** `items`数组的别名,当任何枚举的key与`items`冲突时,可以通过此别名访问所有枚举项
313315
*/
314-
readonly [ITEMS]: T extends { items: unknown } ? EnumItemClass<T[K], K, V, P>[] & IEnumItems<T, K, V, P> : never;
316+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
317+
readonly [ITEMS]: IsAny<T> extends true
318+
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
319+
EnumItemClass<any, string, EnumValue, P>[]
320+
: T extends { items: unknown }
321+
? EnumItemClass<T[K], K, V, P>[] & IEnumItems<T, K, V, P>
322+
: never;
315323
/**
316324
* - **EN:** All items in the enumeration as an array
317325
*
@@ -322,15 +330,20 @@ export interface IEnum<
322330
*
323331
* > 仅支持 `ReadonlyArray<T>` 中的只读方法,不支持push、pop等任何修改的方法
324332
*/
325-
readonly items: T extends { items: unknown }
326-
? ValueTypeFromSingleInit<T['items'], 'items', T[K] extends number | undefined ? number : 'items'>
327-
: EnumItemClass<T[K], K, V, P>[] & IEnumItems<T, K, V, P>;
333+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
334+
readonly items: IsAny<T> extends true
335+
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
336+
EnumItemClass<any, string, EnumValue, P>[] & IEnumItems<any, string, EnumValue, P>
337+
: T extends { items: unknown }
338+
? ValueTypeFromSingleInit<T['items'], 'items', T[K] extends number | undefined ? number : 'items'>
339+
: EnumItemClass<T[K], K, V, P>[] & IEnumItems<T, K, V, P>;
328340
/**
329341
* - **EN:** Alias for the `keys` array, when any enum key conflicts with `keys`, you can access all
330342
* enum keys through this alias
331343
* - **CN:** `keys`数组的别名,当任何枚举的key与`keys`冲突时,可以通过此别名访问所有枚举项的keys
332344
*/
333-
readonly [KEYS]: T extends { keys: unknown } ? K[] : never;
345+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
346+
readonly [KEYS]: IsAny<T> extends true ? string[] : T extends { keys: unknown } ? K[] : never;
334347
/**
335348
* - **EN:** Get all keys of the enumeration items as an array
336349
*
@@ -341,15 +354,19 @@ export interface IEnum<
341354
*
342355
* > 仅支持 `ReadonlyArray<T>` 中的只读方法,不支持push、pop等任何修改的方法
343356
*/
344-
readonly keys: T extends { keys: unknown }
345-
? ValueTypeFromSingleInit<T['keys'], 'keys', T[K] extends number | undefined ? number : 'keys'>
346-
: K[];
357+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
358+
readonly keys: IsAny<T> extends true
359+
? string[]
360+
: T extends { keys: unknown }
361+
? ValueTypeFromSingleInit<T['keys'], 'keys', T[K] extends number | undefined ? number : 'keys'>
362+
: K[];
347363
/**
348364
* - **EN:** Alias for the `values` array, when any enum key conflicts with `values`, you can access
349365
* all enum values through this alias
350366
* - **CN:** `values`数组的别名,当任何枚举的key与`values`冲突时,可以通过此别名访问所有枚举项的values
351367
*/
352-
readonly [VALUES]: T extends { values: unknown } ? V[] : never;
368+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
369+
readonly [VALUES]: IsAny<T> extends true ? EnumValue[] : T extends { values: unknown } ? V[] : never;
353370
/**
354371
* - **EN:** Get all values of the enumeration items as an array
355372
*
@@ -360,15 +377,19 @@ export interface IEnum<
360377
*
361378
* > 仅支持 `ReadonlyArray<T>` 中的只读方法,不支持push、pop等任何修改的方法
362379
*/
363-
readonly values: T extends { values: unknown }
364-
? ValueTypeFromSingleInit<T['values'], 'values', T[K] extends number | undefined ? number : 'values'>
365-
: V[];
380+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
381+
readonly values: IsAny<T> extends true
382+
? EnumValue[]
383+
: T extends { values: unknown }
384+
? ValueTypeFromSingleInit<T['values'], 'values', T[K] extends number | undefined ? number : 'values'>
385+
: V[];
366386
/**
367387
* - **EN:** Alias for the `labels` array, when any enum key conflicts with `labels`, you can access
368388
* all enum labels through this alias
369389
* - **CN:** `labels`数组的别名,当任何枚举的key与`labels`冲突时,可以通过此别名访问所有枚举项的labels
370390
*/
371-
readonly [LABELS]: T extends { labels: unknown } ? string[] : never;
391+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
392+
readonly [LABELS]: IsAny<T> extends true ? string[] : T extends { labels: unknown } ? string[] : never;
372393
/**
373394
* - **EN:** Get all labels of the enumeration items as an array
374395
*
@@ -379,30 +400,48 @@ export interface IEnum<
379400
*
380401
* > 仅支持 `ReadonlyArray<T>` 中的只读方法,不支持push、pop等任何修改的方法
381402
*/
382-
readonly labels: T extends { labels: unknown }
383-
? ValueTypeFromSingleInit<T['labels'], 'labels', T[K] extends number | undefined ? number : 'labels'>
384-
: string[];
403+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
404+
readonly labels: IsAny<T> extends true
405+
? string[]
406+
: T extends { labels: unknown }
407+
? ValueTypeFromSingleInit<T['labels'], 'labels', T[K] extends number | undefined ? number : 'labels'>
408+
: string[];
385409
/**
386410
* - **EN:** Alias for the `named` array, when any enum key conflicts with `named`, you can access
387411
* all enum names through this alias
388412
* - **CN:** `named`数组的别名,当任何枚举的key与`named`冲突时,可以通过此别名访问所有枚举项的names
389413
*/
390-
readonly [NAMED]: T extends { named: unknown } ? IEnumItems<T, K, V, P>['named'] : never;
414+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
415+
readonly [NAMED]: IsAny<T> extends true
416+
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
417+
Record<string, EnumItemClass<any, string, EnumValue, P>>
418+
: T extends { named: unknown }
419+
? IEnumItems<T, K, V, P>['named']
420+
: never;
391421
/**
392422
* - **EN:** Get all names of the enumeration items as an array
393423
*
394424
* > Only supports read-only methods in `ReadonlyArray<T>`, does not support push, pop, and any
395425
* > modification methods
396426
*/
397-
readonly named: T extends { named: unknown }
398-
? ValueTypeFromSingleInit<T['named'], 'named', T[K] extends number | undefined ? number : 'named'>
399-
: IEnumItems<T, K, V, P>['named'];
427+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
428+
readonly named: IsAny<T> extends true
429+
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
430+
Record<string, EnumItemClass<any, string, EnumValue, P>>
431+
: T extends { named: unknown }
432+
? ValueTypeFromSingleInit<T['named'], 'named', T[K] extends number | undefined ? number : 'named'>
433+
: IEnumItems<T, K, V, P>['named'];
400434
/**
401435
* - **EN:** Alias for the `meta` array, when any enum key conflicts with `meta`, you can access all
402436
* enum meta information through this alias
403437
* - **CN:** `meta`数组的别名,当任何枚举的key与`meta`冲突时,可以通过此别名访问所有枚举项的meta信息
404438
*/
405-
readonly [META]: T extends { meta: unknown } ? IEnumItems<T, K, V, P>['meta'] : never;
439+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
440+
readonly [META]: IsAny<T> extends true
441+
? Record<string, unknown[]>
442+
: T extends { meta: unknown }
443+
? IEnumItems<T, K, V, P>['meta']
444+
: never;
406445
/**
407446
* - **EN:** Get all meta information of the enumeration items as an array
408447
*
@@ -413,9 +452,12 @@ export interface IEnum<
413452
*
414453
* > 仅支持 `ReadonlyArray<T>` 中的只读方法,不支持push、pop等任何修改的方法
415454
*/
416-
readonly meta: T extends { meta: unknown }
417-
? ValueTypeFromSingleInit<T['meta'], 'meta', T[K] extends number | undefined ? number : 'meta'>
418-
: IEnumItems<T, K, V, P>['meta'];
455+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
456+
readonly meta: IsAny<T> extends true
457+
? Record<string, unknown[]>
458+
: T extends { meta: unknown }
459+
? ValueTypeFromSingleInit<T['meta'], 'meta', T[K] extends number | undefined ? number : 'meta'>
460+
: IEnumItems<T, K, V, P>['meta'];
419461
}
420462

421463
export type NativeEnumMembers<

src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,3 +235,5 @@ export type ArrayToMap<A extends Record<string, any>[] | readonly Record<string,
235235
export type ExactEqual<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false;
236236

237237
export type IsNever<T> = [T] extends [never] ? true : false;
238+
239+
export type IsAny<T> = 0 extends 1 & T ? true : false;

0 commit comments

Comments
 (0)