ts-enum-next 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -98,7 +98,7 @@ console.log(statusMessages.get(HttpStatus.NOT_FOUND)); // "The resource does not
98
98
  - Generate options for Ant Design `Select`
99
99
 
100
100
  ```ts
101
- import { Enum, enumOptions } from "ts-enum-next";
101
+ import { Enum } from "ts-enum-next";
102
102
 
103
103
  class HttpStatus extends Enum<number> {
104
104
  static readonly OK = new HttpStatus(200, "OK", "Request succeeded");
@@ -110,12 +110,12 @@ class HttpStatus extends Enum<number> {
110
110
  static readonly NOT_FOUND = new HttpStatus(404, "NOT_FOUND");
111
111
  }
112
112
 
113
- const options = enumOptions(HttpStatus);
113
+ const options = HttpStatus.enumOptions();
114
114
  // options:
115
115
  // [
116
- // { label: "OK", value: 200 },
117
- // { label: "BAD_REQUEST", value: 400 },
118
- // { label: "NOT_FOUND", value: 404 }
116
+ // { label: "OK", value: 200, name: "OK", description: "Request succeeded" },
117
+ // { label: "BAD_REQUEST", value: 400, name: "BAD_REQUEST", description: "Error request" },
118
+ // { label: "NOT_FOUND", value: 404, name: "NOT_FOUND" }
119
119
  // ]
120
120
  ```
121
121
 
package/README.zh-CN.md CHANGED
@@ -163,7 +163,7 @@ console.log(statusMessages.get(HttpStatus.NOT_FOUND)); // “请求的资源不
163
163
  ### 场景 7:为 Ant Design `Select` 生成枚举下拉项
164
164
 
165
165
  ```ts
166
- import { Enum, enumOptions } from "ts-enum-next";
166
+ import { Enum } from "ts-enum-next";
167
167
 
168
168
  class HttpStatus extends Enum<number> {
169
169
  static readonly OK = new HttpStatus(200, "OK", "请求成功");
@@ -171,12 +171,12 @@ class HttpStatus extends Enum<number> {
171
171
  static readonly NOT_FOUND = new HttpStatus(404, "NOT_FOUND", "资源未找到");
172
172
  }
173
173
 
174
- const options = enumOptions(HttpStatus);
174
+ const options = HttpStatus.enumOptions();
175
175
  // options:
176
176
  // [
177
- // { label: "OK", value: 200 },
178
- // { label: "BAD_REQUEST", value: 400 },
179
- // { label: "NOT_FOUND", value: 404 }
177
+ // { label: "OK", value: 200, name: "OK", description: "请求成功" },
178
+ // { label: "BAD_REQUEST", value: 400, name: "BAD_REQUEST", description: "错误请求" },
179
+ // { label: "NOT_FOUND", value: 404, name: "NOT_FOUND", description: "资源未找到" }
180
180
  // ]
181
181
  ```
182
182
 
package/dist/index.d.ts CHANGED
@@ -15,10 +15,14 @@ declare abstract class Enum<T extends string | number = string | number> {
15
15
  */
16
16
  description?: unknown | undefined);
17
17
  static values<T extends Enum>(this: new (...args: any[]) => T): T[];
18
- static fromValue<T extends Enum>(this: new (...args: any[]) => T, value: T['value']): T;
19
- static fromName<T extends Enum>(this: new (...args: any[]) => T, name: string): T;
18
+ static fromValue<T extends Enum>(this: new (...args: any[]) => T, value: T['value']): T | undefined;
19
+ static fromName<T extends Enum>(this: new (...args: any[]) => T, name: string): T | undefined;
20
20
  static setOf<T extends Enum>(this: new (...args: any[]) => T, ...items: T[]): Set<T>;
21
21
  static enumMap<V, T extends Enum = Enum>(this: new (...args: any[]) => T, map: Record<string | number, V>): Map<T, V>;
22
+ static enumOptions<T extends Enum>(this: new (...args: any[]) => T): Array<T & {
23
+ label: string;
24
+ value: T['value'];
25
+ }>;
22
26
  toString(): string;
23
27
  valueOf(): string;
24
28
  }
package/dist/index.js CHANGED
@@ -25,19 +25,21 @@ class Enum {
25
25
  }
26
26
  // 通过值获取枚举实例
27
27
  static fromValue(value) {
28
- const enumInstance = Enum._valueMap.get(this)?.get(value);
29
- if (!enumInstance) {
30
- throw new Error(`No enum value ${value} found`);
31
- }
32
- return enumInstance;
28
+ if (value === undefined || value === null)
29
+ return undefined;
30
+ const valueMap = Enum._valueMap.get(this);
31
+ if (!valueMap)
32
+ return undefined;
33
+ return valueMap.get(value);
33
34
  }
34
35
  // 通过名称获取枚举实例
35
36
  static fromName(name) {
36
- const enumInstance = Enum._nameMap.get(this)?.get(name);
37
- if (!enumInstance) {
38
- throw new Error(`No enum name ${name} found`);
39
- }
40
- return enumInstance;
37
+ if (name === undefined || name === null || name === '')
38
+ return undefined;
39
+ const nameMap = Enum._nameMap.get(this);
40
+ if (!nameMap)
41
+ return undefined;
42
+ return nameMap.get(name);
41
43
  }
42
44
  // 创建枚举集合
43
45
  static setOf(...items) {
@@ -65,6 +67,15 @@ class Enum {
65
67
  }
66
68
  return result;
67
69
  }
70
+ // 获取枚举选项数组,用于 Ant Design Select 组件
71
+ static enumOptions() {
72
+ const values = this.values();
73
+ return values.map((i) => ({
74
+ ...i,
75
+ label: i.name,
76
+ value: i.value,
77
+ }));
78
+ }
68
79
  // 重写toString方法
