Создание производного перечисления с ключами исходного в TypeScript

Задача

Создать перечисление или аналогичный тип DerivedEnum, ключи которого полностью совпадают с перечислением SampleEnum, при этом:

  1. Внесение изменений в ключи SampleEnum (добавление новых, удаление или переименовывание уже существующих) должно сделать DerivedEnum невалидным. Иными словами, TypeScript должен сказать в виде ошибки: "Изменил SampleEnum - давай теперь DerivedEnum тоже меняй".
  2. SampleEnum должна быть enum.

В принципе SampleEnum может иметь произвольный набор ключей, но поскольку для примера что-то нужно, то пусть это будет

enum SampleEnum {
  alpha: "FOO",
  bravo: "BAR"
}

Отчёт о самостоятельном сборе информации

Начнём с того, что тупое ручное копирование типа

enum SampleEnum {
  alpha: "FOO",
  bravo: "BAR"
}

enum DerivedEnum {
  alpha: "BAZ",
  bravo: "HOGE"
}

решением не является, поскольку внесение изменений в SampleEnum не повлечёт за собой ошибки TypeScript по причине невалидности DerivedEnum. По сути, DerivedEnum полностью автономна по отношению к SampleEnum как и к любым переменным.

keyof - это не то, что нужно, поскольку keyof даёт нам типы значений, а в этой задаче мы наследуем именно ключи, а не значения.

Наконец, я пытался задать аналогичный вопрос на англоязычном StackOveflow. Предложенное решение предполагает отказ от enum, а что бы про enum плохого не говорили, полноценной замены этой сущности пока нет. Другое дело, что получить enum на основе другой enum скорее всего, невозможно, потому DerivedEnum может быть и не enum, однако в рамках этой задачи SampleEnum является enum как данность.


Ответы (1 шт):

Автор решения: Александр Рогонов

Как-то вот так, если я правильно понял вопрос.

enum SampleEnum {
  alpha = "FOO",
  bravo = "BAR"
}

type DerivedEnum = {
  [key in keyof typeof SampleEnum]: string
}

const derivedEnum: DerivedEnum = {
  alpha: '123',
  bravo: '321',
};

Внесение изменений в ключи SampleEnum (добавление новых, удаление или переименовывание уже существующих) сделает derivedEnum не валидным.

→ Ссылка