My colleague @mattcosta7 demonstrated something that feels obvious in hindsight.

Instead of enums, use a regular object. So instead of


enum State {
  SOLID,
  LIQUID,
  GAS,
}

(playground here - note how "complex" the transpiled JavaScript becomes)

...use an object. Objects have the advantage that when the TypeScript is converted to JavaScript, it looks pretty much identical. TypeScript 5.8 makes it possible to disallow "non-erasable syntax" which means you can set up your tsconfig.json to avoid enum.

The alternative is an object. It's a bit more verbose but it has advantages:


const State = {
  SOLID: "solid",
  LIQUID: "liquid",
  GAS: "gas"
} as const

type State = typeof State[keyof typeof State]

(playground here - note how simple the transpiled JavaScript is)

In the above code, if you hover the mouse over State it'll say

'solid' | 'liquid' | 'gas'

If you had used:


type State =  keyof typeof State

and then hover over the State, you'd see:

'SOLID' | 'LIQUID' | 'GAS'

which is not what you'd expect to use.

The smart in type State = typeof State[keyof typeof State] is that you could edit the value and the types would still all remain correct. For example:


const State = {
  SOLID: "solid",
  LIQUID: "liquid",
- GAS: "gas"
+ GAS: "gasy"
} as const

Alternatively, as a list of strings

You could also define the type as:


type State = 'solid' | 'liquid' | 'gas'

But then consider the code that'd use it. Instead of:


function printer(state: State) {
  if (state === State.GAS) console.log("It's a gas")
  else if (state === State.LIQUID) console.log("It's a liquid")
  else if (state === State.SOLID) console.log("It's a solid")
  else throw new Error(state)
}

printer(State.SOLID)

you have to make the JavaScript refer to these by strings exactly too:


function printer(state: State) {
  if (state === 'gas') console.log("It's a gas")
  else if (state === 'liquid') console.log("It's a liquid")
  else if (state === 'solid') console.log("It's a solid")
  else throw new Error(state)
}

printer('solid')

Simpler, but if you decide to change gas to gasy you have to change all the code that uses this too. E.g.


function printer(state: State) {
- if (state === 'gas') console.log("It's a gas")
+ if (state === 'gasy') console.log("It's a gas")
  else if (state === 'liquid') console.log("It's a liquid")
  else if (state === 'solid') console.log("It's a solid")
  else throw new Error(state)
}

Comments

Your email will never ever be published.

Previous:
How I run standalone Python in 2025 January 14, 2025 Python
Next:
How to send custom headers in a loader in react-router v7 February 7, 2025 React, JavaScript
Related by category:
Switching from Next.js to Vite + wouter July 28, 2023 JavaScript
How to SSG a Vite SPA April 26, 2025 JavaScript
An ideal pattern to combine React Router with TanStack Query November 18, 2024 JavaScript
swr compared to @tanstack/react-query August 30, 2024 JavaScript
Related by keyword:
Performance of truth checking a JavaScript object February 3, 2020 Node, JavaScript
US License Plate Spotter (part 1) July 9, 2012 JavaScript