Skip to content

Commit 6cf84e6

Browse files
committed
chore: enhance type definitions in Enum methods
1 parent 2fd6796 commit 6cf84e6

File tree

8 files changed

+204
-97
lines changed

8 files changed

+204
-97
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+
## 2.3.4
6+
7+
2025-7-2
8+
9+
### Features
10+
11+
- ✨ Enhance the type definitions for methods like `Enum.label`, `Enum.key`, and `Enum.raw` to ensure return types more accurately correspond to input values. When an input value can be matched within the enum, the return type will no longer include `undefined`.
12+
513
## 2.3.3
614

715
2025-6-19

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<!-- markdownlint-disable MD001 MD009 MD033 MD041 -->
22

3-
[English](./README.md) | [中文](./README.zh-CN.md)
3+
[English](./README.md) | [中文](./README.zh-CN.md) | [CHANGELOG](./CHANGELOG.md)
44

55
<p align="center">
66
<a href="https://github.com/shijistar/enum-plus" target="blank">

README.zh-CN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<!-- markdownlint-disable MD001 MD009 MD033 MD041 -->
22

3-
[English](./README.md) | [中文](./README.zh-CN.md)
3+
[English](./README.md) | [中文](./README.zh-CN.md) | [CHANGELOG](./CHANGELOG.md)
44

