Reputation: 1126
I am using Next.js with typescript feature enabled
Trying to use getStaticProps as described here https://nextjs.org/docs/basic-features/typescript
With GetStaticProps type
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)
I would appreciate any help.
Here is the entire page's code:
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 →</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 →</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 →</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 →</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
Upvotes: 83
Views: 103754
Reputation: 999
Disclaimer: For /pages
setup only
In short use this for constant reuse:
export const getStaticProps = async ({
params,
}: GetStaticPropsContext<PageParams>): Promise<
GetStaticPropsResult<ContentPageProps>
> => {
const { title, description } = await fetch(".../entity", { uuid: params.uuid })
return {
props: {
title,
description,
},
}
}
Here is what correct typing for getStaticProps
looks like in page/content.tsx
for me:
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,
}
}
Notice
async (context:GetStaticPropsContext<PageParams>):
Promise<GetStaticPropsResult<ContentPageProps>
Where PageParams
is derived from ParsedUrlQuery
and ContentPageProps
is what you will put into your component to render, can by any complexity (but not recursive).
Upvotes: 8
Reputation: 2228
Hi Ran in to your issue but none of the answers above helped me.
I had a quick read in the documentation: https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation
and found out that you the correct type for your getStaticProps should be:
import { GetStaticProps } from 'next'
export const getStaticProps: GetStaticProps = async (context) => {
// ...
}
Then in your component:
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
This will autogenerate a type from GetStaticProps to your component it worked for me 100%
Upvotes: 84
Reputation: 49709
getStaticPaths
export const getStaticPaths: GetStaticPaths = async () => {
getStaticProps
export const getStaticProps = async ({params}:
GetStaticPropsContext<{ slug: string }>) => {
Component
export default function Product({product}: InferGetStaticPropsType<typeof getStaticProps>) {
Upvotes: 1
Reputation: 151
The correct way to do it in 2022 is to leverage generics in the Next.js types.
import type { NextPage, GetStaticProps } from "next";
// ...
interface HomeProps {
host: string
}
const Home: NextPage<HomeProps> = (props) => {
// ...
};
export const getStaticProps: GetStaticProps<HomeProps> = async () => {
// ...
};
Upvotes: 10
Reputation: 550
I had same trouble as OP. This tutorial worked perfectly for me: https://www.vitamindev.com/next-js/getstaticprops-getstaticpaths-typescript/. It addressed the issue where getStaticPaths
requires a type of ParsedUrlQuery
. Authors offers extending it, as a solution. Please make you name your properties exactly(!) else TS will complain.
Upvotes: 2
Reputation: 3104
Your original example is almost correct but the getStaticProps
function expression is missing async
. Try this:
export const getStaticProps: GetStaticProps = async () => { // must be async
return {
props: {
host: process.env.DB_HOST.toString(),
},
};
};
This is not because of TS but the actual definition of getStaticProps() in Next.js.
Back to your example, even better would be to improve typing with the Props generic:
interface Props {
host: string;
}
export const getStaticProps: GetStaticProps<Props> = async () => {
return {
props: {
host: process.env.DB_HOST.toString(),
},
};
};
Upvotes: 27
Reputation: 1126
Answer is as follows:
export async function getStaticProps(context): Promise<GetStaticPropsResult<HomeProps>> {
return {
props: {
host: process.env.DB_HOST,
},
};
}
My colleague found the solution by checking GetStaticProps type definition:
Here is the whole page code
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 →</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 →</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 →</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 →</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;
Upvotes: 17