3

Say, I have an array const colors = ['R', 'G', 'B'] (or object const colors = {R: 'R', G: 'G', B: 'B'} which will also do). Considering typescript enums transpiled into objects, if I'm not missing anything. Is there a way to parse above array (or object) into enum dynamically?

E.g. something like (non-working pseudo-code sample for the sake of example):

type Color = colors.reduce((palette, color) => palette | color) 

or

enum Color = colors.reduce((palette, color) => (palette[color] = color, palette), enum) 

The whole idea behind is to turn long list of string values into enum, without hardcoding miles long type definition, like:

type Color = 'R' | 'G' | 'B' .. /* followed by gazillion more color values */ 

2 Answers 2

5

I think you need something like this:

 const Colors = ['Red', 'Blue', 'Green'] as const; type colors = typeof Colors[number] // 'Red' | 'Blue' | 'Green' 

Hopefully, this will work for you :)

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

Comments

0

Short answer:

Only numeric enums can have computed members, but this expression has type 'string'. If you do not need exhaustiveness checks, consider using an object literal instead`.

The long answer:

Unfortunately, you can do it, but it does not mean you should:

const colors = ['R', 'G', 'B'] enum Color { } const result = colors.reduce((acc, elem) => { return { ...acc, [elem]: elem } }, Color) 

In this case, you are loosing type safety. TS, can not figure out type of Color enum.

type O = keyof typeof result // never, TS don't know anymore nothing about this type enum OkColor{ R='R', G='G', B='B' } type O2 = keyof typeof OkColor // 'R' | 'G' | 'B' ---> here TS knows the keys of enum 

Try to avoid enums as much as possible. The best approach is to use constant objects:

const colors = { R:'R', G: 'G', B: 'B', } as const; 

If you still want to use enums, use them at least with const keyword. See docs

const enum X { A='A' } 

Here is code for type safe converting an array to readonly object:

const colors = ['R', 'G', 'B'] as const; type ValuesOfArray<T extends ReadonlyArray<any>> = T[number] type ToObj<K extends string> = { [P in K]: P } type ToEnum = ToObj<ValuesOfArray<typeof colors>> const toPseudoEnum = <T extends readonly any[], K extends ValuesOfArray<T>>(arr: T):Readonly<ToObj<K>> => { return arr.reduce((acc, elem) => { return { ...acc, [elem]: elem } }, {}) } const customEnum = toPseudoEnum(colors); // {R:'R',G:'G',B:'B'} 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.