How to get an array of enum values in TypeScript

Russian translation of this article is available.

Here is a generic function that works with both numeric and string enums:

type EnumObject = {[key: string]: number | string};
type EnumObjectEnum<E extends EnumObject> = E extends {[key: string]: infer ET | string} ? ET : never;

function getEnumValues<E extends EnumObject>(enumObject: E): EnumObjectEnum<E>[] {
  return Object.keys(enumObject)
    .filter(key => Number.isNaN(Number(key)))
    .map(key => enumObject[key] as EnumObjectEnum<E>);
}

Seems to be working in TypeScript 4 and 3.6+.

Usage

Numeric enum:

enum NumEnum {
    A,
    B,
    C,
}
// The type is inferred as NumEnum[]
let numEnumValues = getEnumValues(NumEnum);

String enum:

enum StringEnum {
    A = "a",
    B = "b",
    C = "c",
}
// The type is inferred as StringEnum[]
let stringEnumValues = getEnumValues(StringEnum);

Known issues

Unfortunately, this function doesn't type-check very well with mixed enums (containing both numeric and string values), at least at the time of TypeScript 4.6:

enum MixedEnum {
    A = "a",
    B = 2,
    C = "c",
}
// The type is inconveniently inferred as MixedEnum.B[]
let mixedEnumValues = getEnumValues(MixedEnum);
// Declare type explicitly as a workaround:
let mixedEnumValues: MixedEnum[] = getEnumValues(MixedEnum);
let mixedEnumValues = getEnumValues(MixedEnum) as MixedEnum[];

Afterwords

Here's an amazing post by Zhenghao about type-level programming in TypeScript, if you want to tinker in this stuff too. It taught me a lot!

Zhenghao
Software Engineer