Как получить массив значений перечисления (enum) в TypeScript
👋
Хочешь поучаствовать в жизни сайта?
Мы ищем авторов!
Вот generic-функция, которая работает как с числовыми enum'ами, так и со строковыми:
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>);
}
Работает на TypeScript 4 и 3.6+.
Использование
На числовом перечислении:
enum NumEnum {
A,
B,
C,
}
// Компилятор определяет тип numEnumValues как NumEnum[]
let numEnumValues = getEnumValues(NumEnum);
На строковом перечислении:
enum StringEnum {
A = "a",
B = "b",
C = "c",
}
// Компилятор определяет тип stringEnumValues как StringEnum[]
let stringEnumValues = getEnumValues(StringEnum);
Известные проблемы
К сожалению, функция проходит тайп-чекинг не очень хорошо, если enum составлен из разных типов (из чисел и строк одновременно), по крайней мере на момент TypeScript 4.6:
enum MixedEnum {
A = "a",
B = 2,
C = "c",
}
// Тип mixedEnumValues неправильно определяется как MixedEnum.B[]
let mixedEnumValues = getEnumValues(MixedEnum);
// Можно избежать этой проблемы, если задать тип явно одним из способов:
let mixedEnumValues: MixedEnum[] = getEnumValues(MixedEnum);
let mixedEnumValues = getEnumValues(MixedEnum) as MixedEnum[];
Послесловие
Вот шикарный пост от Zhenghao про программирование на уровне типов в TypeScript. Я из него многое почерпнул!
Zhenghao’s site
The official site of Zhenghao He, a software engineer and a TypeScript/JavaScript enthusiast.

Материал подготовлен с ❤️ редакцией Кухни IT.
☕
Заходи в канал Telegram
и в чат!
Кухня - это не только сайт, но и живое сообщество айтишников.