打字稿枚举开关不起作用

Typescript enum switch not working

我有以下枚举

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

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

var editMode = EditMode.Edit;

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

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

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

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

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

使用 const:

声明枚举
const enum EditMode {
    View = 0,
    Edit = 1,
    Delete = 2
}

万一其他人在这里结束并且上述选项似乎不是问题,double-check 你所有的 switch 语句都是 breaking/returning! 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');
}

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

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

打字稿 3.6.3

如果您在带类型参数的函数中使用 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

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

var editMode = EditMode.Edit

TypeScript 将类型计算为:

var editMode: 1 = EditMode.Edit

现在,当您将 typescript 知道的值 must 知道的值 1 (EditMode.Edit) 进行比较时must be 0 (EditMode.View),它将所有这些视为类型安全违规。如果变量 editMode 不是 enum,打字稿只会抱怨,但由于它是一个 enum,它在 javascript 中并不存在,打字稿可以控制以实际抛出错误的方式进行转译。
所以你有两个选择。因此,您可以强制 editMode 成为 number 或成为 EditMode(即任何值 EditMode 都可以是,而不仅仅是分配给 EditMode 的值=18=] 变量)。
就个人而言,我更喜欢将其强制转换为 EditMode,因为它感觉类型更安全。

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

switch(+editMode)

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

switch(editMode as EditMode)

随心所欲,但我喜欢明确地说 "this variable is being treated as an EditMode" 而不是 "this variable is supposed to actually be a number, not an Enum"。

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

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

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

}

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

像这样使用它。

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

使用 //@ts-ignore 抑制你可以做:

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