Union of enum values as type

95 Views Asked by At

I'm trying to use type safety for a specific scenario. Imagine we have:

const enum Color {
  red = 'red',
  blue = 'blue',
}

const enum Shape {
  rectangle = 'rectangle',
  square = 'square',
  circle = 'circle'
}

Is it possible to create a type that would accept either the values of the first enum or the second?

What I've tried:

type Characteristics =
  | `${Color}`
  | `${Shape}`

const characteristic: Characteristics[] = ['circle', 'red']; // should fail, but it does not

But I couldn't fully satisfy my requirements as that array can take any of the enum values.

What I need is:

const char1: Characteristics[] = ['circle', 'square']; // good
const char2: Characteristics[] = ['circle', 'red']; // fail
const char3: Characteristics[] = []; // fail
const char4: Characteristics[] = ['test', 'red', 'blue']; // fail
2

There are 2 best solutions below

1
On BEST ANSWER

Use a Union Type (keyof typeof Color)[] | (keyof typeof Shape)[] to declare an array type with items either only of type Color or only of type Shape.

To ensure that the array has at least one value declare a Tuple Type with a fixed first item and a spreaded array on the second index.

const enum Color {
  red = "red",
  blue = "blue",
}

const enum Shape {
  rectangle = "rectangle",
  square = "square",
  circle = "circle",
}

type Colors = keyof typeof Color;
type Shapes = keyof typeof Shape;

type Characteristics = [Colors, ...Colors[]] | [Shapes, ...Shapes[]];

let char: Characteristics;

char = ["circle", "square"]; // good
char = ["red", "blue"]; // good
char = ["circle", "red"]; // fail
char = ["circle", "red"]; // fail
char = []; // fail
char = ["test", "red", "blue"]; // fail

TypeScript Playground

0
On

See this answer for some reference: Is it possible to define a non empty array type in Typescript?

With that in mind, the following would do.

type NonEmptyArray<T> = [T, ...T[]];
type Characteristics = NonEmptyArray<Color>|NonEmptyArray<Shape>;