69
80
  toString() {
70
81
  return this.name;
@@ -88,11 +88,15 @@ describe('Enum', () => {
88
88
  expect(HttpStatus.fromValue(404)).toBe(HttpStatus.NOT_FOUND);
89
89
  expect(HttpStatus.fromValue(500)).toBe(HttpStatus.SERVER_ERROR);
90
90
  });
91
- it('should throw error for non-existent numeric value', () => {
92
- expect(() => HttpStatus.fromValue(999)).toThrow('No enum value 999 found');
91
+ it('should return undefined for non-existent numeric value', () => {
92
+ expect(HttpStatus.fromValue(999)).toBeUndefined();
93
93
  });
94
- it('should throw error for non-existent string value', () => {
95
- expect(() => OrderStatus.fromValue('INVALID')).toThrow('No enum value INVALID found');
94
+ it('should return undefined for non-existent string value', () => {
95
+ expect(OrderStatus.fromValue('INVALID')).toBeUndefined();
96
+ });
97
+ it('should return undefined when value is null or undefined', () => {
98
+ expect(HttpStatus.fromValue(undefined)).toBeUndefined();
99
+ expect(HttpStatus.fromValue(null)).toBeUndefined();
96
100
  });
97
101
  });
98
102
  describe('fromName()', () => {
@@ -111,11 +115,16 @@ describe('Enum', () => {
111
115
  expect(HttpStatus.fromName('NOT_FOUND')).toBe(HttpStatus.NOT_FOUND);
112
116
  expect(HttpStatus.fromName('SERVER_ERROR')).toBe(HttpStatus.SERVER_ERROR);
113
117
  });
114
- it('should throw error for non-existent name', () => {
115
- expect(() => HttpStatus.fromName('INVALID')).toThrow('No enum name INVALID found');
118
+ it('should return undefined for non-existent name', () => {
119
+ expect(HttpStatus.fromName('INVALID')).toBeUndefined();
116
120
  });
117
121
  it('should be case-sensitive', () => {
118
- expect(() => HttpStatus.fromName('ok')).toThrow('No enum name ok found');
122
+ expect(HttpStatus.fromName('ok')).toBeUndefined();
123
+ });
124
+ it('should return undefined when name is null, undefined or empty string', () => {
125
+ expect(HttpStatus.fromName(undefined)).toBeUndefined();
126
+ expect(HttpStatus.fromName(null)).toBeUndefined();
127
+ expect(HttpStatus.fromName('')).toBeUndefined();
119
128
  });
120
129
  });
121
130
  describe('setOf()', () => {
@@ -208,6 +217,50 @@ describe('Enum', () => {
208
217
  expect(statusConfig.get(HttpStatus.NOT_FOUND)).toEqual({ color: 'red', icon: 'error' });
209
218
  });
210
219
  });
220
+ describe('enumOptions()', () => {
221
+ it('should return options array for numeric enum', () => {
222
+ const options = HttpStatus.enumOptions();
223
+ expect(options).toHaveLength(5);
224
+ expect(options[0]).toEqual({
225
+ value: 200,
226
+ name: 'OK',
227
+ description: 'Request succeeded',
228
+ label: 'OK'
229
+ });
230
+ });
231
+ it('should return options array for string enum', () => {
232
+ const options = OrderStatus.enumOptions();
233
+ expect(options).toHaveLength(4);
234
+ expect(options[0]).toEqual({
235
+ value: 'PENDING',
236
+ name: 'Pending',
237
+ description: 'Order is pending',
238
+ label: 'Pending'
239
+ });
240
+ });
241
+ it('should return options array for enum without description', () => {
242
+ const options = Priority.enumOptions();
243
+ expect(options).toHaveLength(3);
244
+ expect(options[0]).toEqual({
245
+ value: 1,
246
+ name: 'LOW',
247
+ description: undefined,
248
+ label: 'LOW'
249
+ });
250
+ });
251
+ it('should have correct label and value for each option', () => {
252
+ const options = HttpStatus.enumOptions();
253
+ const okOption = options.find(opt => opt.value === 200);
254
+ expect(okOption.label).toBe('OK');
255
+ expect(okOption.value).toBe(200);
256
+ });
257
+ it('should preserve all enum properties in options', () => {
258
+ const options = HttpStatus.enumOptions();
259
+ const notFoundOption = options.find(opt => opt.value === 404);
260
+ expect(notFoundOption.name).toBe('NOT_FOUND');
261
+ expect(notFoundOption.description).toBe('Resource not found');
262
+ });
263
+ });
211
264
  describe('toString()', () => {
212
265
  it('should return the name', () => {
213
266
  expect(HttpStatus.OK.toString()).toBe('OK');
@@ -240,12 +293,12 @@ describe('Enum', () => {
240
293
  });
241
294
  it('should not interfere with each other when querying by value', () => {
242
295
  // 虽然值相同,但是不同的枚举类
243
- expect(() => HttpStatus.fromValue('PENDING')).toThrow();
244
- expect(() => OrderStatus.fromValue(200)).toThrow();
296
+ expect(HttpStatus.fromValue('PENDING')).toBeUndefined();
297
+ expect(OrderStatus.fromValue(200)).toBeUndefined();
245
298
  });
246
299
  it('should not interfere with each other when querying by name', () => {
247
- expect(() => HttpStatus.fromName('Pending')).toThrow();
248
- expect(() => OrderStatus.fromName('OK')).toThrow();
300
+ expect(HttpStatus.fromName('Pending')).toBeUndefined();
301
+ expect(OrderStatus.fromName('OK')).toBeUndefined();
249
302
  });
250
303
  });
251
304
  describe('Edge cases', () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-enum-next",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Ultimate Enum Enhancement for TypeScript",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",