TS2345报错:类型'{}'缺少Movie类型所需属性如何解决
问题根因
TS2345报错的核心原因是Redux中Movies_State类型定义的movies_list字段被标注为object[](普通对象数组),而非Movie[]类型,导致TS推导MoviesList的元素类型为无属性的空对象{},此时给map回调参数手动标注Movie类型,就会触发类型不兼容的校验错误。
另外代码里还存在两个容易引发后续问题的隐患:
Movie接口在CardI.tsx和App.tsx中重复定义,后续字段调整时很容易出现两边类型不一致的问题- 遍历渲染时
key属性写在了组件内部的MUI Card标签上,不符合React要求key绑定在循环直接子元素的规则,会触发运行时警告
排查步骤
- 打开
./redux/reducers/MoviesReducer文件,检查Movies_State接口中movies_list字段的类型,确认是否被误写为object[],或因缺省类型被TS默认推导为object[] - 检查
useSelector的泛型参数与根state路径是否匹配,若state路径写错也可能导致拿到的类型不符合预期 - 确认两个文件中重复定义的
Movie接口字段是否完全一致,避免后续维护出现类型偏差
修复方案
- 抽离公共类型,避免重复定义
新建src/types/index.ts文件存放全局共用的接口定义:
// src/types/index.ts export interface Movie { title: string; image: string; id: string; description: string; }
- 修正Redux State类型
在MoviesReducer文件中引入公共Movie类型,给movies_list指定正确的数组类型:
// src/redux/reducers/MoviesReducer.ts import { Movie } from '../../types'; // 其余reducer逻辑保持不变 export interface Movies_State { // 将原有的movies_list: object[] 替换为以下定义 movies_list: Movie[]; // 其余state字段按原有逻辑保留 }
- 修正组件代码
- 删掉
CardI.tsx和App.tsx中本地重复定义的Movie接口,统一从公共类型文件引入 - 去掉
map回调中多余的参数类型标注,TS会自动根据MoviesList的类型推导元素类型 - 将
key属性移到循环渲染的直接子组件上
修正后的CardI.tsx代码:
import { Card, CardHeader, CardMedia, CardContent, Typography, } from "@mui/material"; import { Movie } from '../types'; const CardI = (props : Movie) => { return ( <Card sx={{ maxWidth: 345, minWidth: 200, marginTop: "15px" }}> <CardHeader title={props.title} /> <CardMedia component="img" height="194" image={props.image} alt={props.title} /> <CardContent> <Typography variant="body2" color="text.secondary"> {props.description} </Typography> </CardContent> </Card> ); }; export default CardI;
修正后的App.tsx代码:
import React from "react"; import AppBar from "./components/AppBar"; import { Box } from "@mui/material"; import Card from "./components/Card"; import "./App.css"; import { Movies_State } from "./redux/reducers/MoviesReducer"; import { useSelector } from "react-redux"; function App() { // 按你实际配置的store根state结构调整state的取值路径 const MoviesList = useSelector( (state: { movies: Movies_State }) => state.movies.movies_list ); return ( <div className="App"> <AppBar /> <br /> <br /> <Box justifyContent={"space-around"} flexWrap={"wrap"} display={"flex"}> <React.Fragment> {MoviesList.length > 0 && MoviesList.map((el) => { return <Card key={el.id} {...el} />; })} </React.Fragment> </Box> </div> ); } export default App;
提示:如果你的Redux配置了正确的根state类型(比如通过combineReducers自动推导,或者手动定义了RootState类型),useSelector不需要手动写泛型参数,TS会自动推导返回值类型。
内容的提问来源于stack exchange,提问作者Ostrich96
相关产品推荐
相关产品推荐

