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">
В любом случае, надеюсь, это поможет. Удачи!
Ссылка на код