【问题标题】:Typescript in redux reducerredux reducer 中的打字稿
【发布时间】:2019-12-11 10:35:51
【问题描述】:

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

【问题讨论】:

    标签: typescript redux


    【解决方案1】:

    试试这个:

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

    【讨论】:

      【解决方案2】:

      它编译时出错,因为 reducer 中的 Action.action1Action.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
      

      Playground

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-09-29
        • 2019-04-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-09
        相关资源
        最近更新 更多