Is there a way to dynamically generate enums on TypeScript based on Object Keys?
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]}
Solution 1:
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;
Solution 2:
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";
// }