如何在TypeScript中实现类似C#的泛型枚举值获取方法?
I want to get all values of an enum type in TypeScript and convert them into an array. Here's the equivalent C# implementation:
public static TEnum[] GetValues<TEnum>() where TEnum : Enum { return Enum.GetValues(typeof(TEnum)) .OfType<TEnum>() .ToArray(); }
I hope the TypeScript method can be called like this:
const allCountries: Country[] = GetEnumValues<Country>();
Additional note: I'm currently using TypeScript 3.9.4 and can upgrade to a higher version.
Hey there! Let's tackle this problem—getting all enum values into an array in TypeScript, just like your C# implementation does.
First, a quick heads-up: TypeScript enums compile to JavaScript objects. For numeric enums, they even include reverse mappings (value → name) that we need to filter out. String enums don't have this quirk, so we can build a function that handles both cases smoothly.
Recommended Implementation (Type-Safe & Explicit)
The cleanest, safest approach is to pass the enum itself as an argument (this avoids messy runtime type lookups). Here's how it works:
function GetEnumValues<TEnum>(enumObj: Record<string, TEnum>): TEnum[] { // Filter out reverse mapping strings for numeric enums return Object.values(enumObj).filter(value => { return typeof value !== 'string' || isNaN(Number(value)); }) as TEnum[]; } // Example usage with a string enum enum Country { USA = 'USA', Canada = 'CANADA', Mexico = 'MEXICO' } // This gives you a properly typed array of Country enum values const allCountries: Country[] = GetEnumValues(Country);
If You Prefer the Generic-Only Syntax
If you really want to call it as GetEnumValues<Country>() without passing the enum object, we can make it work—but note this uses eval, which carries small risks (only use this if you trust all enum names in your codebase):
function GetEnumValues<TEnum>(): TEnum[] { // Extract the enum name from the generic type (relies on the enum being in scope) const enumName = (TEnum as unknown as { name: string }).name; const enumObj = eval(enumName) as Record<string, TEnum>; return Object.values(enumObj).filter(value => { return typeof value !== 'string' || isNaN(Number(value)); }) as TEnum[]; } // Usage: const allCountries: Country[] = GetEnumValues<Country>();
For TypeScript 4.1+ (Since You Can Upgrade)
If you bump up to TS 4.1 or later, you can use more advanced type utilities to make the function even stricter, but the core logic stays the same. The explicit approach above is still the most maintainable for most projects.
Quick Breakdown
- Numeric Enums: The
filterstep removes the auto-generated reverse mapping strings (like "0", "1") that TypeScript adds for numeric enums. - String Enums: Since there's no reverse mapping, the filter just returns all values directly.
This matches the behavior of your C# GetValues method perfectly!
内容的提问来源于stack exchange,提问作者Marcel

