Craig Smitham
Craig Smitham

Reputation: 3965

Create a TypeScript (string) enum from a union type?

If I have a TypeScript union like so:

type SomeUnion = 'Foo' | 'Bar' | 'Baz';

Is there a way I can convert this into a string-based enum? Like the the following:

enum SomeUnionBasedEnum {
  Foo = 'Foo',
  Bar = 'Bar',
  Baz = 'Baz'
}

I am trying to model an enum that represents the permissions in our system, but those permissions are in some cases automatically generated union types. I want a way to combine them into a single enum because enums provide a better developer experience by limiting the intellisense to the permissible values. For example AppPermisionEnum.<available enum values>. I'd also be open to ways to combine enums into a single enum, but I don't think that's possible. My end goal is to have an enum comprised of values from a couple different sources.

Upvotes: 10

Views: 6582

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249556

Like I pointed out in the comments string literal types already offer good intelisense support, so I personally would just use those and not bother creating anything else, the developer experience is already great.

The code below is a solution in search of a problem but we can do something close to what you want.

You can't create an enum, but you can create an object that has all the properties of the union and each property has the same value as the key, using a mapped type. You will need to maintain these objects manually, but typescript will issue a warning if ever they are out of sync so maintaining them should not be an issue.

type SomeUnion = 'Foo' | 'Bar' | 'Baz';

function createEnumObject<T extends string>(o: { [P in T]: P }) {
    return o;
}

const SomeUnion = createEnumObject<SomeUnion>({
    Foo: "Foo",
    Bar: "Bar",
    Baz: "Baz"
})

let o: SomeUnion = SomeUnion.Bar;

Converting a union (ie a type) to an object (ie a value) without extra code is in principle not possible, types are erased at compile time so can't be relied upon for anything at run-time and typescript has a strict policy against type directed emit.

Upvotes: 9

Related Questions