【问题标题】:Typescript enum switch not working打字稿枚举开关不起作用
【发布时间】:2015-03-01 02:18:57
【问题描述】:

我有以下枚举

enum EditMode {
    View = 0,
    Edit = 1,
    Delete = 2
}

假设我有一个枚举类型的变量

var editMode = EditMode.Edit;

为什么下面的代码不起作用(直接进入默认)?

switch (editMode) {
    case EditMode.Delete:
        ...
        break;
    case EditMode.Edit:
        ...
        break;
    default:
        ...
        break;
    }

【问题讨论】:

  • 此代码在 TypeScript Playground 中工作。您确定您的脚本加载顺序正确吗?
  • 我还可以确认它可以在 Playground 中使用。
  • 是的,看来问题不在于代码本身。出于某种原因,我的代码分配的不是枚举后面的数字,而是与数字关联的字符串,例如而不是 1(编辑)“1”。为什么我不明白。
  • 用 if/else 替换它,它应该可以工作。 TypeScript 中有很多打字问题/功能。例如。那个 - github.com/Microsoft/TypeScript/issues/8618
  • 实际上这段代码在 Typescript 操场上不起作用...editmode DELETE 无法与editmode EDIT 相提并论

标签: enums switch-statement typescript


【解决方案1】:

我找到了为什么我会发生。代码中的某处有一个激活函数(我使用的是 durandal),它将这个枚举作为字符串传递(该函数将参数标记为枚举,但它仍然是一个字符串)。这就是我的 switch 语句失败的原因。我只是将值转换为数字,现在一切都按预期工作。还是谢谢

【讨论】:

  • 这也是我的问题。我的构造函数有一个 Enum 类型的参数,但外部调用者正在传递一个字符串。我将构造函数参数改为字符串类型,并使用 EnumType[parameter] 将其转换为枚举。
【解决方案2】:

我也有这个问题。绕过它的简单方法:在开关中的变量之前添加一个+ 符号,即

switch (+editMode) {
    case EditMode.Delete:
        ...
        break;
    case EditMode.Edit:
        ...
        break;
    default:
        ...
        break;
    }

【讨论】:

  • 这似乎是修复打字稿故障/错误的唯一方法。
  • 所以 + 会将其更改为数字,这似乎有效。我认为这似乎不是一个很好的解决方案。我还尝试将我的枚举中的第一项分配给 0,但它没有帮助。看起来像一个错误。
  • + 是一种将其强制转换为数字的 hack。根据现代 Typescript 版本,我的回答是正确的。
【解决方案3】:

使用const 声明您的枚举:

const enum EditMode {
    View = 0,
    Edit = 1,
    Delete = 2
}

【讨论】:

  • 这并不能解决我的问题。
【解决方案4】:

如果其他人在这里结束并且上述选项似乎不是问题,请仔细检查您的所有 switch 语句是否正在中断/返回! Typescript 编译器足够聪明,可以看到如果您的 case 级联到另一个,您正在比较的值可能永远不会达到您期望的情况。

let handlerName;

switch(method){
  case 'create':
    handlerName = 'createHandler';
    break;
  case 'update';
    handlerName = 'updateHandler';
    // Here is where the forgotten break would go
  default:
    throw new Error('Unrecognized Method');
}

switch(handlerName){
  case 'createHandler':
    ...
    break;
  case 'updateHandler':
    // You will see an error on this case because
    // the compiler knows that execution will never
    // arrive here with handler === 'updateHandler'
  default:
    throw new Error('Unrecognized Handler');
}

