enum-plus

repository·main·Indexed 41 days ago

https://github.com/shijistar/enum-plus

A business dictionary management solution and drop-in replacement for native TypeScript enums (version 3.3.0). It enhances enums with runtime capabilities including human-readable labels, metadata, and internationalization. It provides a plugin ecosystem for integration with Ant Design, React, Vue, and i18next to enable UI component generation and automatic translation updates.

Tokens
49.5K
Snippets
186
Records
233
Agent score
52%

What's inside enum-plus

  1. Overview of enum-plus features

    main

    enum-plus is an enhanced enumeration library designed for business dictionary management. It acts as a drop-in replacement for native TypeScript/JavaScript enums while adding several capabilities:

    • Enhanced Metadata: Supports display names (labels) and custom metadata fields for each enum item.
    • Internationalization (i18n): Supports translating display names, compatible with any i18n library.
    • UI Integration: Can generate UI components like dropdowns and menus, compatible with libraries like Ant Design, Element Plus, and Material-UI.
    • Type Safety: Supports type narrowing in TypeScript for better developer experience.
    • Data Transformation: Easily convert enum values directly into their localized display names for UI rendering.
    • Extensibility: Features a plugin system and an extensible design for custom metadata.
    • Environment Support: Works with SSR, React Native, Taro, mini-programs, and vanilla JS.
  2. Important constraints for Enum initialization

    main
    When initializing an enum, all items must follow a consistent data structure. You cannot mix different initialization formats (e.g., mixing Key-Value format and Standard format) within a single Enum call.
  3. How enum labels respond to language changes

    main

    You can define enums using next-international localization keys in the label field. The behavior of Enum.label() and Enum.name depends on the localize.mode setting.

    Text Mode (mode: 'text')

    In this mode, label() returns a static string based on the translation key at the time of call. It does not react to language changes.

    Component Mode (mode: 'component')

    In this mode, label() and Enum.name return React components. These components are reactive and will automatically re-render with the correct translated text when the language changes.

    Example Usage:

    const WeekEnum = Enum(
      {
        Monday: { value: 1, label: 'week.monday' },
        Tuesday: { value: 2, label: 'week.tuesday' },
      },
      { name: 'weekDays.name' }
    );
    
    // If mode is 'component':
    // WeekEnum.label(1) returns a React component that displays 'Monday' (or '星期一' after language change).
    // WeekEnum.name returns a React component that displays 'Week' (or '周' after language change).
    // Example with Ant Design Select in 'component' mode
    <Select options={WeekEnum.items} defaultValue={WeekEnum.Monday} />;
    // When language changes, the selected item text updates automatically.
  4. Understand the test structure for Jest and Playwright

    main

    To allow Jest (Node.js unit tests) and Playwright (Browser E2E tests) to share a common codebase, tests must be split into two distinct, serializable parts:

    1. evaluate: Contains the actual test logic execution. This code must be serializable and cannot depend on closures or external state.
    2. assert: Contains the assertions to verify the test results. This part must also be serializable.

    By separating logic into these two phases, the same test code can be executed in a Node.js environment via Jest and then transported to a browser environment via Playwright.

  5. Understand the EnumPlus testing structure

    main

    EnumPlus tests are designed to be compatible with both Jest (for Node.js unit testing) and Playwright (for browser-based E2E testing). To achieve this code sharing, every test must be split into two distinct, serializable parts:

    1. evaluate: Contains the core test logic. This code runs the actual operations being tested.
    2. assert: Contains the assertions used to verify the results produced by the evaluate step.

    Because these parts are executed in different environments (Node.js vs. Browser), they must not rely on local closures or external state that cannot be serialized and passed between the two stages.

  6. Handle naming conflicts with special symbols

    main

    In enum-plus, enum item names have higher priority than the enum instance's methods and properties. If an enum item shares a name with a built-in method (like keys, values, label, named, toList, or items), the item will overwrite the method.

    To access the original methods when they are shadowed, use the following special symbols imported from enum-plus:

    • KEYS: Access the list of keys via items[KEYS].
    • VALUES: Access the list of values via items[VALUES].
    • ITEMS: Access the items property via [ITEMS] if it has been shadowed by an enum item.

    Note: KEYS and VALUES are used as aliases specifically to avoid interfering with the built-in behavior of JavaScript arrays.

    import { KEYS, VALUES, ITEMS } from 'enum-plus';
    
    const WeekEnum = Enum({
      foo: { value: 1 },
      keys: { value: 3 }, // Shadowing the 'keys' method
      items: { value: 9 }, // Shadowing the 'items' property
    });
    
    // Access shadowed items
    WeekEnum.keys; // 3
    WeekEnum.items[KEYS]; // ['foo', 'keys', 'items']
    WeekEnum.items[VALUES]; // [1, 3, 9]
    WeekEnum[ITEMS].toList(); // Accessing the original items method
  7. Explore the enum-plus ecosystem

    main

    The enum-plus ecosystem includes various plugins to integrate with specific frameworks and libraries:

    • React Support: @enum-plus/plugin-react, @enum-plus/plugin-react-i18next
    • i18n Support:
      • @enum-plus/plugin-i18next (General i18next)
      • @enum-plus/plugin-i18next-vue (Vue i18n)
      • @enum-plus/plugin-next-international (Next.js internationalization)
    • UI Library Integration:
      • @enum-plus/plugin-antd (Ant Design)
    • Vue Support: @enum-plus/plugin-vue-i18n
  8. Use Type Narrowing with TypeScript

    main

    In TypeScript, you can use typeof WeekEnum.valueType to create a type that is constrained strictly to the valid values of your enum. This provides compile-time safety for variables, function parameters, and component props.

    type WeekValues = typeof WeekEnum.valueType; // e.g., 0 | 1 | 2 | ...
    
    const weekValue: WeekValues = 1; // ✅ Correct
    const badWeekValue: WeekValues = 8; // ❌ Error: 8 is not a valid enum value
    
    function setDay(day: typeof WeekEnum.valueType) {
      // day is narrowed to valid enum values
    }
  9. Decide whether to develop an official or third-party plugin

    main

    Before starting development, assess if your plugin should be maintained in the official enum-plus repository or as an independent third-party plugin.

    Your plugin is suitable for the official repository if it meets these three criteria:

    1. Openness: It targets a public framework or technology (not a private company/org technology).
    2. Generality: It is used by the majority of users of that technology.
    3. Relevance: It is closely related to the concept of enumeration.

    Third-party plugins should be published to npm independently. Once published, you can share your plugin link in the Awesome Plugins section of the main repository.