Reputation: 1269
Let's say I have a function like this but with many more possible values for the enum parameter:
enum API{
userDetails = "/api/user/details",
userPosts = "/api/user/posts",
userComments = "/api/user/comments",
postDetails = "/api/post/details",
postComments = "/api/post/comments"
//...
};
function callAPI(endpoint: API/*, some more params*/){
// some code to deal with the specified endpoint...
}
callAPI(API.userComments);
The above code works fine, but I need to group the many values of the enum into an organized hierarchical structure in order to make things a little more organized... For example, it would be much better if the syntax for calling the API can be callAPI(API.user.comments)
instead of callAPI(API.userComments)
.
I tried things like the below attempts but it looks like none were accepted as a valid syntax for typescript.
Attempt 1
enum API{
user = {
details : "/api/user/details",
userPorts : "/api/user/posts",
userComments : "/api/user/comments"
}
post = {
postDetails : "/api/post/details",
postComments : "/api/post/comments"
}
}
Attempt 2
enum user {
details = "/api/user/details",
userPorts = "/api/user/posts",
userComments = "/api/user/comments"
}
enum post {
postDetails = "/api/post/details",
postComments = "/api/post/comments"
}
enum API{
user,
post
}
Attempt 3
enum user {
details = "/api/user/details",
userPorts = "/api/user/posts",
userComments = "/api/user/comments"
}
enum post {
postDetails = "/api/post/details",
postComments = "/api/post/comments"
}
enum API{
user = user,
post = post
}
Attempt 4
enum user {
details = "/api/user/details",
userPorts = "/api/user/posts",
userComments = "/api/user/comments"
}
enum post {
postDetails = "/api/post/details",
postComments = "/api/post/comments"
}
enum API{
user:user
post:post
}
Upvotes: 3
Views: 3905
Reputation: 374
My understanding is that it's not possible with enums - right hand side of an enum member can be either nothing, number, string, or another enum value. See https://www.typescriptlang.org/docs/handbook/enums.html for more details.
But you can easily achieve what you want with plain objects.
const API = {
user: {
details: "/api/user/details",
posts: "/api/user/posts",
},
// ...
};
If you're worried that it might be modified, you can use Object.freeze.
If you need to pass the whole API object to a function via argument then you'll need to define an interface for it too, but otherwise autocomplete and checks should work just fine.
-------- edit
Adding types in case you find them useful:
export type ApiRoutes<TRoute extends string> = { [key in TRoute]: string };
export interface MyApi {
user: ApiRoutes<"details" | "posts" | "comments">;
post: ApiRoutes<"details" | "comments">;
}
Upvotes: 4
Reputation: 1932
You could wrap it inside a namespace:
namespace API{
export enum User {
details = "/api/user/details",
posts = "/api/user/posts",
comments = "/api/user/comments",
}
export enum Post {
details = "/api/post/details",
comments = "/api/post/comments",
}
}
console.log(API.User.comments)
console.log(API.Post.details)
Upvotes: 9