如何让Next.js的getStaticProps与typescript配合使用

80

我正在使用启用typescript功能的Next.js

尝试按照此处描述的方式使用getStaticProps https://nextjs.org/docs/basic-features/typescript

具有GetStaticProps类型

export const getStaticProps: GetStaticProps = () => {
    return {
        props: {
            host: process.env.DB_HOST.toString(),
        },
    }
}

我遇到了这样的错误 在此输入图片说明

Type '() => { props: { host: string; }; }' is not assignable to type 'GetStaticProps<{ [key: string]: any; }, ParsedUrlQuery>'.
  Type '{ props: { host: string; }; }' is missing the following properties from type 'Promise<GetStaticPropsResult<{ [key: string]: any; }>>': then, catch, [Symbol.toStringTag], finallyts(2322)

我会感激任何帮助。

这是整个页面的代码:

import Head from 'next/head'
import styles from '../styles/Home.module.css'
import React from 'react'
import { GetStaticProps, GetStaticPropsContext } from 'next'

interface Props {
    host: string
}

const Home: React.FC<Props> = (props) => {
    return (
        <div className={styles.container}>
            <Head>
                <title>Create Next App</title>
                <link rel="icon" href="/favicon.ico" />
            </Head>

            <main className={styles.main}>
                aa:{props.host}
                <h1 className={styles.title}>
                    Welcome to <a href="https://nextjs.org">Next.js!</a>
                </h1>
                <p className={styles.description}>
                    Get started by editing <code className={styles.code}>pages/index.js</code>
                </p>
                <div className={styles.grid}>
                    <a href="https://nextjs.org/docs" className={styles.card}>
                        <h3>Documentation &rarr;</h3>
                        <p>Find in-depth information about Next.js features and API.</p>
                    </a>

                    <a href="https://nextjs.org/learn" className={styles.card}>
                        <h3>Learn &rarr;</h3>
                        <p>Learn about Next.js in an interactive course with quizzes!</p>
                    </a>

                    <a
                        href="https://github.com/vercel/next.js/tree/master/examples"
                        className={styles.card}
                    >
                        <h3>Examples &rarr;</h3>
                        <p>Discover and deploy boilerplate example Next.js projects.</p>
                    </a>

                    <a
                        href="https://vercel.com/import?filter=next.js&utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
                        className={styles.card}
                    >
                        <h3>Deploy &rarr;</h3>
                        <p>Instantly deploy your Next.js site to a public URL with Vercel.</p>
                    </a>
                </div>
            </main>

            <footer className={styles.footer}>
                <a
                    href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
                    target="_blank"
                    rel="noopener noreferrer"
                >
                    Powered by <img src="/vercel.svg" alt="Vercel Logo" className={styles.logo} />
                </a>
            </footer>
        </div>
    )
}

export const getStaticProps: GetStaticProps = () => {
    return {
        props: {
            host: process.env.DB_HOST.toString(),
        },
    }
}

export default Home
7个回答

82

你好,我遇到了和你一样的问题,但是上面的答案都没有帮到我。

我在文档中快速阅读了一下: https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation

发现你的getStaticProps应该使用正确的类型:

import { GetStaticProps } from 'next'

export const getStaticProps: GetStaticProps = async (context) => {
  // ...
}

然后在你的组件中:

import { InferGetStaticPropsType } from 'next'
import { GetStaticProps } from 'next'

type Post = {
  author: string
  content: string
}

export const getStaticProps: GetStaticProps = async (context) => {
  const res = await fetch('https://.../posts')
  const posts: Post[] = await res.json()

  return {
    props: {
      posts,
    },
  }
}

function Blog({ posts }: InferGetStaticPropsType<typeof getStaticProps>) {
  // will resolve posts to type Post[]
}

export default Blog

这将自动生成一个类型,从GetStaticProps到您的组件,它对我百分之百有效。


我该如何将这个与从父组件传递下来的 props 结合起来? - Arbnor Lumezi
我在一个新安装的NextJS应用程序中使用此代码时遇到了编译器问题:“getStaticProps不受支持/ app /”。 - delete

27

您原始的示例几乎是正确的,但getStaticProps函数表达式缺少async。尝试这样做:

export const getStaticProps: GetStaticProps = async () => { // must be async
  return {
    props: {
      host: process.env.DB_HOST.toString(),
    },
  };
};

这不是因为TS,而是因为Next.js中getStaticProps()的实际定义

回到你的示例,更好的方式是使用Props泛型来改进类型:

interface Props {
  host: string;
}

export const getStaticProps: GetStaticProps<Props> = async () => {
  return {
    props: {
      host: process.env.DB_HOST.toString(),
    },
  };
};

16

答案如下:

export async function getStaticProps(context): Promise<GetStaticPropsResult<HomeProps>> {
    return {
        props: {
            host: process.env.DB_HOST,
        },
    };
}

我的同事通过检查GetStaticProps类型定义找到了解决方案:enter image description here

下面是整个页面的代码:

import Head from "next/head";
import styles from "../styles/Home.module.css";
import React from "react";
import { GetStaticPropsResult, GetStaticProps } from "next";

