Next.js - Typescript 界面道具传递给组件?

Next.js - Typescript interface props pass down to component?

我有一个接口,其中为我的 API 数据定义了道具。如果我直接在定义接口用法的页面内使用数据,则该接口有效。但是一旦我将数据传递给一个组件,我就会得到:Binding element 'site' implicitly has an 'any' type.

基本上,我想知道如何将定义的界面道具级别传递得更深。

查询:

  export interface SiteProps {
      address?: [Array];
      copyright: string;
      cookieConsent: {
        enabled: boolean;
        link?: string;
      };
      description: string;
      email: string;
      error?: string;
      gtmID?: string;
      keywords: [Array];
      logo: [object];
      mainMenu: [Array];
      phone?: string;
      promoBar: {
        display: string;
        enabled: boolean;
        link?: string;
        text: [Array];
      };
      seo: {
        favicon?: string;
        faviconLegacy?: string;
        metaDesc?: string;
        metaTitle: string;
        shareDesc?: string;
        shareGraphic?: string;
        shareTitle: string;
        touchIcon?: string;
      };
      siteTitle: string;
      socials: [Array];
      rootDomain: string;
    }
    
    
    export interface PageProps {
      body: [Array];
      featuredImage: string;
      slug: string;
      title: string;
      user: {
        featuredImage: string;
        name: string;
        image: string;
      };
      _id: string;
    }
    
    export interface NotFoundProps {
      data: {
        site: SiteProps;
        page: PageProps;
      };
    }

页面 404.tsx 正在使用和运行界面道具的页面:

import { GetStaticProps, NextPage } from "next";

import { getStaticPage } from "@lib/helpers";
import { notFoundQuery } from "@lib/queries";

import Layout from "@components/Layout";
import { NotFoundProps } from "types/typings";

const NotFoundPage: NextPage<NotFoundProps> = ({ data }) => {
  const { page, site } = data;

  const { title } = page;

  return (
    <Layout site={site} page={page}>
      <div className="bg-bubblegum">
        <div className="relative max-w-5xl px-6 min-h-[500px] md:min-h-[700px]  flex flex-col h-full justify-center mx-auto">
          <h1 className="text-5xl antialiased md:text-7xl md:leading-snug">
            {title}
          </h1>

          <p className="text-xl md:text-3xl py-7">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
            eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
            ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
            aliquip ex ea commodo consequat.
          </p>

          <div className="flex gap-4 md:mt-5">
            <button className="items-center justify-center px-6 py-1.5 text-sm font-medium text-white uppercase transition duration-150 ease-in-out border rounded-full shadow-sm md:text-lg bg-navyBlue border-navyBlue hover:bg-white hover:text-navyBlue">
              Cta jumbo primair
            </button>
            <button className="items-center justify-center px-6 py-1.5 text-sm font-medium uppercase transition duration-150 ease-in-out bg-transparent border rounded-full shadow-sm md:text-lg text-navyBlue border-navyBlue hover:bg-white hover:text-navyBlue">
              Cta jumbo secundair
            </button>
          </div>
        </div>
      </div>
    </Layout>
  );
};

export default NotFoundPage;

export const getStaticProps: GetStaticProps = async () => {
  const pageData = await getStaticPage(notFoundQuery);

  return {
    props: {
      data: pageData,
    },
    revalidate: 60,
  };
};

Layout.tsx 界面道具不起作用:

import Script from "next/script";

import { m } from "framer-motion";

import { pageTransitionSpeed } from "@lib/animate";

const pageTransitionAnim = {
  show: {
    opacity: 1,
    transition: {
      duration: pageTransitionSpeed / 1000,
      delay: 0.2,
      ease: "linear",
      when: "beforeChildren",
    },
  },
  hide: {
    opacity: 0,
    transition: {
      duration: pageTransitionSpeed / 1000,
      ease: "linear",
      when: "beforeChildren",
    },
  },
};

    const Layout = ({ site, page = {}, children }) => {
      const { gtmID } = site;
    
      return (
        <>
          {gtmID && (
            <Script
              id="gtm"
              dangerouslySetInnerHTML={{
                __html: `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
          new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
          j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
          'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
          })(window,document,'script','dataLayer','${gtmID}');`,
              }}
            />
          )}
          <m.div
            key={page._id}
            initial="hide"
            animate="show"
            exit="hide"
            variants={pageTransitionAnim}
          >
            <main id="content">{children}</main>
          </m.div>
        </>
      );
    };
    
    export default Layout;

我想你也应该输入布局页:

  interface LayoutProps {
    data: {
      site: SiteProps;
      page: PageProps;
    };
  }

  const Layout: FunctionComponent<LayoutProps> = ({ site, page = {}, children }) => {
    ...
  }