簡體   English   中英

Typescript 減速機的開關盒類型保護不適用於 object 擴展

[英]Typescript reducer's switch case typeguard doesn't work with object spread

我有一個減速器,它根據action.type執行不同的操作,某些操作的操作負載不同。

    export enum ActionType {
      UpdateEntireState = "UPDATE_ENTIRE_STATE",
      UpdateStateItem = "UPDATE_STATE_ITEM"
    }
    
    type TypeEditData = {
      id: string;
      name: string;
      surname: string;
      age: number;
    };
    
    export type State = TypeEditData[];
    export type Action = UpdateEntireState | UpdateStateItem;
    
    type UpdateEntireState = {
      type: ActionType.UpdateEntireState;
      payload: State;
    };
    
    type UpdateStateItem = {
      type: ActionType.UpdateStateItem;
      payload: { id: string; data: TypeEditData };
    };
    
    export function reducer(state: State, action: Action): State {
      const { type, payload } = action;
    
      switch (type) {
        case ActionType.UpdateEntireState: {
          return [...payload];
        }
        case ActionType.UpdateStateItem: {
          const person = state.filter((item) => item.id === payload.id);
          return [...state, person[0]];
        }
        default: {
          throw Error("Wrong type of action!");
        }
      }
    }

此代碼不起作用,錯誤會說我的操作負載可以是State{ id: string; data: TypeEditData } { id: string; data: TypeEditData } 但是,如果我像這樣使用點符號訪問開關盒內的有效負載屬性

return [...action.payload];

不會有任何錯誤,類型保護會正常工作。 如何const { type, payload } = action; 在類型方面與action.typeaction.payload不同,為什么 typeguard 不能使用擴展語法?

TS 版本 - 4.3.4

問題是您在action上可用類型信息之前定義了payload ,因此它具有聯合類型

State | {
    id: string;
    data: TypeEditData;
};

在每個 case 語句中定義一個局部變量或簡單地使用action.payload ,編譯器就知道它的類型:

export function reducer(state: State, action: Action): State {
  // const { type, payload } = action;

  switch (action.type) {
    case ActionType.UpdateEntireState: {
      return [...action.payload];
    }
    case ActionType.UpdateStateItem: {
      const person = state.filter((item) => item.id === action.payload.id);
      return [...state, person[0]];
    }
    default: {
      throw Error("Wrong type of action!");
    }
  }
}

變量類型在聲明時顯式建立(例如const a: string )或在初始化時隱式建立(例如a = 4 )。 隨后的類型保護構造不用於重新評估變量的類型。 相反,由於此時已經定義了變量的類型,因此該類型用於驗證后面的構造是否對變量有效。

Action 接口默認帶有 type 屬性。

export interface Action {
    type: string;
}

如果您可以擴展 Action 接口以將有效負載添加為對象數組,那么 typescript 不會向您拋出錯誤。 像這樣的東西,在你的減速機 function 你可以像這樣使用

interface CustomAction extends Action{
    payload: Array<any>
}


export function reducer(state: State, action: CustomAction): State {

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM