Skip to content

@utilslib/core/createEnumWithDescription


创建一个带有描述信息的双向映射枚举对象。

此函数扩展了基本的枚举功能,为每个枚举值添加描述信息,并提供获取描述的方法。

createEnumWithDescription

函数签名

typescript
function createEnumWithDescription<T extends {
    [key: string]: {
      value: string | number;
      description: string;
    };
  }>(enumObj: T): Readonly<
  { [K in keyof T]: T[K]["value"] } & {
    [K in T[keyof T]["value"]]: keyof T;
  } & {
    getDesc(key: keyof T): string;
  }
>

描述

创建一个带有描述信息的双向映射枚举对象。 此函数扩展了基本的枚举功能,为每个枚举值添加描述信息,并提供获取描述的方法。

类型参数

参数名约束默认值描述
T\{ \[key: string\]: \{ value: string | number; description: string; \}; \}--

参数

参数名类型可选默认值描述
enumObjT--

返回值

Readonly< { [K in keyof T]: T[K]["value"] } & { [K in T[keyof T]["value"]]: keyof T; } & { getDesc(key: keyof T): string; } >

点击查看源码
js
/**
 * 创建一个具有双向映射的枚举对象。
 *
 * @param {Object} enumObj - 原始枚举对象,包含键值对
 * @returns {Object} 返回具有双向映射且冻结的枚举对象
 *
 * @throws {TypeError} 当枚举值类型不是 string 或 number 时抛出错误
 */
function createEnum(enumObj) {
  const result = Object.create({});
  for (const key in enumObj) {
    if (!Object.prototype.hasOwnProperty.call(enumObj, key)) continue;
    const value = enumObj[key];
    if (typeof value !== "string" && typeof value !== "number") {
      throw new TypeError(
        `Enum value must be string or number, got ${typeof value}`,
      );
    }
    result[key] = value;
    Object.defineProperty(Object.getPrototypeOf(result), value, {
      value: key,
      enumerable: false,
      writable: false,
      configurable: false,
    });
  }
  return Object.freeze(result);
}
/**
 * 创建一个带有描述信息的双向映射枚举对象。
 * 此函数扩展了基本的枚举功能,为每个枚举值添加描述信息,并提供获取描述的方法。
 *
 * @param {Object} enumObj - 包含枚举定义的对象,每个属性都应该是一个包含 value 和 description 的对象
 * @returns {Readonly<Object>} 返回一个只读的枚举对象,包含:
 *   - 正向映射(键到值)
 *   - 反向映射(值到键)
 *   - getDesc 方法用于获取描述信息
 */
export function createEnumWithDescription(enumObj) {
  const [simpleEnum, descriptions] = Object.entries(enumObj).reduce(
    ([values, descMap], [key, { value, description }]) => {
      return [
        ((values[key] = value), values),
        descMap.set(key, description).set(String(value), description),
      ];
    },
    [{}, new Map()],
  );
  const result = createEnum(simpleEnum);
  Object.defineProperty(Object.getPrototypeOf(result), "desc", {
    value: new Proxy(descriptions, {
      get(target, prop) {
        return target.get(prop);
      },
    }),
    enumerable: false,
    writable: false,
    configurable: false,
  });
  return Object.freeze(result);
}
ts
/**
 * 创建一个具有双向映射的枚举对象。
 *
 * @param {Object} enumObj - 原始枚举对象,包含键值对
 * @returns {Object} 返回具有双向映射且冻结的枚举对象
 *
 * @throws {TypeError} 当枚举值类型不是 string 或 number 时抛出错误
 */
function createEnum<T extends { [key: string]: string | number }>(
  enumObj: T,
): Readonly<T & { [K in T[keyof T]]: keyof T }> {
  const result = Object.create({}) as T & { [K in T[keyof T]]: keyof T };

  for (const key in enumObj) {
    if (!Object.prototype.hasOwnProperty.call(enumObj, key)) continue;
    const value = enumObj[key];
    if (typeof value !== "string" && typeof value !== "number") {
      throw new TypeError(
        `Enum value must be string or number, got ${typeof value}`,
      );
    }
    result[key] = value;
    Object.defineProperty(Object.getPrototypeOf(result), value, {
      value: key,
      enumerable: false,
      writable: false,
      configurable: false,
    });
  }

  return Object.freeze(result);
}

/**
 * 创建一个带有描述信息的双向映射枚举对象。
 * 此函数扩展了基本的枚举功能,为每个枚举值添加描述信息,并提供获取描述的方法。
 *
 * @param {Object} enumObj - 包含枚举定义的对象,每个属性都应该是一个包含 value 和 description 的对象
 * @returns {Readonly<Object>} 返回一个只读的枚举对象,包含:
 *   - 正向映射(键到值)
 *   - 反向映射(值到键)
 *   - getDesc 方法用于获取描述信息
 */
export function createEnumWithDescription<
  T extends {
    [key: string]: {
      value: string | number;
      description: string;
    };
  },
>(
  enumObj: T,
): Readonly<
  { [K in keyof T]: T[K]["value"] } & {
    [K in T[keyof T]["value"]]: keyof T;
  } & {
    getDesc(key: keyof T): string;
  }
> {
  const [simpleEnum, descriptions] = Object.entries(enumObj).reduce(
    ([values, descMap], [key, { value, description }]) => {
      return [
        ((values[key] = value), values),
        descMap.set(key, description).set(String(value), description),
      ];
    },
    [
      {} as { [key: string]: string | number },
      new Map<string | number, string>(),
    ],
  );

  const result = createEnum(simpleEnum) as any;
  Object.defineProperty(Object.getPrototypeOf(result), "desc", {
    value: new Proxy(descriptions, {
      get(target, prop: string) {
        return target.get(prop);
      },
    }),
    enumerable: false,
    writable: false,
    configurable: false,
  });

  return Object.freeze(result);
}

如有错误,请提交issue :::