Juras Rabačauskas
Juras Rabačauskas

Reputation: 13

Typescript React Redux - property does not exist on Action type

i am new to typescript with React and Redux, I can't wrap my head around why I am getting this error. I've started to add types to react-redux code today, from a video called How to use Typescript with Redux on Youtube

Property 'movies' does not exist on type 'UpcomingMovieActionTypes'.
Property 'movies' does not exist on type 'FetchUpcomingMoviesStartAction' TS2339
upcoming: {
  ...state.upcoming
  movies: action.movies,
  fetching: false
}};

Reducer:

import { ACTION_TYPES } from '../../types/Actions.type';
import { Media } from '../../types/Media.type';
import { UpcomingMoviesActionTypes } from '../../types/Actions.type';

interface UpcomingMoviesState {
    upcoming: {
        movies: Media[];
        fetching: boolean;
        errorMessage: string;
    },
    key: string;
}

const INITIAL_STATE: UpcomingMoviesState = {
    upcoming: {
        movies: [],
        fetching: false,
        errorMessage: ''
    },
    key: '78dcec9ee90f01f2415dd96af2cebd76'
};

const movieReducer = (state = INITIAL_STATE, action: UpcomingMoviesActionTypes): UpcomingMoviesState => {
    switch (action.type) {
        case ACTION_TYPES.FETCH_UPCOMING_MOVIES_START:
            return {
                ...state,
                upcoming: {
                    ...state.upcoming,
                    movies: [ ...state.upcoming.movies ],
                    fetching: true
                }
            };
        case ACTION_TYPES.FETCH_UPCOMING_MOVIES_SUCCESS:
            return {
                ...state,
                upcoming: {
                    ...state.upcoming,
                    movies: action.movies,
                    fetching: false
                }
            };
        case ACTION_TYPES.FETCH_UPCOMING_MOVIES_FAILURE: return state;
        default: return state;
    }
};

export default movieReducer;

Actions:

import { ACTION_TYPES, AppActions } from '../../types/Actions.type';
import { Media } from '../../types/Media.type';
import axios from 'axios';
import { Dispatch } from 'redux';

export const fetchUpcomingMoviesStart = (): AppActions => ({
    type: "FETCH_UPCOMING_MOVIES_START"
});

export const fetchUpcomingMoviesSuccess = (movies: Media[]): AppActions => ({
    type: ACTION_TYPES.FETCH_UPCOMING_MOVIES_SUCCESS,
    movies
});

export const fetchUpcomingMoviesFailure = (errorMessage: string): AppActions => ({
    type: ACTION_TYPES.FETCH_UPCOMING_MOVIES_FAILURE,
    errorMessage
});

export const fetchUpcomingMoviesAsync = () => { 
    return (dispatch: Dispatch<AppActions>) => { 
        dispatch(fetchUpcomingMoviesStart());
        axios.get('https://api.themoviedb.org/3/movie/upcoming?api_key=78dcec9ee90f01f2415dd96af2cebd76')
             .then((response: any) => dispatch(fetchUpcomingMoviesSuccess(response.data.results)))
             .catch((error: string) => dispatch(fetchUpcomingMoviesFailure(error)));
    }
};

Action Types:

import { Media } from './Media.type';

export const ACTION_TYPES = {
    FETCH_UPCOMING_MOVIES_START: 'FETCH_UPCOMING_MOVIES_START',
    FETCH_UPCOMING_MOVIES_SUCCESS: 'FETCH_UPCOMING_MOVIES_SUCCESS',
    FETCH_UPCOMING_MOVIES_FAILURE: 'FETCH_UPCOMING_MOVIES_FAILURE'
}

export interface FetchUpcomingMoviesStartAction {
    type: typeof ACTION_TYPES.FETCH_UPCOMING_MOVIES_START;
}

export interface FetchUpcomingMoviesSuccessAction {
    type: typeof ACTION_TYPES.FETCH_UPCOMING_MOVIES_SUCCESS;
    movies: Media[];
}

export interface FetchUpcomingMoviesFailureAction {
    type: typeof ACTION_TYPES.FETCH_UPCOMING_MOVIES_FAILURE;
    errorMessage: string;   
}

export type UpcomingMoviesActionTypes = FetchUpcomingMoviesStartAction | FetchUpcomingMoviesSuccessAction | FetchUpcomingMoviesFailureAction;

export type AppActions = UpcomingMoviesActionTypes;

If i change the action type in the reducer from UpcomingMoviesActionTypes to any it works fine.

Upvotes: 0

Views: 1114

Answers (1)

R&#233;mi Doreau
R&#233;mi Doreau

Reputation: 252

The thing was that your action types were not typed as your type (for example FETCH_UPCOMING_MOVIES_START) but as a string.
You should define your action types like:

export const ACTION_TYPES = {
  FETCH_UPCOMING_MOVIES_START: "FETCH_UPCOMING_MOVIES_START" as const,
  FETCH_UPCOMING_MOVIES_SUCCESS: "FETCH_UPCOMING_MOVIES_SUCCESS" as const,
  FETCH_UPCOMING_MOVIES_FAILURE: "FETCH_UPCOMING_MOVIES_FAILURE" as const
};

or as an enum:

export enum ACTION_TYPES {
  FETCH_UPCOMING_MOVIES_START = "FETCH_UPCOMING_MOVIES_START",
  FETCH_UPCOMING_MOVIES_SUCCESS = "FETCH_UPCOMING_MOVIES_SUCCESS",
  FETCH_UPCOMING_MOVIES_FAILURE = "FETCH_UPCOMING_MOVIES_FAILURE"
}

or as single action types:

export const FETCH_UPCOMING_MOVIES_START = "FETCH_UPCOMING_MOVIES_START";
export const FETCH_UPCOMING_MOVIES_SUCCESS = "FETCH_UPCOMING_MOVIES_SUCCESS";
export const FETCH_UPCOMING_MOVIES_FAILURE = "FETCH_UPCOMING_MOVIES_FAILURE";

Upvotes: 1

Related Questions