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.

Related posts