如何让对象中函数的返回类型与对应React组件的Props类型保持一致?
如何让对象中函数的返回类型与对应React组件的Props类型保持一致?
看起来你想让Layouts对象里每个布局项的component的Props类型,和props函数的返回类型严格绑定,而且每个布局可以有自己独立的类型,还能让TypeScript自动推断对吧?这确实需要用泛型来实现,我给你两种实用的解决方案:
方法一:用泛型工具函数自动推断类型(推荐)
这种方式不需要手动定义所有布局的Props类型,TypeScript会自动帮你匹配每个布局项的component和props函数的类型:
import React, { FC } from 'react'; // 先定义你已有的PageProps类型 type PageProps = { route: { name: string }; sidebarData: string[]; currentUser: { name: string }; // 其他页面公共属性... }; // 定义单个布局项的泛型类型,把组件Props和props函数返回值绑定起来 type LayoutItem<T> = { component: FC<T>; props: (pageProps: PageProps) => T; }; // 用一个泛型函数来创建布局对象,确保每个项的类型匹配 function createLayouts<T extends Record<string, LayoutItem<any>>>(layouts: T): T { return layouts; } // 示例组件 const DefaultLayout = ({ title }: { title: string }) => ( <div className="default-layout"> <h1>{title}</h1> </div> ); const SidebarLayout = ({ sidebarItems, user }: { sidebarItems: string[], user: { name: string } }) => ( <div className="sidebar-layout"> <aside> <p>用户:{user.name}</p> <ul> {sidebarItems.map(item => <li key={item}>{item}</li>)} </ul> </aside> <main>内容区域</main> </div> ); // 创建布局对象,TypeScript会自动验证每个项的类型是否匹配 const layouts = createLayouts({ default: { component: DefaultLayout, // 这里返回的{ title: ... }会自动匹配DefaultLayout的Props类型 props: (pageProps) => ({ title: pageProps.route.name }) }, sidebar: { component: SidebarLayout, // 返回值必须严格匹配SidebarLayout的Props,否则会报错 props: (pageProps) => ({ sidebarItems: pageProps.sidebarData, user: pageProps.currentUser }) } });
这种方式的好处是完全自动推断,你不用额外维护一份所有布局Props的类型定义,只要组件的Props变了,TypeScript会立刻检查props函数的返回值是否匹配。
方法二:手动定义泛型类型约束
如果你希望明确指定所有布局的Props类型,也可以直接给Layouts定义一个泛型类型:
import React, { FC } from 'react'; type PageProps = { /* 你的PageProps定义 */ }; // 定义所有布局的Props类型映射 type LayoutPropsMap = { default: { title: string }; sidebar: { sidebarItems: string[], user: { name: string } }; }; // 把LayoutPropsMap和Layouts类型绑定,确保每个布局项的类型一致 type Layouts<T extends Record<string, any>> = { [K in keyof T]: { component: FC<T[K]>; props: (pageProps: PageProps) => T[K]; }; }; // 现在声明layouts时,TypeScript会严格按照LayoutPropsMap来校验 const layouts: Layouts<LayoutPropsMap> = { default: { component: ({ title }) => <h1>{title}</h1>, props: (pageProps) => ({ title: pageProps.route.name }) }, sidebar: { component: ({ sidebarItems, user }) => ( <aside>{user.name}{sidebarItems.map(item => <div>{item}</div>)}</aside> ), props: (pageProps) => ({ sidebarItems: pageProps.sidebarData, user: pageProps.currentUser }) } };
这种方式适合需要统一管理所有布局Props类型的场景,缺点是每次新增或修改布局时,都要同步更新LayoutPropsMap。
两种方法都能解决你遇到的问题,推荐第一种自动推断的方式,开发效率更高~
备注:内容来源于stack exchange,提问作者Dennis Adamczyk
相关产品推荐
相关产品推荐

