在redux guide to typescript之后,我为减速器想到了以下代码。但是,Typescript无法在switch case语句上推断正确的类型。
通过阅读this answer及其指向的typescript docs,我能够使用接口类型变量上的字符串文字使它工作。但是我不想在其中使用文字,因为我将动作字符串导出到Actions变量中,如下面的代码所示。
要使它像redux指南那样工作,我缺少什么?
export const Action = {
action1:'ACTION1',
action2:'ACTION2'
}
interface actionType1 {
type: typeof Action.action1,
stringPayload:string
}
interface actionType2 {
type: typeof Action.action2,
objectPayload:{
str: string
}
}
type actionType = actionType1 | actionType2;
interface stateType {
str:string,
}
const defaultState = {
str:''
};
const reducer = ( state = defaultState, action:actionType) : stateType => {
switch(action.type){
case Action.action1:
return {
str:action.stringPayload //stringPayload appears as error
}
/*
[ts]
Property 'stringPayload' does not exist on type 'actionType'.
Property 'stringPayload' does not exist on type 'actionType2'.
*/
case Action.action2:
return action.objectPayload //objectPayload appears as error
/*
[ts]
Property 'objectPayload' does not exist on type 'actionType'.
Property 'objectPayload' does not exist on type 'actionType1'
*/
default:
return state
}
}
答案 0 :(得分:1)
它编译出错,因为reducer中的Action.action1
,Action.action2
解析为字符串。如果将鼠标悬停在Action
类型上,则可以看到其解释:
const Action: {
action1: string;
action2: string;
}
您还可以通过编写以下代码进行测试
type TestAction2Prop = typeof Action.action2 // type TestAction2Prop = string
要解决此问题,您必须明确地告诉TypeScript,不得将Action
的文字类型扩展(例如,将'ACTION1'转换为字符串)。您可以通过const assertions来做到这一点:
export const Action = {
action1:'ACTION1',
action2:'ACTION2'
} as const
答案 1 :(得分:0)
尝试一下:
export class Action {
static action1:'ACTION1';
static action2:'ACTION2';
}
interface actionType1 {
type: typeof Action.action1,
stringPayload:string
}
interface actionType2 {
type: typeof Action.action2,
objectPayload:{
str: string
}
}
type actionType = actionType1 | actionType2;
interface stateType {
str:string,
}
const defaultState = {
str:''
};
const reducer = ( state = defaultState, action:actionType) : stateType => {
switch(action.type){
case Action.action1:
return {
str:action.stringPayload //stringPayload appears as error
}
/*
[ts]
Property 'stringPayload' does not exist on type 'actionType'.
Property 'stringPayload' does not exist on type 'actionType2'.
*/
case Action.action2:
return action.objectPayload //objectPayload appears as error
/*
[ts]
Property 'objectPayload' does not exist on type 'actionType'.
Property 'objectPayload' does not exist on type 'actionType1'
*/
default:
return state
}
}