在 useReducer 钩子、TypeScript 中重载有效负载

Pau*_*sal 0 javascript typescript use-reducer

这是我在函数组件中初始化的 useReducer 钩子。在listReducer函数中,我想创建用户==>我分配给状态用户类型的数组。所以,在有效负载中我必须有User[]. 但是,当我通过 _id 删除 ==> 仅其中单个元素时(必须使用私有变量来解决),我必须将字符串类型传递给有效负载。

type State = {
  list: User[];
}

const initialListState: State = {
  list: [],
};

enum ActionKind {
  CREATE = 'CREATE',
  DELETE = 'DELETE',
}

type Action = {
  type: ActionKind,
  payload: User[] | string;
}

function listReducer(state: State, action: Action): State {
  const { type, payload } = action;
  switch (type) {
    case ActionKind.CREATE:
      return { list: action.payload };
    case ActionKind.DELETE:
      return {
        list: state.list.filter((el) => el._id !== action.payload._id),
      };
    default:
      return state;
  }
}

export const DashBoard = () => {
  const [state, dispatch] = useReducer(listReducer, initialListState);

  useEffect(() => {
    if (allUsers && allUsers.length > 0) {
      dispatch({ type: ActionKind.CREATE,
        payload: allUsers,
      });
    }
  }, [allUsers]);
Run Code Online (Sandbox Code Playgroud)

在 useEffect 中,当 allUsers(type User[]) 分配给数组时,我将 allUsers 传递给有效负载。这是我在当前代码中遇到的错误:TS2339: Property 'list' does not exist on type 'string | User[]'. 这是用户界面

export interface User {
  _id: string;
  name: string;
  age: string;
  email: string;
  password: string;
  isAdmin: boolean;
}
Run Code Online (Sandbox Code Playgroud)

我尝试将有效负载作为具有单独属性的对象id-string 和list-User[]

type Action = {
  type: ActionKind,
    payload: {
      list: User[],
      id: string,
  },
}

function listReducer(state: State, action: Action): State {
  const { type, payload } = action;
  switch (type) {
    case ActionKind.CREATE:
      return { list: action.payload.list };
 ...
Run Code Online (Sandbox Code Playgroud)

和里面的useEffect

dispatch({ type: ActionKind.CREATE,
          payload: {
            list: allUsers,
          },
        
      });
Run Code Online (Sandbox Code Playgroud)

但这样payload.list和payload.id是必填字段 - 如果类型声明我将它们设置为可选字段,则会出现多个错误,例如==>

type Action = {
  type: ActionKind,
    payload: {
      list?: User[],
      id?: string,
  },
}
Run Code Online (Sandbox Code Playgroud)

那么list是 User[] | 未定义并且id是字符串 | 不明确的

我该如何做才正确?会很高兴得到任何帮助

小智 6

我喜欢像与打字稿一样实现减速器,如下所示:

type State = {
  x: number
  y: string
  z: Array<string>
}

type Payload1 = {
  x: number
  y: string
}
type Payload2 = {
  z: Array<string>
}

type Action
  = { type: "action1"; payload: Payload1 }
  | { type: "action2"; payload: Payload2 }


function reducer(state: State, action: Action): State {
  switch (action.type) {
    case "action1":
      return { ...state, x: action.payload.x, y: action.payload.y }
    case "action2":
      return { ...state, z: action.payload.z }
  }
  throw new Error("unreachable");
}

Run Code Online (Sandbox Code Playgroud)

一切正常。然后您可以将此作为参考并创建类似的内容:

type Action = { 
  type: ActionType.CREATE
  payload: User[]
} | {
  type: ActionType.DELETE
  payload: number
}
Run Code Online (Sandbox Code Playgroud)