Reputation: 333
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]}
Upvotes: 33
Views: 36328
Reputation: 15955
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;
}
Upvotes: 0
Reputation: 3247
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";
// }
Upvotes: 4
Reputation: 249796
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;
Upvotes: 28