【问题标题】:TypeScript - Switch Statement based on Enum Comparison goes straight to DefaultCaseTypeScript - 基于枚举比较的 Switch 语句直接进入 DefaultCase
【发布时间】:2019-08-12 07:06:40
【问题描述】:

问题: 我有一个 switch 语句。比较基于两个enums。但是条件都返回 false。

在 STACK_OVERFLOW 上找到可能的解决方案: 我在某处读到,为了避免这种情况,您必须在这种情况下添加+

switch(+resources) instead of switch(resources)

这有副作用,将case 转换为一个数字,这让TS 很不高兴,因为我的enumsstrings

示例代码: 枚举,我想在我的函数中使用:

enum ResourceTypes {
  RESOURCE1 = 'RESOURCE1',
  RESOURCE2 = 'RESOURCE2',
  RESOURCE3 = 'RESOURCE2',
}

export default ResourceTypes;
enum OperationTypes {
  OPERATION1 = 'OPERATION1',
  OPERATION2 = 'OPERATION2',
  OPERATION3 = 'OPERATION3',
  OPERATION4 = 'OPERATION4'
}

export default OperationTypes;

函数,总是恢复到默认情况,只是检查resourceType,并返回一个操作数组:

import ResourceTypes from '../enums/ResourceTypes';
import OperationTypes from '../enums/OperationTypes';

const operationPerResource = (resource: any): OperationTypes[] => {
  const { RESOURCE1, RESOURCE2, RESOURCE3 } = ResourceTypes;
  const { OPERATION1, OPERATION2, OPERATION3, OPERATION4 } = OperationTypes;

  switch (resource) {
    case RESOURCE1:
      return [OPERATION2, OPERATION3, OPERATION4];
    case RESOURCE2:
      return [OPERATION1, OPERATION2, OPERATION3];
    case RESOURCE3:
      return [OPERATION1, OPERATION2];
    default:
      return [];
  }
};

export default operationPerResource;

这就是我调用函数的地方:

    const resources = transformEnumToArray(ResourceTypes);

    const operations = operationPerResource(resources.value).map((value: any) => ({
      label: value,
      value
    }));

这是 transofrmEnumToArray 函数:

const transformEnumToArray = (object: object): any =>
  Object.keys(object).map(value => ({
    label: value,
    value
  }));

export default transformEnumToArray;

关于实施的一些细节。 operations 用于 React-Select 组件。因此,对于每个选择,我在一个字段(资源)上进行,我在另一个字段中获得可用的操作。

resources.value 打印在控制台中。根据每个 react-select,我在 label, value 对象中恢复了所有内容。


我的意思是,我在这里做错了什么?为什么枚举的比较不起作用。你们能帮我吗?我用constants而不是枚举测试了它,它工作得很好。那么 Typescript 中的enums 有什么区别呢? 谢谢

【问题讨论】:

  • 你在这里有一个错字RESOURCE3 = 'RESOURCE2' 除了它似乎工作之外,你能展示你如何调用这个函数
  • 在官方打字稿操场和 jsfiddle 3.5.1 版本中测试上面的代码,它按预期工作,你能举一个可重现的例子吗? jsfiddle.net/ab9v8mty
  • 听起来(resource: any) 并不是您希望的那样(any 在这里听起来是个坏主意)
  • 嗯,resource:any,是一个我可以轻松修复的小更新。已经完成了,但不会改变结果。我已经更新了问题,包括我使用函数的方式、获取数据的位置以及适当的转换函数。

标签: javascript reactjs typescript enums


【解决方案1】:

如果您在带有类型参数的函数中使用 switch 表达式,则可以按预期工作。

例子:

enum ResourceTypes {
    RESOURCE1 = 'RESOURCE1',
    RESOURCE2 = 'RESOURCE2',
    RESOURCE3 = 'RESOURCE2',
}

enum OperationTypes {
    OPERATION1 = 'OPERATION1',
    OPERATION2 = 'OPERATION2',
    OPERATION3 = 'OPERATION3',
    OPERATION4 = 'OPERATION4',
}

const operationPerResource = (resource: ResourceTypes): OperationTypes[] => {
    const { RESOURCE1, RESOURCE2, RESOURCE3 } = ResourceTypes;
    const { OPERATION1, OPERATION2, OPERATION3, OPERATION4 } = OperationTypes;

    switch (resource) {
        case RESOURCE1:
            return [OPERATION2, OPERATION3, OPERATION4];
        case RESOURCE2:
            return [OPERATION1, OPERATION2, OPERATION3];
        case RESOURCE3:
            return [OPERATION1, OPERATION2];
        default:
            return [];
    }
};


console.log (operationPerResource(ResourceTypes.RESOURCE2))

将编译?并输出["OPERATION1", "OPERATION2", "OPERATION3"]?

【讨论】:

    【解决方案2】:

    你能展示示例调用代码吗?一些可能有助于追查问题的想法:

    我希望签名是

    const operationPerResource = (resource: ResourceType): OperationTypes[]
    

    这将保证您使用 ResourceType 进行调用

    我从未见过像这样解构的枚举。当然,我不认为这有什么问题,但是 TypeScript 可能对这些类型做了一些意想不到的事情。如果您明确重写ResourceType.RESOURCE1 等,是否会发生任何变化?

    【讨论】:

    • 我没有尝试告诉你真相。但最终babel 应该将它们转换为正确的结构。让我试试,然后回复你..
    • 遗憾的是,它没有成功。无论如何,解构不应该发挥作用。感谢您的宝贵时间。
    • 现在您已经发布了调用代码,很清楚为什么需要将签名键入为any - 您似乎没有使用 ResourceType 'RESOURCE1' 调用代码一般来说,避免在 TypeScript 中使用any,这是隐藏错误类型的一种逃避尝试在 operationPerResource 函数中添加日志语句,我敢打赌你看不到类似
    【解决方案3】:

    编辑: (我还不能评论你的帖子)

    如果您在 typescript playground 中查看,您会看到为什么它适用于 JS 对象而不是枚举。 当您检查 RESOURCE1 时,它不会被评估为字符串 RESOURCE1 您可以通过更改 RESOURCE1: 'RESOURCE123' 来检查它,例如

    我通常也不使用枚举,但似乎

    const { RESOURCE1, RESOURCE2, RESOURCE3 } = ResourceTypes
    
    // RESOURCE1 != 'RESOURCE1' as it would be for a JS Object
    // RESOURCE1 === RESOURCE1
    

    您可以检查this playground 打开您的控制台,然后点击运行按钮。 如果您查看 case 键,您会发现第一个不是 RESOURCE1aze,但仍然是 RESOURCE1


    你仍然可以使用tell don't ask pattern来避免switch语句:

    import { RESOURCE1, RESOURCE2, RESOURCE3 } from '../enums/ResourceTypes'
    import { OPERATION1, OPERATION2, OPERATION3, OPERATION4 } from '../enums/OperationTypes'
    
    const cases = {
      RESOURCE1: [OPERATION2, OPERATION3, OPERATION4],
      RESOURCE2: [OPERATION1, OPERATION2, OPERATION3],
      RESOURCE3: [OPERATION1, OPERATION2],
      default: []
    }
    
    const operationPerResource = (resource: ResourceTypes): OperationTypes[] => {
      const operations = cases[ressource] || cases['default']
      return operations
    }
    
    export default operationPerResource
    

    这里是an exemple in the typescript playground

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-11
      • 1970-01-01
      • 1970-01-01
      • 2017-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多