You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript报错Property 'original_title' does not exist on type 'string'如何解决

问题排查与修复

存在的问题

  • 类型定义错误:IMovieState里的movie字段定义为string[],但实际TMDB返回的是包含original_title等属性的电影对象数组,同时Action的payload类型也错误定义为string
  • Reducer字段拼写错误:更新state时写错字段名,原state字段是movie,返回时写为movies,导致数据没有正确存入对应字段
  • useSelector使用错误:useSelector接收的参数是整个Redux根state,不是单个reducer的IMovieState类型
  • 接口数据处理错误:TMDB接口返回的电影列表存放在res.data.results字段,直接传递res.data会拿到包含分页信息的外层对象,不是电影数组
  • 数组合并逻辑错误:Reducer中更新数组时未展开payload,会把整个数组作为单个元素存入目标数组
  • HTML结构不规范:li标签没有外层ul/ol包裹,同时缺少遍历必填的key属性

修复后代码

1. 定义公共电影类型

新建types.ts或者直接加在reducer文件中:

// 可根据TMDB返回字段补全其他属性
export interface IMovie {
  id: number;
  original_title: string;
}

2. 修正Reducer.ts

import { Action } from './actions'
import { IMovie } from './types'

export interface IMovieState {
  movie: IMovie[] // 修正为电影对象数组类型
}
const initialState: IMovieState = {
  movie: [],
}

export const movieReducer = (
state: IMovieState = initialState,
action: Action,
) => {
switch (action.type) {
case 'GET_MOVIES': {
  // 修正字段名,同时展开payload合并数组
  return { ...state, movie: [...state.movie, ...action.payload] }
}
default:
  return state
 }
}

3. 修正Actions.ts

import axios from 'axios'
import { Dispatch } from 'redux'
import { IMovie } from './types'

// 修正payload类型为电影对象数组
export type Action = { type: 'GET_MOVIES'; payload: IMovie[] }

const getMovies = (movies: IMovie[]): Action => ({
 type: 'GET_MOVIES',
 payload: movies,
})

export const loadMovies = () => {
 return function (dispatch: Dispatch<Action>) {
 axios
  .get(`${process.env.REACT_APP_API_KEY}`)
  .then((res) => {
    // 取接口返回的results字段,就是电影列表数组
    dispatch(getMovies(res.data.results))
  })
  .catch((err) => console.log(err))
  }
 }

4. 修正Store.ts,导出RootState类型

import { createStore, applyMiddleware } from 'redux'
import { composeWithDevTools } from "redux-devtools-extension";
import reduxThunk from 'redux-thunk'
import  rootReducer  from '../redux/rootReducer'

const middlewares = [reduxThunk]

export const store = createStore(rootReducer, 
composeWithDevTools(applyMiddleware(...middlewares)))

// 导出根state类型,供useSelector使用
export type RootState = ReturnType<typeof store.getState>

5. 修正App.tsx

import React, { useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { loadMovies } from './redux/actions'
import { RootState } from './redux/store'
import './App.css'

function App() {
const dispatch = useDispatch()
// 修正useSelector类型,注意此处的movieReducer要和你rootReducer里挂载的字段名对应
const movies = useSelector((state: RootState) => state.movieReducer.movie)
useEffect(() => {
dispatch(loadMovies())
}, [dispatch])
return <div className="App">
  <ul>
    {movies.map(mov => (
      <li key={mov.id}>{mov.original_title}</li>
    ))}
  </ul>
</div>
 }

export default App

注意:如果你的rootReducer中给movieReducer挂载的别名不是movieReducer,需要把state.movieReducer.movie里的第一个movieReducer替换为你实际定义的别名。

内容的提问来源于stack exchange,提问作者Faruk Suljagic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 23:15:02