Home > Blockchain >  How to use/create type of array in Typescript
How to use/create type of array in Typescript

Time:12-08

I have a react project, where I am creating a store. Here is the code:

import React, { useReducer, useEffect } from 'react';
import { v4 as uuid } from 'uuid';

import { Movie, MoviesAction } from 'types';
import { getMovies } from 'api/movies';

interface MoviesState {
  movies: Movie[]
  initialized: boolean
}

export function useMoviesCollection(): [MoviesState, React.Dispatch<MoviesAction>] {
  // TODO: Implement all action processing

  const movieReducer = (state: MoviesState, action: MoviesAction): MoviesState => {
    switch (action.type) {
      case 'fetch':
        
          console.log('ss', state)
          // return {...state}
          return { ...state, movies: action.payload };
         
        // return { ...state };

      case 'add':
        return { ...state };

      case 'delete':
        return { ...state };

      case 'rate':
        return { ...state };

      default:
        return state
    }
  };

  const [state, dispatch] = useReducer(movieReducer, {
    movies: [],
    initialized: false,
  });

  useEffect( () => {
    // TODO: Call fetch action
    
     getMovies().then((d)=>{
      console.log('g', d)
         dispatch({
          type: 'fetch',
          payload: {
              data: d
          }
      })
     })
  }, []);

  return [state, dispatch];
}

In my useEffect hook, I'm trying to call an API and then use the Data/result to pass it inside the dispatch as the action's payload. Even though the API call returns the type Movie[] of movie array but when I set it to inside the state, I get this error message:

Type '{ data: Movie[]; }' is missing the following properties from type 'Movie[]': length, pop, push, concat, and 28 more. 

The getMovies API call's implementation is like this:

import { Movie } from "types"

export const getMovies = async (): Promise<Movie[]> => {
    return require('../data/movies.json')
}

The types/interfaces for MovieAction and Movie are declared as:

export interface Movie {
    id: string,
    title: string,
    subtitle: string,
    description: string,
    imageUrl: string,
    ratings: number[]
}

export interface MovieFetchAction {
    type: 'fetch',
    payload: {
        data: Movie[]
    }
}

Can someone tell me what I have got wrong here? I feel I am passing the right type.

CodePudding user response:

You are going to kick yourself:

You are writing

dispatch({
          type: 'fetch',
          payload: {
              data: d
          }
      })

when you should just write

dispatch({
          type: 'fetch',
          payload: d
      })

Incidentally, I would rewrite the whole thing as

  useEffect( () => {
    // TODO: Call fetch action
    const doFetch = async() => {
     const payload = await getMovies();
     console.log('payload', payload)
     dispatch({
          type: 'fetch',
          payload
     });
    };

    doFetch();
  }, []);

Which is (imo) more readable.

One thing you should notice here is the huge advantage that Typescript gives you. If you made the same mistake in Javascript, you would not find out about it until some consumer of the store failed at some point in the future.

CodePudding user response:

The error message state's the obvious error. Your passing payload with type {data:Movie[]} and in your Moviestatethe type of movies is 'Movie[]'.

You need to chain call the data property inside your return to return the correct type.

Use:

return { ...state, movies: action.payload.data };
  • Related