10

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.

1
  • 2
    But string literal types will already provide intelisense. If you type "" in a position where a string literal is expected you will get intelisense as to possible values... Commented May 28, 2019 at 22:50

1 Answer 1

10

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Union type is nice and all, but I'm looking into making an enum for the main purpose of maintainability in the event that a string needs to be renamed. I might use the string literal "apple" in multiple places in the codebase, but using an enum gives me an easy way to rename things in a way that a global string find and replace would fail.
@mxiong enums have their advantages for sure. While renaming might not work, you should get errors everywhere the old version of the string is used

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.