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

Time:04-17

I have an interface with defined props for my API data. The interface works if I am using the data directly inside the page where the interface usage is defined. But once I pass down the data to a component I get: Binding element 'site' implicitly has an 'any' type.

Basically, I want to know how I can pass the defined interface props levels deeper.

The queries:

  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;
      };
    }

The page 404.tsx where the interface props is being used and works:

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 where the interface props not work:

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;

CodePudding user response:

I think you should type also Layout Page:

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

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