Интеграция Typescript со сложными редукционными действиями и редукторами - PullRequest
3 голосов
/ 03 апреля 2020

В данный момент я новичок в машинописи и пытаюсь объединить его с редукционными действиями и редукторами. Я получаю ошибку прямо сейчас, и я хочу лучший подход к рефакторингу кода. Это был мой метод, и мне нужна помощь.

Действие

import Axios from "axios";

export const fetchTODO = term => async dispatch => {
  dispatch({ type: "FETCH_TODO" });

  try {
    const response = await Axios.get(`/api/TODO/${term}`, {});
    dispatch({
      type: "FETCH_TODO_SUCCESS",
      payload: response.data
    });
  } catch (error) {
    dispatch({ type: "FETCH_TODO_FAILURE", error });
  }
};

Редуктор

const initialState = {
  payload: [],
  isLoading: false,
  error: {}
};

export default (state = initialState, { type, payload, error }) => {
  switch (type) {
    case "FETCH_TODO":
      return { ...state, isLoading: true };

    case "FETCH_TODO_SUCCESS":
      return { ...state, payload, isLoading: false };

    case "FETCH_TODO_FAILURE":
      return { ...state, error: error, isLoading: false };

    default:
      return state;
  }
};

Машинописный код

types.t c

export enum ActionTypes {
  fetchTodos,
  fetchTodosSuccess,
  fetchTodosFailure
}

Действие

import { ActionTypes } from "./types";
import Axios from "axios";
import { Dispatch } from "redux";

export interface Todo {
  id: number;
  title: string;
  completed: boolean;
}

export interface FetchTodoAction {
  type: ActionTypes;
  payload?: Todo[];
  error?: object;
}

export const fetchTransaction = (term: string) => async (
  dispatch: Dispatch
) => {
  dispatch({ type: ActionTypes.fetchTodos });

  try {
    const response = await Axios.get<Todo[]>(
      `https://jsonplaceholder.typicode.com/todos/`
    );
    dispatch<FetchTodoAction>({
      type: ActionTypes.fetchTodosSuccess,
      payload: response.data
    });
  } catch (error) {
    dispatch({ type: ActionTypes.fetchTodosFailure, error });
  }
};

StateInterface объект

export interface StateInterface {
  payload?: Todo[];
  isLoading: boolean;
  error?: object;
}

Редуктор


import { Todo, FetchTodoAction } from "./../actions/index";
import { ActionTypes } from "../actions/types";
import { StateInterface } from ".";

const initialState = {
  payload: [],
  isLoading: false,
  error: {}
};

export const todosReducer = (
  state: StateInterface = initialState,
  { type, payload, error }: FetchTodoAction
) => {
  switch (type) {
    case ActionTypes.fetchTodos:
      return { ...state, isLoading: true };

    case ActionTypes.fetchTodosSuccess:
      return { ...state, payload, isLoading: false };

    case ActionTypes.fetchTodosFailure:
      return { ...state, error: error, isLoading: false };

    default:
      return state;
  }
};

Я получил эту ошибку после кода, и любой может подсказать лучшую реализацию

(alias) const todosReducer: (state: StateInterface | undefined, { type, payload, error }: FetchTodoAction) => StateInterface
import todosReducer
No overload matches this call.
  Overload 1 of 3, '(reducers: ReducersMapObject<StateInterface, any>): Reducer<CombinedState<StateInterface>, AnyAction>', gave the following error.
    Argument of type '{ todos: (state: StateInterface | undefined, { type, payload, error }: FetchTodoAction) => StateInterface; }' is not assignable to parameter of type 'ReducersMapObject<StateInterface, any>'.
      Object literal may only specify known properties, and 'todos' does not exist in type 'ReducersMapObject<StateInterface, any>'.

пожалуйста, Очень жду поддержки и заранее благодарю

1 Ответ

2 голосов
/ 03 апреля 2020

Эта ошибка выдается, потому что TypeScript препятствует тому, чтобы у вас был аргумент, чтобы быть опцией (то есть undefined), когда требуются следующие аргументы (то есть, не undefined).

Вы можете исправить это, выведя тип от initialState.

Например. const initialState: StateInterface { ... }

Теперь вам больше не нужно устанавливать тип для состояния в аргументах вашего редуктора, поскольку TypeScript будет знать, что это значение всегда будет определено.

Например. export const todosReducer = (state = initialState, ...) => { ... }

Следовательно, измените свой код редуктора на следующее:

import { Todo, FetchTodoAction } from "./../actions/index";
import { ActionTypes } from "../actions/types";
import { StateInterface } from ".";

// Define initial state type here
const initialState: StateInterface = {
  payload: [],
  isLoading: false,
  error: {}
};

export const todosReducer = (
  state = initialState, // state type is now inferred from initialState
  { type, payload, error }: FetchTodoAction
) => {
  switch (type) {
    case ActionTypes.fetchTodos:
      return { ...state, isLoading: true };

    case ActionTypes.fetchTodosSuccess:
      return { ...state, payload, isLoading: false };

    case ActionTypes.fetchTodosFailure:
      return { ...state, error, isLoading: false };

    default:
      return state;
  }
};

РЕДАКТИРОВАТЬ: Если это все еще не работает, тогда измените { type, payload, error }: FetchTodoAction на { type, payload, error }: FetchTodoAction | undefined должен сделать свое дело.

...