TypeScript не позволяет вам добавлять свойства к элементу enum
, который во время выполнения является простой строкой или числом.Вместо этого вы должны сделать что-то вроде создания нового типа, который содержит ссылки на эти элементы, а также имеет методы или свойства, которые вы хотите.
Вот один из возможных способов сделать это.Начните с простого enum
, например:
enum SampleEnum {
V, IV, III
}
И давайте дадим определение интерфейса для вашего расширенного типа.Он имеет name
, description
и number
.Обратите внимание, что этот тип является общим, поэтому мы можем сузить типы name
и number
в ближайшее время:
interface ISample<N extends number, S extends string> {
readonly name: S;
readonly description: string;
readonly number: N;
}
Вот функция, которая может взять ваш объект SampleEnum
и вернуть что-то с теми же ключамино со значениями, которые реализуют расширенный интерфейс:
function makeSample<E extends Record<Extract<keyof E, string>, number>>(
mapping: E
): { [K in Extract<keyof E, string>]: ISample<E[K], K> } {
const ret = {} as { [K in Extract<keyof E, string>]: ISample<E[K], K> };
(Object.keys(mapping).filter(k => k !== (+k) + "") as
(Extract<keyof E, string>)[]
).forEach(k => {
ret[k] = {
name: k,
description: "Blah " + k,
number: mapping[k]
}
});
return ret;
}
Это может быть много жонглирования типов, но это в основном просто извлечение строковых ключей из SampleEnum
(и игнорирование обратного отображения , который добавляет числовые ключи к числовым перечислениям во время выполнения) и создает экземпляр расширенного интерфейса для каждого из них, в некоторой степени безопасным для типа способом.
Наконец, давайте создадим значение и тип Sample
, которые заменяют наши enum
:
const Sample = makeSample(SampleEnum);
type Sample = (typeof Sample)[keyof typeof Sample]
Хорошо, давайте использовать его:
const nameOfIV = Sample.IV.name; // "IV"
console.log(nameOfIV); // "IV"
const numberOfIII = Sample.III.number; // SampleEnum.III
console.log(numberOfIII); // 1
const descriptionOfV = Sample.V.description; // string
console.log(descriptionOfV); // "Blah V"
const goodSample: Sample = Sample.III; // okay
const badSample: Sample = {
name: "II",
description: "oops",
number: 3
}; // error, name doesn't match
Выглядит разумно для меня. Убедитесь сами .Конечно, есть и другие способы приблизиться к этому, но мы надеемся, что это даст вам представление.Надеюсь, это поможет.Удачи!