interface HomeProps {
    host: string;
}

const Home: React.FC<HomeProps> = (props: HomeProps) => {
    return (
        <div className={styles.container}>
            <Head>
                <title>Create Next App</title>
                <link rel="icon" href="/favicon.ico" />
            </Head>

            <main className={styles.main}>
                aa:{props.host}
                <h1 className={styles.title}>
                    Welcome to <a href="https://nextjs.org">Next.js!</a>
                </h1>
                <p className={styles.description}>
                    Get started by editing <code className={styles.code}>pages/index.js</code>
                </p>
                <div className={styles.grid}>
                    <a href="https://nextjs.org/docs" className={styles.card}>
                        <h3>Documentation &rarr;</h3>
                        <p>Find in-depth information about Next.js features and API.</p>
                    </a>

                    <a href="https://nextjs.org/learn" className={styles.card}>
                        <h3>Learn &rarr;</h3>
                        <p>Learn about Next.js in an interactive course with quizzes!</p>
                    </a>

                    <a href="https://github.com/vercel/next.js/tree/master/examples" className={styles.card}>
                        <h3>Examples &rarr;</h3>
                        <p>Discover and deploy boilerplate example Next.js projects.</p>
                    </a>

                    <a
                        href="https://vercel.com/import?filter=next.js&utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
                        className={styles.card}
                    >
                        <h3>Deploy &rarr;</h3>
                        <p>Instantly deploy your Next.js site to a public URL with Vercel.</p>
                    </a>
                </div>
            </main>

            <footer className={styles.footer}>
                <a
                    href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
                    target="_blank"
                    rel="noopener noreferrer"
                >
                    Powered by <img src="/vercel.svg" alt="Vercel Logo" className={styles.logo} />
                </a>
            </footer>
        </div>
    );
};

export async function getStaticProps(context): Promise<GetStaticPropsResult<HomeProps>> {
    return {
        props: {
            host: process.env.DB_HOST,
        },
    };
}

export default Home;

我尝试了上面的代码,但它没有起作用。 - Varanasi Phaneendra

11

2022年正确的做法是在Next.js类型中利用泛型。

import type { NextPage, GetStaticProps } from "next";
// ...

interface HomeProps {
  host: string
}

const Home: NextPage<HomeProps> = (props) => {
  // ...
};

export const getStaticProps: GetStaticProps<HomeProps> = async () => {
  // ...
};

7

声明:仅适用于/pages设置

简而言之,可在此处用于常量重用:


export const getStaticProps = async ({
    params,
}: GetStaticPropsContext<PageParams>): Promise<
    GetStaticPropsResult<ContentPageProps>
> => {
    const { title, description } = await fetch(".../entity", { uuid: params.uuid })
    return {
        props: {
            title,
            description,
        },
    }
}

以下是我在page/content.tsx中正确使用getStaticProps的示例:

import type {
    GetStaticPathsResult,
    GetStaticPropsContext,
    GetStaticPropsResult,
} from 'next'

type PageParams = {
   uuid: string
}

type ContentPageProps = {
   title: string
   description: string
}

const ContentPage = ({ title, description }: ContentPageProps): JSX.Element => {
    return (
        <>
             <h1>{title}</h1>
             <p>{description}</p>
        </>
    )
}

export default ContentPage

export const getStaticProps = async ({
    params,
}: GetStaticPropsContext<PageParams>): Promise<
    GetStaticPropsResult<ContentPageProps>
> => {
    const { title, description } = await fetch(".../entity", { uuid: params.uuid })
    return {
        props: {
            title,
            description,
        },
    }
}

export const getStaticPaths = async ({}): Promise<
    GetStaticPathsResult<PageParams>
> => {
    return {
        paths: { params: { uuid: "54b659a1-3f20-4440-90b5-9107bd62b5ca" }},
        fallback: false,
    }
}

注意

async (context:GetStaticPropsContext<PageParams>):
    Promise<GetStaticPropsResult<ContentPageProps>

其中PageParams是从ParsedUrlQuery派生而来,而ContentPageProps是您将放入组件中进行渲染的内容,可以是任何复杂度(但不可递归)。


时机恰到好处 - petrosmm
1
@petrosmm 很高兴能帮到你。 - Roman M. Koss
2
导出默认的ContentPage常量是错误的,只需要使用前面的赋值,将其改为export default ContentPage - Roman M. Koss
你从 ParsedUrlQuery 中获取 PageParams 的方法是什么? - Ini
所以 ParsedUrlQuery 是我们在 HTTP 请求中接收到的内容,或者在进行静态渲染时提供的输入。它是请求的一部分,我们使用 GetStaticPathsResult/GetStaticPropsContext 泛型来提供类型。 - Roman M. Koss
显示剩余2条评论

2

1
  • getStaticPaths

    export const getStaticPaths: GetStaticPaths = async () => {
    
  • getStaticProps

    export const getStaticProps = async ({params}: 
                                         GetStaticPropsContext<{ slug: string }>) => {
    
  • Component

     export default function Product({product}: InferGetStaticPropsType<typeof getStaticProps>) {
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接