35

I'm defining an object and I want to dynamically generate enum based on its keys, so I get IDE suggestions and do not call wrong keys.

const appRoutes = {
   Login,
   Auth,
   NotFound
} 

enum AppRoutes = {[Key in keyof appRoutes]: [keyof appRoutes]}

3 Answers 3

29

You can't build an actual enum from the object keys.

You can get a union of all keys with just keyof typeof appRoutes and that will have the type safe effect you want:

type AppRoutes = keyof typeof appRoutes

let ok: AppRoutes = "Auth";
let err: AppRoutes = "Authh";

An enum is not just a type though, it's also a runtime object that contains the keys and values of the enum. Typescript does not offer a way to automatically create such an object from a string union. We can however create a type that will ensure that the keys of an object and the members of the union stay in sync and we get a compiler error if t hey are not in sync:

type AppRoutes = keyof typeof appRoutes
const AppRoutes: { [P in AppRoutes]: P } = {
    Auth : "Auth",
    Login: "Login",
    NotFound: "NotFound" // error if we forgot one 
    // NotFound2: "NotFound2" // err
}
let ok: AppRoutes = AppRoutes.Auth;
Sign up to request clarification or add additional context in comments.

2 Comments

What, if any, differences are there between these and original enums?
I think that the point is that this is a way to dynamically generate values as opposed to hardcoding them, as you need to do with enums.
4

I use this workaround to convert the keys to a const key -> key object:

const { Login, Auth, NotFound } = {} as any
const appRoutes = {
  Login,
  Auth,
  NotFound
}

const AppRoutes = (() => ({
 ...Object.keys(appRoutes)
   .filter(k => isNaN(Number(k)))
   .reduce((acc, cur) => ({
     ...acc,
     [cur]: cur,
   }), {}),
} as  {
 [k in keyof typeof appRoutes]: k
}))()

console.info(AppRoutes)
// AppRoutes: {
//   Login: "Login";
//   Auth: "Auth";
//   NotFound: "NotFound";
// }

Comments

1

Anyways enum in typescript get converted to object, so I think, best is to create an object dynamically

 type A = keyof typeof ImagePresetDetails;
 const ImagePresetsObject:Record<A,A> = {}; // use this as enum
 for (const key in ImagePresetDetails) {
     ImagePresetsObject[key] = key;
 }

Comments

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.