Можно ли получить значение enums от сервиса в Angular? - PullRequest
0 голосов
/ 21 ноября 2019

У меня есть созданное перечисление, которое на данный момент является ключом и значением динамическим, но теперь значение, которое оно должно получить от службы в виде отображаемого текста, и я все равно не нахожу, как это сделать. Мне нужно только получить значение от службы, чтобы не изменять динамическое значение, которое будет содержать только одно значение с текстом. Это перечисление.

const enum Test {
Test1 = 'this is test 1',
Test2 = 'this is test 2',
Test3 = 'this is test 3',
Test4 = 'this is test 4',
}

С этого момента текст приходит с другой платформы с URL-адресом, который мне нужен. например, в Интерполяции или Привязке свойств.

Test1 = this.textService.getText('here the id of the text'),

Метод getText в Service

public getText(key: string, isGeneralKey = false): string {
  let searchKeys: string[];
  let result: string | DisplayTextMap;

  searchKeys = key.split('.');
  result = (isGeneralKey
    ? this.generalTexts[searchKeys[0]]
    : this.texts[searchKeys[0]]) as DisplayTextMap;

  if (result && searchKeys[1]) {
    result = result[searchKeys[1]];
  }
  if (result) {
    return this.decodeUnicodeTextService.getDecodedText(result as string);
  }
  return `${key} not found`;
}

1 Ответ

1 голос
/ 22 ноября 2019

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

К счастью, вам, вероятно, не нужен enum. Часто вы можете заменить enum на const объект с readonly свойствами, инициализированными значениями, которые вас интересуют, например:

    const asReadonly = <T>(t: T): { readonly [K in keyof T]: T[K] } => t
    const Test = asReadonly({
        Test1: this.textService.getText('here the id of the text'),
        Test2: this.textService.getText('here is a different id'),
        Test3: this.textService.getText('you get the idea'),
        Test4: this.textService.getText('etc')
    });

(Обратите внимание, что приведенный выше asReadonly() только делаетсвойства доступны только для чтения во время компиляции. Если вы хотите, чтобы чтение также было только во время выполнения, вы можете сделать так, чтобы оно возвращало Object.freeze(t) вместо t.)

Тогда вы можете использовать свойства Test так же, как призначение enum:

const someVal = Test.Test2; // string

Существуют некоторые различия между const объектом и enum, но они могут не иметь значения для вашего варианта использования. И вы можете исправить это, если они делают.

Например: enum вводит именованные типы , а также именованные значения. Так как ваши значения вычисляются, вы не можете добиться гораздо большего успеха, чем использование string в качестве типа. Если вы хотите, чтобы кто-то не копировал случайные значения string в то место, где вы ожидаете перечисления, вы можете использовать фирменный примитив типа:

const asEnum = <T, N extends string>(t: T, n: N) =>
    Object.freeze(t) as { readonly [K in keyof T]: T[K] & { __brand: N } };

const Test = asEnum({
    Test1: this.textService.getText('here the id of the text'),
    Test2: this.textService.getText('here is a different id'),
    Test3: this.textService.getText('you get the idea'),
    Test4: this.textService.getText('etc')
}, "Test");
type Test = typeof Test[keyof typeof Test];

И тогда вы можете использовать Testи как значение со свойствами, и как тип:

function acceptTestEnumOnly(t: Test) { }
acceptTestEnumOnly(Test.Test3); // okay
acceptTestEnumOnly("oops"); // error!  "oops" is not assignable to Brand<"Test">

В любом случае, надеюсь, это поможет. Удачи!

Ссылка на код

...