【问题标题】:How to find element<T> in Array[T] where <T> is an enum?如何在 <T> 是枚举的 Array[T] 中找到元素<T>?
【发布时间】:2017-01-16 17:07:45
【问题描述】:

我才刚接触 TypeScript 几个月,正在深入研究它的内部工作原理。也许有人可以帮助提高我的理解。

在我们的 angular2 应用程序中,我们有一个enum 的权限定义为:

export enum UserPrivileges{
  SUPER,
  USER,
  GUEST 
}

我们将此类型作为枚举类型的数组包含在函数定义中:

checkPrivileges(userPrivileges: UserPrivileges[]) {...}

我们用来查找用户权限的模式是:

this.isSuperUser = userPrivileges.includes(UserPrivileges[UserPrivileges.SUPER]);

问题

TypeScript 抱怨 “'string' 类型的参数不能分配给 'UserPrivileges' 类型”,因为 Array.prorotype.includes() 方法调用(.indexOf() 存在同样的问题。)

我想不到的就地铸造形式都不起作用:

this.isSuperUser = userPrivileges.includes(<string>UserPrivileges[UserPrivileges.SUPER]);
this.isSuperUser = userPrivileges.includes(UserPrivileges[UserPrivileges.<string>SUPER]);

我们可以“欺骗” tsc linter 并将函数签名更改为:

checkPrivileges(userPrivileges: string[]) {...}

...但是使用类型有什么意义呢?

这一定是一个常见的用例,但我一定缺少必要的装饰器?是否需要将方法添加到枚举类型定义中以允许将其解释为字符串?

编辑

为了清楚起见,我们的后端在数组中返回用于特权的字符串令牌,例如userPrivileges = ["SUPER", "GUEST", "USER"]UserPrivileges 枚举类型旨在模仿这一点。

有效的旧方法(期望true):

userPrivileges.indexOf(UserPrivileges[UserPrivileges.SUPER]) > -1;

因为

  • UserPrivileges.SUPER 计算结果为 0(因为解释了发出的 JS Paarth)
  • UserPrivileges[0] 然后计算为字符串 "SUPER"
  • ...这是来自后端的userPrivileges[] 中的值。

而这些都将不受欢迎(但可以预见)返回false

userPrivileges.includes(UserPrivileges.SUPER);
userPrivileges.indexOf(UserPrivileges.SUPER) > -1;

出于与上述相同的原因:从服务器返回的userPrivileges[] 不包含值0

“当您将枚举值返回给自身时,您将取回字符串。” 为了使提议的解决方案发挥作用,似乎我是否必须使用类型的 数字索引 UserPrivileges[0] 来获取字符串以与 REST 返回进行比较?

【问题讨论】:

    标签: angular typescript ecmascript-6


    【解决方案1】:

    UserPrivileges.SUPER代替UserPrivileges[UserPrivileges.SUPER]

    this.isSuperUser = userPrivileges.includes(UserPrivileges.SUPER);
    

    打字稿中的非 const 枚举能够前后移动(它们是具有字符串到值和值到字符串的映射的对象)。它在 JS 中可能看起来像这样。

    const UserPrivileges = {
        ['SUPER'] = 0,
        ['USER'] = 1,
        ['GUEST'] = 2,
        [0] = 'SUPER',
        [1] = 'USER',
        [2] = 'GUEST',
    }
    

    因此,当您将枚举值返回给自身时,您将取回字符串 - 这解释了您看到的错误,因为 UserPrivileges.SUPER 解析为 0,并基于枚举上的数字索引返回一个字符串名称。


    更新了编辑中的信息。

    需要明确的是,我们的后端会在数组中返回用于权限的字符串令牌,例如 userPrivileges = ["SUPER", "GUEST", "USER"]

    如果这是真的,那么我怀疑我们可能在互相交谈。变量userPrivileges 不是Array&lt;T extends Enum&gt; 这是Array&lt;string&gt;

    此时您有几个选择。您可以决定使用字符串并将 UserPrivileges 创建为

    const UserPrivileges = {
        ['SUPER'] = 'SUPER',
        ['USER'] = 'USER',
        ['GUEST'] = 'GUEST',
    }
    

    或者您可以将字符串列表转换为真正的枚举列表。然后,从该列表工作应该会按预期运行。

    【讨论】:

    • 这是一个有趣的解决方案,正是我所观察到的。我会从赞成的数量中接受这是一个惯用的解决方案,所以谢谢。但对我来说似乎很奇怪,我必须自己实现这个双哈希映射。有没有更好的替代类型定义我可以使用,或者不同的查找模式?这似乎是潜在错误的来源:您必须记住将两者都添加,对于大型列表,这可能并不明显我不知道除了错误的分配检查之外的自动工具来检测这种错误,如果我有机会写使用它的代码。
    • 我担心我可能不清楚@msanford。您不必实现该 const,这大致是 typescript 编译器在发出 javascript 时为您生成的。我在说明您不需要索引枚举类型并解释为什么会遇到您遇到的错误。您应该绝对继续以与您在问题中相同的方式定义枚举。您应该以不同的方式使用它们(我的答案的第一行)
    • 感谢您的详细解释,Paarth。我已经用更多信息编辑了这个问题。建议的解决方案似乎不起作用,因为我必须使用UserPrivileges.0,而不是UserPrivileges.SUPER。不过,我可能仍然误解了一些东西。
    • @msanford 添加了一些更新以响应您的编辑。
    • 谢谢!我会与我的团队分享这个!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-08
    • 1970-01-01
    相关资源
    最近更新 更多