是否可以从Angular中的服务获取枚举的值

时间:2019-11-21 08:47:18

标签: angular typescript enums angular-services

我创建了一个枚举,目前该枚举是键和动态值,但是现在它的值需要来自服务作为显示文本,并且无论如何我都找不到。 我只需要从服务获取的值就不会更改动态,而该值只是文本的一个值 这是枚举。

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

从现在开始,文本来自另一个带有URL的平台,例如,我需要在插值或属性绑定中显示该URL。

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

Service中的getText方法

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 个答案:

答案 0 :(得分:1)

const enum完全不能具有计算成员。不是enum的数字const可以具有计算成员,但是不幸的是,具有字符串成员的enum不能具有计算成员。我不知道是否有很好的文档,但是至少有open issue个关于您收到的错误消息是如何引起误解的信息。无论如何,要点是:您无法使用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。)< / p>

然后,您可以像使用Test值那样使用enum的属性:

const someVal = Test.Test2; // string

const对象和enum之间存在一些差异,但是它们对于您的用例可能并不重要。如果这样做的话,您可能可以修复它们。

例如:enum引入了命名的 types 以及命名的值。但是,由于您的值是经过计算的,因此您不能比使用string作为类型更好。如果要防止某人将随机的string值复制到您希望枚举的位置,则可以使用branded primitive类型:

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">

无论如何,希望能有所帮助。祝你好运!

Link to code