【讨论】:

    【解决方案5】:

    将您的 EditMode 枚举定义更改为:

    enum EditMode {
        View = "View",
        Edit = "Edit",
        Delete = "Delete"
    }
    

    打字稿 3.6.3

    【讨论】:

    • 这对我来说比基于整数的解决方案更有效,因为我的对象来自提供 JSON 的 REST 服务,其中枚举值在文本值的位置,因此我无法将数字分配给他们或者我会破坏序列化/反序列化过程。
    【解决方案6】:

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

    例子:

    enum EditMode {
        View,
        Edit,
        Delete,
    }
    
    function testSwitch(editMode: EditMode) {
        switch(editMode) {
            case EditMode.Delete:
                console.log("delete");
                break;
            case EditMode.Edit:
                console.log("edit");
                break;
            default:
                console.log("default");
                break;
        }
    }
    
    testSwitch(EditMode.Edit)
    

    将编译?并输出edit?

    【讨论】:

      【解决方案7】:

      这里的问题与打字稿的(numeric) literal types 有关。当你做这个作业时:

      var editMode = EditMode.Edit
      

      TypeScript 将类型评估为:

      var editMode: 1 = EditMode.Edit
      

      现在,当您将 typescript 知道 必须1 (EditMode.Edit) 的值与它知道 必须0 (@ 987654327@),它认为这一切都是违反类型安全的。如果变量editMode 不是enum,typescript 只会抱怨,但由于它是一个enum,它在javascript 中并不真正存在,typescript 可以通过它实际抛出的方式控制转译一个错误。
      所以你有2个选择。因此,您可以强制 editMode 成为 number 或成为 EditMode (即允许任何值 EditMode,而不仅仅是分配给变量 editMode 的值)。
      就个人而言,我更喜欢将其强制为 EditMode,因为它感觉更安全。

      要走数字路线,您可以执行以下操作,前面提到过:

      switch(+editMode)
      

      要走EditMode 路线(我推荐),您可以将它传递给前面提到的函数,但有时不编写函数会更简洁一些。如果这里是这种情况,那么您可以再次强制 switch 语句中的类型:

      switch(editMode as EditMode)
      

      随你喜欢,但我只是喜欢明确地说“这个变量被视为EditMode”而不是“这个变量实际上应该是number,而不是Enum ”。

      【讨论】:

        【解决方案8】:

        TypeScript 版本 3.7.5

        这段代码对我有用

        enum Seasons {
            Winter,
            Spring,
            Summer,
            Autum
          }
        
        switch (+Seasons.Winter) {
            case Seasons.Winter:
                console.log('weather is cold');
                break;
            case Seasons.Spring:
                console.log('weather is spring');
                break;
            case Seasons.Summer:
                console.log('weather is summer');
                break;
            default:
                break;
        }
        

        或者您可以声明一个常量并用作 switch 语句的参数

        const season: Seasons = Seasons.Winter
        switch (+season) {
            case Seasons.Winter:
                console.log('weather is cold');
                break;
            case Seasons.Spring:
                console.log('weather is spring');
                break;
            case Seasons.Summer:
                console.log('weather is summer');
                break;
            default:
                break;
        }
        

        【讨论】:

        • 如果没有加号 ('+'),它将无法工作。它是如何解决问题的?
        • d***,救命稻草。有什么文件吗?
        【解决方案9】:

        在我的例子中,我在一个条件中使用了开关,它把枚举强制转换为一个值:

        enum A {
            VAL_A,
            VAL_B,
            VAL_C
        }
        interface ia {
            maybe?: A
        }
        const o: ia = {maybe: 0}
        if(o.maybe){ //<-- o.maybe is not falsey (thus, is not 0)
            switch(o.maybe) {
                case A.VAL_A: //<-- Error! we know that o.maybe is not 0. Its VAL_B | VAL_C
                break;
            }
        
        }
        
        

        【讨论】:

          【解决方案10】:

          如果枚举是在单独的 typescript 文件中定义的,请确保它被标记为“export”,并且在您引用它的 typescript 文件的顶部正确导入它。

          【讨论】:

            【解决方案11】:

            像这样使用它。

            const enum OperationsType{
                CREATE="CREATE",
                DELETE="DELETE",
                UPDATE="UPDATE"
            }
            

            【讨论】:

              【解决方案12】:

              使用//@ts-ignoresuppress 你可以这样做:

              //@ts-ignore
              switch (EditMode[editMode] as EditMode) {
                  case EditMode.Delete:
                      ...
                      break;
                  case EditMode.Edit:
                      ...
                      break;
                  default:
                      ...
                      break;
                  }
              }
              

              【讨论】:

                猜你喜欢
                • 2020-04-30
                • 1970-01-01
                • 1970-01-01
                • 2020-01-29
                • 2019-09-25
                • 2017-05-09
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多