【问题标题】:How to nest enums in TypeScript?如何在 TypeScript 中嵌套枚举?
【发布时间】:2020-10-07 07:41:04
【问题描述】:

假设我有一个这样的函数,但枚举参数有更多可能的值:

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);

上面的代码工作正常,但我需要将枚举的许多值组合成一个有组织的层次结构,以使事情更有条理......例如,如果调用的语法会更好API 可以是callAPI(API.user.comments) 而不是callAPI(API.userComments)

我尝试了以下尝试,但似乎没有一个被接受为打字稿的有效语法。

尝试 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"
    }
}

尝试 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
}

尝试 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
}

尝试 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
}

【问题讨论】:

    标签: typescript enums


    【解决方案1】:

    你可以把它包裹在 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)
    

    【讨论】:

      【解决方案2】:

      我的理解是枚举是不可能的——枚举成员的右侧可以是空值、数字、字符串或其他枚举值。 详情请见https://www.typescriptlang.org/docs/handbook/enums.html

      但是您可以使用普通对象轻松实现您想要的。

      const API = {
        user: {
          details: "/api/user/details",
          posts: "/api/user/posts",
        },
        // ...
      };
      

      如果担心会被修改,可以使用Object.freeze

      如果您需要通过参数将整个 API 对象传递给函数,那么您也需要为其定义一个接口,否则自动完成和检查应该可以正常工作。

      -------- 编辑

      添加类型以备不时之需:

      export type ApiRoutes<TRoute extends string> = { [key in TRoute]: string };
      
      export interface MyApi {
        user: ApiRoutes<"details" | "posts" | "comments">;
        post: ApiRoutes<"details" | "comments">;
      }
      

      【讨论】:

      • 您还可以在对象末尾添加as const,使其仅可读。这不会阻止运行时修改,但类型应该阻止编译尝试修改它
      • 我想我会用这个。尽管如果我可以将 API 作为一种类型来实现类型验证,我会更喜欢。
      • 有点hacky,但你可以使用这些类型:如前所述,在对象初始化后使用as const。然后要获取您的类型,首先创建一个通用用例type ValueOf&lt;T&gt; = T[keyof T];,它为您提供对象值的联合。然后type APIRoute = ValueOf&lt;ValueOf&lt;typeof API&gt;&gt; 为您提供值的值,即字符串路由。只要深度保持不变,这应该可以工作,我知道如何为动态深度做到这一点
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-15
      • 1970-01-01
      • 2016-03-31
      • 2019-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多