55
<p align="center">
66
<a href="https://github.com/shijistar/enum-plus" target="blank">

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": "2.3.3",
3+
"version": "2.3.4",
44
"description": "A drop-in replacement for native enum. Like native enum but much better!",
55
"keywords": [
66
"enum",

src/enum-collection.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type {
1414
IEnumItems,
1515
MenuItemOption,
1616
ObjectFirstOptionConfig,
17+
PrimitiveOf,
1718
StandardEnumItemInit,
1819
ToSelectConfig,
1920
ValueTypeFromSingleInit,
@@ -118,12 +119,26 @@ export class EnumCollectionClass<
118119
Object.freeze(this.keys);
119120
}
120121

121-
key(value?: string | V) {
122+
label<KV extends V | K | NonNullable<PrimitiveOf<V>> | NonNullable<PrimitiveOf<K>> | undefined>(keyOrValue: KV) {
123+
return this.items.label(keyOrValue);
124+
}
125+
126+
key<IV extends V | NonNullable<PrimitiveOf<V>> | undefined>(value?: IV) {
122127
return this.items.key(value);
123128
}
124-
label(keyOrValue?: string | V): string | undefined {
125-
return this.items.label(keyOrValue);
129+
130+
raw(): T;
131+
raw<IK extends V | K | Exclude<EnumValue, string> | NonNullable<string>>(
132+
keyOrValue: IK
133+
): IK extends K ? T[IK] : IK extends V ? T[FindEnumKeyByValue<T, IK>] : T[K] | undefined;
134+
raw<IK extends EnumValue>(value?: IK | unknown): T | T[K] | T[FindEnumKeyByValue<T, IK>] | undefined {
135+
if (value != null) {
136+
return this.items.raw(value as keyof T | EnumValue) as T[K];
137+
} else {
138+
return this.items.raw();
139+
}
126140
}
141+
127142
has(keyOrValue?: string | V) {
128143
return this.items.has(keyOrValue);
129144
}
@@ -180,19 +195,6 @@ export class EnumCollectionClass<
180195
return this.items.valuesEnum();
181196
}
182197

183-
raw(): T;
184-
// eslint-disable-next-line @typescript-eslint/ban-types
185-
raw<IK extends V | K | Exclude<EnumValue, string> | (string & {})>(
186-
keyOrValue: IK
187-
): IK extends K ? T[IK] : IK extends V ? T[FindEnumKeyByValue<T, IK>] : T[K] | undefined;
188-
raw<IK extends EnumValue>(value?: IK | unknown): T | T[K] | T[FindEnumKeyByValue<T, IK>] | undefined {
189-
if (value != null) {
190-
return this.items.raw(value as keyof T | EnumValue) as T[K];
191-
} else {
192-
return this.items.raw();
193-
}
194-
}
195-
196198
get valueType() {
197199
return this.items.valueType;
198200
}

src/enum-values.ts

Lines changed: 60 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ import type {
1010
EnumKey,
1111
EnumValue,
1212
FindEnumKeyByValue,
13+
FindLabelByValue,
1314
IEnumItems,
1415
MenuItemOption,
1516
ObjectFirstOptionConfig,
17+
PrimitiveOf,
1618
ToSelectConfig,
1719
ValueMap,
1820
ValueTypeFromSingleInit,
@@ -70,13 +72,66 @@ export class EnumItemsArray<
7072
*/
7173
readonly [ENUM_ITEMS] = true;
7274

73-
label(keyOrValue?: string | V): string | undefined {
74-
// First find by value, then find by key
75-
return (this.find((i) => i.value === keyOrValue) ?? this.find((i) => i.key === keyOrValue))?.label;
75+
label<KV extends V | K | NonNullable<PrimitiveOf<V>> | NonNullable<PrimitiveOf<K>> | undefined>(
76+
keyOrValue: KV
77+
):
78+
| (undefined extends KV ? undefined : never)
79+
| (KV extends undefined
80+
? undefined
81+
: NonNullable<KV> extends K
82+
? T[NonNullable<KV>] extends { label: unknown }
83+
? T[NonNullable<KV>]['label'] extends undefined
84+
? NonNullable<KV>
85+
: string
86+
: NonNullable<KV>
87+
: NonNullable<KV> extends V
88+
? FindLabelByValue<T, NonNullable<KV>>
89+
: PrimitiveOf<K> extends KV
90+
? string | undefined
91+
: PrimitiveOf<V> extends KV
92+
? string | undefined
93+
: undefined) {
94+
// Find by value, then try key
95+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
96+
return (this.find((i) => i.value === keyOrValue) ?? this.find((i) => i.key === keyOrValue))?.label as any;
7697
}
7798

78-
key(value?: string | V): K | undefined {
79-
return this.find((i) => i.value === value)?.key;
99+
key<IV extends V | NonNullable<PrimitiveOf<V>> | undefined>(
100+
value?: IV
101+
):
102+
| (undefined extends IV ? undefined : never)
103+
| (IV extends undefined
104+
? undefined
105+
: NonNullable<IV> extends V
106+
? FindEnumKeyByValue<T, NonNullable<IV>>
107+
: PrimitiveOf<V> extends NonNullable<IV>
108+
? K | undefined
109+
: undefined) {
110+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
111+
return this.find((i) => i.value === value)?.key as any;
112+
}
113+
114+
raw(): T;
115+
raw<IK extends V | K | Exclude<EnumValue, string> | NonNullable<string>>(
116+
keyOrValue: IK
117+
): IK extends K ? T[IK] : IK extends V ? T[FindEnumKeyByValue<T, IK>] : T[K] | undefined;
118+
raw<IK extends EnumValue>(value?: IK | unknown): T | T[K] | T[FindEnumKeyByValue<T, IK>] | undefined {
119+
if (value == null) {
120+
// Return the original initialization object
121+
return this.#raw;
122+
} else {
123+
if (Object.keys(this.#raw).some((k) => k === (value as string))) {
124+
// Find by key
125+
return this.#raw[value as K];
126+
}
127+
// Find by value
128+
const itemByValue = this.find((i) => i.value === value);
129+
if (itemByValue) {
130+
return itemByValue.raw;
131+
} else {
132+
return undefined;
133+
}
134+
}
80135
}
81136

82137
has(keyOrValue?: string | V): boolean {
@@ -162,30 +217,6 @@ export class EnumItemsArray<
162217
return this.toFilter();
163218
}
164219

165-
raw(): T;
166-
// eslint-disable-next-line @typescript-eslint/ban-types
167-
raw<IK extends V | K | Exclude<EnumValue, string> | (string & {})>(
168-
keyOrValue: IK
169-
): IK extends K ? T[IK] : IK extends V ? T[FindEnumKeyByValue<T, IK>] : T[K] | undefined;
170-
raw<IK extends EnumValue>(value?: IK | unknown): T | T[K] | T[FindEnumKeyByValue<T, IK>] | undefined {
171-
if (value == null) {
172-
// Return the original initialization object
173-
return this.#raw;
174-
} else {
175-
if (Object.keys(this.#raw).some((k) => k === (value as string))) {
176-
// Find by key
177-
return this.#raw[value as K];
178-
}
179-
// Find by value
180-
const itemByValue = this.find((i) => i.value === value);
181-
if (itemByValue) {
182-
return itemByValue.raw;
183-
} else {
184-
return undefined;
185-
}
186-
}
187-
}
188-
189220
/** @deprecated Stub method, only for typing usages, not for runtime calling */
190221
get valueType(): V {
191222
throw new Error(

0 commit comments

Comments
 (0)