Type-safe Enum Dictionaries in Typescript

Viewed 82

I would like dirVectors[Turn.Straight] to fail at compile-time.

enum Direction {
    Up,
    Down,
    Right,
    Left,
}

enum Turn {
    Clockwise,
    Counterclockwise,
    Straight,
}

const dirVectors = {
    [Direction.Up]: [0, 1],
    [Direction.Down]: [0, -1],
    [Direction.Right]: [1, 0],
    [Direction.Left]: [-1, 0]
} as Record<Direction, [number, number]>;

I'm assuming the reason dirVectors[Turn.Straight] is OK is because they're both numbers, with Straight = 2, which is a subset of Direction {0,...,3}. When I assign a unique string to each enum's value, it does fail at compile-time. However, is it possible to get the compile-time error without going the string route?

1 Answers

If you assign values to Enum, it works as expected:

enum Direction {
  Up = 'Up',
  Down = 'Down',
  Right = 'Right',
  Left = 'Left'
}

enum Turn {
  Clockwise = 'Clockwise',
  Counterclockwise = 'Counterclockwise',
  Straight = 'Straight'
}

const dirVectors = {
  [Direction.Up]: [0, 1],
  [Direction.Down]: [0, -1],
  [Direction.Right]: [1, 0],
  [Direction.Left]: [-1, 0]
} as Record<Direction, [number, number]>

dirVectors[Direction.Up] // compiles
dirVectors[Turn.Straight] // does not compile

Question is, do you really need Enum? Are you using anything from Enum which union types does not provide? See if following works for you:

type Direction = 'Up' | 'Down' | 'Right' | 'Left'

type Turn = 'Clockwise' | 'Counterclockwise' | 'Straight'

const dirVectors: Record<Direction, [number, number]> = {
  Up: [0, 1],
  Down: [0, -1],
  Right: [1, 0],
  Left: [-1, 0]
}

dirVectors['Down'] // compiles
dirVectors['Straight'] // does not compile
Related