enum в typescript - это до сих пор единственный способ представить номинативный юнион и сохранить механизм "исчерпывания" (exhaustion) - как то проверка в Record и сужение в switch-case. Брендирование строк, например, теряет это свойство(
Помню был PR по добавлению специального синтаксиса для брендов, но он так и не взлетел.
Playground link
enum Fruit { orange = 'orange', apple = 'apple'}
enum Color { orange = 'orange', green = 'green'}
type Fruit_union =
| 'orange' & {__tag: 'Fruit'}
| 'apple' & {__tag: 'Fruit'}
type Color_union =
| 'orange' & {__tag: 'Color'}
| 'green' & {__tag: 'Color'}
// exhaustiveness example
const testExUnion: Record<Fruit_union, number> = {} // doesn't work
// @ts-expect-error Type '{}' is missing the following properties from type 'Record<Fruit, number>': orange, apple
const testExEnum: Record<Fruit, number> = {} // works fine
// nominative example
const testNomColor: Color = Color.orange
// @ts-expect-error Type 'Fruit.orange' is not assignable to type 'Color'.
const testNomColor1: Color = Fruit.orange