After a few years of trying to make them work, I've given up on TS enums, for the reasons you describe. The union-of-values approach works better, is safer at runtime, and my IDE is smart enough that I can tab-complete to the seemingly 'magic' strings.

Also, 'as const' works magic:

const Suits = ["Hearts", "Diamonds","Clubs","Spades"] as const.

type SuitType = typeof Suits[number]; // Super hacky-looking but works great if you need to change Suits.

This couples especially well with the 'options object' pattern:

const SuitsOptions: Record<SuitType, SuitOptionType> =

{ "Hearts": { icon: "♥️" },

...etc }

and permits looping over the options in an order of your choosing, the way a numeric enum does, e.g. for showing a React element for each:

{Suits.map(suit => <SuitComponent key={suit} suit={suit} />)}

Hope this changes your mind about the utility of union-of-values types!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Alex Feinman

Obligate infovore. All posts made with 100% recycled electrons, sustainably crafted by artisanal artisans. He/him/his.