在TypeScript中切换特定类型

时间:2018-06-09 13:29:01

标签: typescript

我有一个界面Action

interface Action {}

Action SpecificAction的实现:

class SpecificAction implements Action {
   payload?: Any
}

在TS中是否可以构造一个开关操作符,如下所示:

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

在这种情况下是否可以知道该操作已经是SpecificAction类型?

3 个答案:

答案 0 :(得分:2)

我认为使用switch语句进行类型检查的愿望是可读性。首先,第一个解决方案提供了所有本机打字稿解决方案,但是缺点很烦人,我将提供的解决方案更好。代替使用switch es,使用标记的语句。例如,请考虑以下示例:

const t = [];
typecheck: {
    if (t instanceof Array) {
        console.log("true")
        break typecheck;
    }
    if (t instanceof Object) {
        console.log("shouldn't appear")
        break typecheck;
    }
}

它的工作原理与切换一样好,但是打字稿可以使类型专门化,这还带来了额外的好处。

答案 1 :(得分:1)

最好使用带有挡板的if语句。

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

function isSpecificAction(action: any): action is SpecificAction {
    return action.payload;
}

在一天结束时,TypeScript仍然是JavaScripty,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 
}

action将被评估并与 SpecificAction进行比较。据推测,actionSpecificAction实例(或实现Action接口的某个对象)。

使用switch,您可以执行此操作:

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

switch (a) {
    case b:
        console.log("Worked");
}

评估表达式a并将其与表达式b(和a === b进行比较,因此我们点击console.log),但这显然不是什么你正在寻找。

如果要检查实例是否属于特定类型(re:class),则应使用类型保护。 switch/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

答案 2 :(得分:1)

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

  • 有区别的工会docs stackblitz,但您需要专用的属性作为区分符
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;        
}
  • 用户定义的类型防护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 
}
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;
  }