React+TypeScript入门报错:类型'YYY'缺少类型'ZZZ'要求的必填属性XXX的解决求助
解决React + TypeScript中“property XXX is missing in type 'YYY' but required in type 'ZZZ'”错误
我来帮你搞定这个TypeScript类型错误!你猜的没错,这个问题确实和TypeScript的接口类型匹配有关,和React本身关系不大。咱们一步步理清楚问题出在哪,以及怎么修复。
错误原因分析
你遇到的核心问题是组件传参时的类型不匹配:
- 你的
Page组件接收的props类型是PageInterface,它要求必须有两个属性:user(类型是{ permaLink: string; })和avatarSize(类型是number)。 - 但在
App组件里,你写了<Page user={data} />——这里你把整个data对象(包含user和avatarSize两个属性)传给了Page的user属性,导致:Page的user属性类型变成了整个data的类型,而不是预期的{ permaLink: string; };Page需要的avatarSize属性完全没有传递,所以TypeScript报错说这个必填属性缺失。
修复方案
有两种简单的修复方式,选哪种都可以:
方案1:明确传递每个必填属性
直接把data里的user和avatarSize分别传给Page组件:
const App = () => <Page user={data.user} avatarSize={data.avatarSize} />;
方案2:使用扩展运算符传递所有属性
因为data对象的结构刚好完全符合PageInterface的要求,所以可以用扩展运算符...把data的所有属性一次性传给Page:
const App = () => <Page {...data} />;
修复后的完整代码
import { Link } from "react-router-dom"; export interface AvatarSize { avatarSize: number; } export interface PageInterface extends AvatarSize { user: { permaLink: string; }; } const data = { user: { permaLink: "https://images.unsplash.com/photo-1590698933947-a202b069a861?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTF8fGhhcHB5fGVufDB8fDB8fA%3D%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60" }, avatarSize: 50 }; // 这里用方案2的写法,也可以换成方案1 const App = () => <Page {...data} />; const Page = (props: PageInterface) => ( <PageLayout user={props.user} avatarSize={props.avatarSize} /> ); const PageLayout = (props: PageInterface) => ( <NavigationBar user={props.user} avatarSize={props.avatarSize} /> ); const NavigationBar = (props: PageInterface) => ( <Link to={props.user.permaLink}> <Avatar avatarSize={props.avatarSize} /> </Link> ); const Avatar = (props: AvatarSize) => ( <div>Avatar Size: {props.avatarSize}</div> ); export default App;
额外的优化建议(可选)
你会发现PageLayout和NavigationBar组件其实只用到了PageInterface里的user和avatarSize属性,为了让类型更精准,可以用TypeScript的Pick工具类型来限制它们的props:
// 用Pick来选择需要的属性,比直接用PageInterface更精准 const PageLayout = (props: Pick<PageInterface, 'user' | 'avatarSize'>) => ( <NavigationBar user={props.user} avatarSize={props.avatarSize} /> ); const NavigationBar = (props: Pick<PageInterface, 'user' | 'avatarSize'>) => ( <Link to={props.user.permaLink}> <Avatar avatarSize={props.avatarSize} /> </Link> );
这样做的好处是,以后如果PageInterface新增了其他属性,这些组件不会意外接收不需要的props,类型检查会更严格。
内容的提问来源于stack exchange,提问作者Ryan Kim
相关产品推荐
相关产品推荐

