我有一个界面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
类型?
答案 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
进行比较。据推测,action
是SpecificAction
的实例(或实现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)
目前看来,有一些选择,所有这些都有一些缺点
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;
}
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;
}