在TypeScript中切换为特定类型

Vla*_*tko 7 typescript

我有一个界面Action

interface Action {}
Run Code Online (Sandbox Code Playgroud)

并实现一个Action SpecificAction

class SpecificAction implements Action {
   payload?: Any
}
Run Code Online (Sandbox Code Playgroud)

在TS中是否可以构造一个切换运算符,如下所示:

let action: Action
switch (action) {
   case SpecificAction: //it works
       console.log(action.payload) // it doesn't 
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下是否有可能知道该动作已经是SpecificAction类型?

Dan*_*aru 25

目前看起来有几个选择,所有这些都有一些缺点

interface Action {}

class SpecificAction implements Action {
  kind: "specific";
  payload?: any;
}

class ToggleAction implements Action {
  kind: "toggle";
  toggle: boolean;
}

let action: SpecificAction | ToggleAction;
switch (action.kind) {
  case "specific":
    console.log(action.payload) // it works 
    break;
  case "toggle":
    console.log(action.toggle) // it works 
    break;        
}
Run Code Online (Sandbox Code Playgroud)
  • User-Defined Type Guards docs stackblitz,但你需要 if 语句而不是 switch
interface Action {}

class SpecificAction implements Action {
  payload?: any;
}

class ToggleAction implements Action {
  toggle: boolean;
}

let isSpecific = (p: any): p is SpecificAction => !!p.payload
let isToggle = (p: any): p is ToggleAction => !!p.toggle

let action: Action;
if (isSpecific(action)) {
  console.log(action.payload) // it works 
} else if (isToggle(action)) {
  console.log(action.toggle) // it works 
}
Run Code Online (Sandbox Code Playgroud)
interface Action { }

class SpecificAction implements Action {
  payload?: any;
}

class ToggleAction implements Action {
  toggle: boolean;
}

switch (action.constructor) {
  case SpecificAction:
    console.log((<SpecificAction>action).payload) // it kinda works 
    break;
  case ToggleAction:
    console.log((<ToggleAction>action).toggle) // it kinda works 
    break;
  }
Run Code Online (Sandbox Code Playgroud)


pus*_*kin 8

您最好使用if带有类型保护的语句。

let action: Action = ...;
if (isSpecificAction(action)) {
    console.log(action.payload);
}

function isSpecificAction(action: any): action is SpecificAction {
    return action.payload;
}
Run Code Online (Sandbox Code Playgroud)

归根结底,TypeScript 仍然是 JavaScript,并且该switch语句被转换为常规 JS switch

switch 语句首先计算其表达式。然后,它查找第一个 case 子句,其表达式的计算结果与输入表达式的结果相同(使用严格比较,===)

所以在你的情况下:

interface Action {}
class SpecificAction implements Action {
   payload?: any
}

let action: Action
switch (action) {
   case SpecificAction: //it works
       console.log(action.payload) // it doesn't 
}
Run Code Online (Sandbox Code Playgroud)

action将进行评估并与班级 SpecificAction进行比较。据推测,action是一个实例SpecificAction或实现该Action接口的某个对象)。

使用switch,您可以这样做:

let a: Action = new SpecificAction();
let b: Action = a;

switch (a) {
    case b:
        console.log("Worked");
}
Run Code Online (Sandbox Code Playgroud)

对该表达式a进行求值并与表达式进行比较b(和a === b,因此我们点击console.log),但这显然不是您想要的。

如果您想检查实例是否属于特定类型(re:类),那么您应该使用类型保护。Aswitch/case是错误的构造。


或者,为什么不使用instanceof

interface Action { };
class SpecificAction implements Action {}
class NotSpecificAction implements Action {}

let action: Action = new SpecificAction();
console.log(action instanceof SpecificAction); // true
console.log(action instanceof NotSpecificAction); // false
Run Code Online (Sandbox Code Playgroud)

  • 这是否没有回答问题,或者存在技术错误?(对否决票感到好奇) (2认同)