Свойство isFetching не существует для типа never, но работает, когда объект распространяется. - PullRequest
0 голосов
/ 06 мая 2020

Почему я получаю эту ошибку Typescript Property 'isFetching' does not exist on type 'never'.ts(2339) для фрагмента ниже

const mapStateToProps = (
  state: AppState,
  ownProps: AuthenticationPageProps
): IMapStateToProps => ({
  isFetching: state.authentication.isFetching,
  user: state.authentication.user
});

Но если я разверну объект, он работает, как ожидалось?

const mapStateToProps = (
  state: AppState,
  ownProps: AuthenticationPageProps
): IMapStateToProps => {
  const { isFetching, user } = state.authentication;
  return { isFetching, user };
};

Этот фрагмент работает как и ожидалось:

const mapStateToProps = (
  state: AppState,
  ownProps: AuthenticationPageProps
): IMapStateToProps => ({
  isFetching: state.authentication["isFetching"],
  user: state.authentication["user"],
});

Ниже показано, что я вижу в своих инструментах разработчика, когда печатаю props

enter image description here

Вот интерфейс для IMapStateToProps

interface IMapStateToProps {
  isFetching: boolean;
  user: User;
}

Дополнительные интерфейсы

export interface AuthenticationState {
  isFetching: boolean;
  user: User;
  errors: Error[];
}

export interface User {
  email?: string;
}

export interface Error {
  message: string;
  status: string;
}

export const rootReducer = combineReducers({
  authentication: authenticationReducer, // authenticationReducer returns type: AuthenticationState
});

export type AppState = ReturnType<typeof rootReducer>;

Редуктор:

import {
  LOGOUT_SUCCESS,
  LOGOUT_REQUEST,
  LOGOUT_FAILURE,
  LOGIN_FAILURE,
  LOGIN_SUCCESS,
  LOGIN_REQUEST,
  REGISTER_FAILURE,
  REGISTER_SUCCESS,
  REGISTER_REQUEST,
  AuthenticationState,
  AuthenticationActionTypes,
  CHECK_LOGGED_IN_REQUEST,
  CHECK_LOGGED_IN_SUCCESS,
  CHECK_LOGGED_IN_FAILURE,
} from "../../types/Authentication";

export const AuthenticationReducerDefaultState = {
  errors: [],
  isFetching: false,
  user: {},
};

export const authenticationReducer = (
  state = AuthenticationReducerDefaultState,
  action: AuthenticationActionTypes
): AuthenticationState => {
  switch (action.type) {
    case LOGIN_REQUEST:
    case LOGOUT_REQUEST:
    case REGISTER_REQUEST:
    case CHECK_LOGGED_IN_REQUEST:
      return {
        ...state,
        isFetching: true,
      };
    case LOGIN_SUCCESS:
      return {
        ...state,
        isFetching: false,
        user: action.user,
      };
    case LOGOUT_SUCCESS:
      return { ...state, isFetching: false };
    case CHECK_LOGGED_IN_SUCCESS:
      return { ...state, isFetching: false };
    case REGISTER_SUCCESS:
      return { ...state, isFetching: false };
    case LOGIN_FAILURE:
      return { ...state, isFetching: false };
    case LOGOUT_FAILURE:
      return { ...state, isFetching: false };
    case REGISTER_FAILURE:
      return { ...state, isFetching: false };
    case CHECK_LOGGED_IN_FAILURE:
      return { ...state, isFetching: false };
    default:
      return state;
  }
};

1 Ответ

1 голос
/ 06 мая 2020

Ваше начальное состояние не того же типа, что и возвращенное состояние.

export interface AuthenticationState {
  isFetching: boolean;
  user: User;
  errors: Error[];
}

export const AuthenticationReducerDefaultState = {
  errors: [], //Type never
  isFetching: false,
  user: {}, //Type {} not type User
};

Вы можете исправить это с помощью:

export interface AuthenticationState {
  isFetching: boolean;
  user: User | {}; //Note the union type 
  errors: Error[];
}

export const AuthenticationReducerDefaultState = <AuthenticationState>{
  errors: [], 
  isFetching: false,
  user: {},
};


//Also should freeze the state as you would not want accidental mutations. 
export const AuthenticationReducerDefaultState = Object.freeze<AuthenticationState>({
  errors: [], 
  isFetching: false,
  user: {},
});
...