Is it possible to store an enum that contains an object?

Viewed 73

I would like to create an enum like:

enum stores {
  STOREA = { label: "Amazon", value: "amazon" };
  STOREB = { label: "Walmart", value: "walmart" };
}

but I see the following error:

Type '{ label: string; value: string; }' is not assignable to type 'stores'.ts(2322)

Is this possible in typescript?

1 Answers

No, an enum can only take string or numeric values in TypeScript:

enum Stores {
    STOREA = "amazon", 
    STOREB = "walmart"
}

But you probably don't need an enum to get the same or similar functionality, depending on your use case. If I wanted to make Stores into something with object values that still acted as much like an enum as possible, I'd write it this way:

const Stores = {
    STOREA: { label: "Amazon", value: "amazon" },
    STOREB: { label: "Walmart", value: "walmart" }
} as const;
type Stores = typeof Stores[keyof typeof Stores];
namespace Stores {
    export type STOREA = typeof Stores.STOREA;
    export type STOREB = typeof Stores.STOREB;
}

Here, there are three things named Stores:

  • an object that exists at runtime, with keys STOREA and STOREB and with object values;
  • a type that corresponds to the union of object values inside the Stores object; and
  • a namespace that exposes its own types, so that the type Stores.STOREA is the type of the value Stores.STOREA, and that the type Stores.STOREB is the type of the value Stores.STOREB.

With these you can essentially do anything a real enum would do for you:

interface Foo {
    store: Stores; // using the type here
}

interface AmazonFoo extends Foo {
    store: Stores.STOREA; // using the namespace here
}

const foo: Foo = { store: Stores.STOREB }; // using the value here
const amFoo: AmazonFoo = { store: Stores.STOREA }; // using the value here

You can verify that these uses work for both versions of Stores. Of course it's quite possible that your actual use case doesn't need all these features, in which case you could only include the ones you care about. My guess is that you absolutely need the const Stores = ... object, and could probably make use of the type Stores = .... type, but I'd be a bit surprised if the namespace Stores { ... } is necessary. But again, that depends on the use case.

Playground link to code

Related