为页面组件分配扩展NextPage类型时遭遇Type Error求助
解决Next.js中NextPageWithLayout与带Props组件的类型不兼容问题
问题
在galleryssr.tsx的const Page处出现类型错误,引入getServerSideProps传递props前,getLayout功能正常,报错提示NextPageWithLayout无法兼容当前组件类型,需调整类型定义以支持props。
错误详情
Type '{ (props: Props): JSX.Element; getLayout(page: ReactElement<any, string | JSXElementConstructor<any>>): JSX.Element; }' is not assignable to type 'NextPageWithLayout'. Type '{ (props: Props): JSX.Element; getLayout(page: ReactElement<any, string | JSXElementConstructor<any>>): JSX.Element; }' is not assignable to type 'FunctionComponent<{}> & { getInitialProps?(context: NextPageContext): {} | Promise<{}>; } & { getLayout?: ((page: ReactElement<any, string | JSXElementConstructor<...>>) => ReactNode) | undefined; }'. Type '{ (props: Props): JSX.Element; getLayout(page: ReactElement<any, string | JSXElementConstructor<any>>): JSX.Element; }' is not assignable to type 'FunctionComponent<{}>'. Types of parameters 'props' and 'props' are incompatible. Property 'pictures' is missing in type '{}' but required in type 'Props'.ts(2322) galleryssr.tsx(19, 3): 'pictures' is declared here.
相关代码
_app.tsx中的类型定义
export type NextPageWithLayout = NextPage & { getLayout?: (page: ReactElement) => ReactNode; }; type AppPropsWithLayout = AppProps & { Component: NextPageWithLayout; }; function MyApp({ Component, pageProps }: AppPropsWithLayout) { const getLayout = Component.getLayout ?? ((page) => page); return ( <ThemeContextProvider> {getLayout(<Component {...pageProps} />)} </ThemeContextProvider> ); } export default MyApp;
galleryssr.tsx页面代码
import type { ReactElement } from "react"; import { SidebarLayout } from "../layouts/SidebarLayout"; import type { NextPageWithLayout } from "./_app"; import Image from "next/image"; import { GetServerSideProps } from "next"; type Picture = { id: string; author: string; width: number; height: number; url: string; download_url: string; }; type Props = { pictures: Picture[]; }; const Page: NextPageWithLayout = (props: Props) => { return ( <div className="w-full text-left"> <h1>This is a server side rendered gallery</h1> <div className="grid grid-cols-1 grid-gap-4"> {props.pictures.map((picture) => { return ( <div className="flex flex-col items-center justify-center bg-base-200 p-4 rounded-md my-4" key={picture.id} > <div className="h-[300px] w-[300px] relative"> <Image src={picture.download_url} alt={picture.id} layout="fill" objectFit="contain" width={picture.width / 20} height={picture.height / 20} /> </div> <div>{picture.author}</div> </div> ); })} </div> </div> ); }; Page.getLayout = function getLayout(page: ReactElement) { return <SidebarLayout>{page}</SidebarLayout>; }; export const getServerSideProps: GetServerSideProps = async () => { const res = await fetch(`https://picsum.photos/v2/list`); const pictures = await res.json(); return { props: { pictures } }; }; export default Page;
解决方案
问题根源是NextPageWithLayout未支持泛型,无法关联页面组件的Props类型。需修改类型定义并在页面中传入对应Props类型:
1. 修改_app.tsx中的类型定义
让NextPageWithLayout支持泛型,继承NextPage的泛型能力:
// _app.tsx import type { NextPage, AppProps } from 'next'; import type { ReactElement, ReactNode } from 'react'; export type NextPageWithLayout<P = {}> = NextPage<P> & { getLayout?: (page: ReactElement) => ReactNode; }; type AppPropsWithLayout = AppProps & { Component: NextPageWithLayout; }; // 其余代码保持不变 function MyApp({ Component, pageProps }: AppPropsWithLayout) { const getLayout = Component.getLayout ?? ((page) => page); return ( <ThemeContextProvider> {getLayout(<Component {...pageProps} />)} </ThemeContextProvider> ); } export default MyApp;
2. 更新galleryssr.tsx的页面类型声明
给NextPageWithLayout传入页面的Props类型:
// galleryssr.tsx中修改Page的类型声明 const Page: NextPageWithLayout<Props> = (props: Props) => { // 组件内容保持不变 };
修改完成后,TypeScript即可正确识别页面组件的Props类型,解决类型不兼容问题。
内容的提问来源于stack exchange,提问作者user12457151
相关产品推荐
相关产品推荐

