TypeScript中如何获取函数接收的枚举的原名称
Great question! Grabbing the actual name of an enum (like "Animals" in your example) at runtime isn't straightforward because TypeScript compiles enums into plain JavaScript objects, and JS objects don't inherently track the variable/export name they're assigned to. But don't worry—there are a few practical approaches to solve this, depending on your project's environment.
Option 1: Use Module Exports (Node.js Only)
If you're working in a Node.js environment and your enum is exported from a module, you can iterate over the module's exports to find the key that maps to your enum object. This works because when you export enum Animals, the enum is stored as module.exports.Animals under the hood.
Here's how to implement it:
export enum Animals { Cow, Pig } export function someFancyFunctiontoPrintMyEnumName(Enum: any): string | null { // Loop through all exports in the current module for (const key in module.exports) { // Skip our utility functions to avoid false matches if (key === "someFancyFunctiontoPrintMyEnumName" || key === "printEnumName") { continue; } if (module.exports[key] === Enum) { return key; } } return null; } export function printEnumName(Enum: any) { console.log(someFancyFunctiontoPrintMyEnumName(Enum)); // Logs "Animals" } // Test it out printEnumName(Animals);
Notes:
- This only works in Node.js—browser environments don't have
module.exports. - If you export the same enum under multiple names, this will return the first matching key it finds.
Option 2: Manually Add a Name Property (Cross-Environment)
If you need a solution that works everywhere (Node.js and browsers), the simplest reliable approach is to manually add a static property to your enum to store its name. It's a tiny bit of extra work, but it's straightforward and avoids environment dependencies.
Example:
export enum Animals { Cow, Pig } // Attach the enum name as a static property (Animals as any).enumName = "Animals"; export function someFancyFunctiontoPrintMyEnumName(Enum: any): string | null { return Enum.enumName ?? null; } export function printEnumName(Enum: any) { console.log(someFancyFunctiontoPrintMyEnumName(Enum)); // Logs "Animals" }
Pros:
- Works in all JavaScript environments.
- Easy to understand and maintain.
Option 3: Compile-Time Injection (For Scaled Projects)
If you're working on a larger project and don't want to manually add the name property to every enum, you can use a TypeScript custom transformer to automatically inject the enum name during compilation. This requires setting up a custom TypeScript build pipeline (usually with ttypescript instead of the official tsc), but it's fully automated once configured.
The transformer would scan your TypeScript AST for enum declarations and add a line like (Enum as any).enumName = "EnumName"; right after each enum is defined. This way, you never have to touch the enum code itself.
Why Can't We Just Get the Name Directly?
To clarify why this isn't "out of the box" functionality: when TypeScript compiles your enum, it turns it into a regular JS object (a bidirectional map for numeric enums, a one-way map for string enums). JavaScript objects don't keep track of what variable name they're assigned to—variable names are just references pointing to the object. There's no built-in way to reverse-engineer that reference name from the object itself at runtime.
内容的提问来源于stack exchange,提问作者IBot

