How to efficiently type nextjs page's props
December 6th, 2022TL;DR;
Use the following line to automatically type your nextjs page props with the returned type of getServerSideProps
or getStaticProps
type Props = Awaited<ReturnType<typeof getServerSideProps>>['props']
When working on a nextjs page that receives props
from a data fetching method, normally i would type the response of the method and the props the page component receives individually, meaning i would duplicate the type definition, like so
type Props = {
users: User[]
}
export default function TestFetchers({ users }: Props) {
return (
<ul>
{users.map((user) => (
<li key={user.name}>{user.name}</li>
))}
</ul>
)
}
type User = { name: string }
export async function getServerSideProps() {
const users: User[] = getUsers()
return {
props: {
users,
},
}
}
Nothing terribly wrong with that but when you need to add more props, you need to manually modify the Props
type, which to me seems like an unnecessary step. After all, we know what getServerSideProps
is returning.
Well, you can achieve that with the following line
type Props = Awaited<ReturnType<typeof getServerSideProps>>['props']
Let's break it down
Awaited
is one of the typescript utility types and it represents the returned type of a async function.
ReturnType
is another utility type that, as the name indicates, creates a type from the return type of a function.
Combining both we can create a type that represents the return type of the promise returned by our method getServerSideProps
. As the return type of getServerSideProps
represents more than just the props
key, we just pick that one by using the square brackets notation.
So, that's it. An elegant combination of the utility types allow you to have type-safe props in your page component without having to manually define them. Pretty neat!
Full example
type Props = Awaited<ReturnType<typeof getServerSideProps>>['props']
export default function TestFetchers({ users }: Props) {
return (
<ul>
{users.map((user) => (
<li key={user.name}>{user.name}</li>
))}
</ul>
)
}
type User = { name: string }
export async function getServerSideProps() {
const users: User[] = getUsers()
return {
props: {
users,
},
}
}