Добавьте атрибут description в enum и прочтите это описание на TypeScript - PullRequest
0 голосов
/ 10 июня 2018

Мне интересно, как добавить атрибуты описания к enum в TypeScript.Я хотел бы создать перечисление следующим образом (или что-то подобное):

public enum Sample
{
    [Display(Name = "Blah V")]
    V,

    [Display(Name = " Blah IV")]
    IV,

    [Display(Name = " Blah III")]
    III,
}

Чтобы иметь возможность выполнять основные операции с таким перечислением, я бы создал общий EnumHelper.Этот вспомогательный класс должен содержать методы, которые позволяют: получить значение описания, получить имя и числовое значение.Вопрос в том, как этого добиться в машинописи?Если невозможно добавить атрибуты в перечисление, есть ли способ обойти?Я хотел бы иметь возможность:

-  get number of enum value,
-  get description value,
-  get the name of enum field.

например, для Sample.IV это будет:

1, 
Blah IV, 
IV.

Ответы [ 4 ]

0 голосов
/ 10 июля 2019

Вариант принятого ответа.Замените number на тип enum, чтобы быть более безопасным.

 export enum Sample {
      V,
      IV,
      III
    }

export const SampleLabel = new Map<Sample, string>([
  [Sample.V, 'FIVE'],
  [Sample.IV, 'FOUR'],
  [Sample.III, 'THREE']
]);
0 голосов
/ 26 июня 2018

этот шаблон работал для меня:

export enum PriceTypes {
    Undefined = 0,
    UndefinedDescription = 'Undefined' as any,
    UserEntered = 1,
    UserEnteredDescription = 'User Entered' as any,
    GeneratedFromTrade = 2,
    GeneratedFromTradeDescription = 'Generated From Trade' as any,
    GeneratedFromFreeze = 3,
    GeneratedFromFreezeDescription = 'Generated Rom Freeze' as any
}

...

    GetDescription(e: any, id: number): string {
        return e[e[id].toString() + "Description"];
    }
    getPriceTypeDescription(price: IPricePoint): string {
        return this.GetDescription(PriceTypes, price.priceType);
    }
0 голосов
/ 12 марта 2019

Другое интересное решение основано здесь использует ES6 Map:

export enum Sample {
  V,
  IV,
  III
}

export const SampleLabel = new Map<number, string>([
  [Sample.V, 'FIVE'],
  [Sample.IV, 'FOUR'],
  [Sample.III, 'THREE']
]);

USE

console.log(SampleLabel.get(Sample.IV)); // FOUR
0 голосов
/ 11 июня 2018

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

Выглядит разумно для меня. Убедитесь сами .Конечно, есть и другие способы приблизиться к этому, но мы надеемся, что это даст вам представление.Надеюсь, это поможет.Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...