InferGetServerSidePropsType doesn't work with conditional returns
Verify canary release
- [X] I verified that the issue exists in Next.js canary release
Provide environment information
❯ next info
Operating System:
Platform: darwin
Arch: x64
Version: Darwin Kernel Version 20.6.0: Tue Feb 22 21:10:41 PST 2022; root:xnu-7195.141.26~1/RELEASE_X86_64
Binaries:
Node: 17.9.0
npm: 8.5.5
Yarn: N/A
pnpm: N/A
Relevant packages:
next: 12.1.6-canary.16
react: 18.0.0
react-dom: 18.0.0
What browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
No response
Describe the Bug
In the documentation here: https://nextjs.org/docs/api-reference/data-fetching/get-server-side-props#redirect
We are shown that we can return a redirect or a notFound instead of props. I have attempted to do that in TypeScript here:
export default function user({ user }: InferGetServerSidePropsType<typeof getServerSideProps>) {
return (
<div>{user}</div>
);
}
export const getServerSideProps = async ({ req }: GetServerSidePropsContext) => {
const userJwt = parseCookies({ req })['jwt']
if (!userJwt) {
return { redirect: { destination: '/login', permanent: false } }
}
const user = await prisma.users.findFirst()
return { props: { user } }
}
If there is logic handling a conditional redirect, we don't get type inference. Here is a WebStorm screenshot showing that:

Once I remove the conditional logic:
export default function user({ user }: InferGetServerSidePropsType<typeof getServerSideProps>) {
return (
<div>{user?.email}</div>
);
}
export const getServerSideProps = async ({ req }: GetServerSidePropsContext) => {
const user = await prisma.users.findFirst()
return { props: { user } }
}
Then type inference works again:

Expected Behavior
Type inference works with conditionals.
To Reproduce
One way of reproducing is copy/pasting what I provided in the bug description:
export default function user({ user }: InferGetServerSidePropsType<typeof getServerSideProps>) {
return (
<div>{user}</div>
);
}
export const getServerSideProps = async ({ req }: GetServerSidePropsContext) => {
const userJwt = parseCookies({ req })['jwt']
if (!userJwt) {
return { redirect: { destination: '/login', permanent: false } }
}
const user = await prisma.users.findFirst()
return { props: { user } }
}
This however requires extra dependencies to be installed. With no dependencies, you can simply take the example from the docs and attempt to use type inference with it: https://nextjs.org/docs/api-reference/data-fetching/get-server-side-props#redirect
You have to use GetServerSideProps/GetStaticProps interface instead and pass the Props interface of your page component to its first generic for the props to be picked up by Infer. You will have to do it anyway once you need to have some sort of baseline props interface across all pages with added benefit the return type of your SSR function will also be typechecked.
@GabenGar I just switched getServerSideProps to:
export const getServerSideProps: GetServerSideProps = async ({ req }) => {
const userJwt = parseCookies({ req })['jwt']
if (!userJwt) {
return { redirect: { destination: '/login', permanent: false } }
}
const user = await prisma.users.findFirst()
return { props: { user } }
}
and user is still being detected as any. Could you copy/paste the correct way of writing it? Perhaps I'm missing something?
Let's say you have interface PageProps { user: unknown } declared somewhere on the component file.
Then you write GetServerSideProps<PageProps> as the type for your getServerSideProps() function.
I think I attempted what you mentioned, but no luck still. I also went back to the docs: https://nextjs.org/docs/api-reference/data-fetching/get-server-side-props#getserversideprops-with-typescript
and I couldn't find a similar example either. I'm still new to TypeScript, perhaps you could copy/paste my example with the changes?
I have a page which uses it. The lines of interest are 30 and 128.
That worked, thank you @GabenGar! Here it is completely, so people can reference it in the future:
import { prisma } from '../db'
import { users } from '@prisma/client'
import { GetServerSideProps, InferGetServerSidePropsType } from "next/types";
import { parseCookies } from "nookies";
export default function Users({ users }: InferGetServerSidePropsType<typeof getServerSideProps>) {
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.email}</li>
))}
</ul>
);
}
interface IProps {
users: users[]
}
export const getServerSideProps: GetServerSideProps<IProps> = async ({ req }) => {
const userJwt = parseCookies({ req })['jwt']
if (!userJwt) {
return { redirect: { destination: '/login', permanent: false } }
}
const users = await prisma.users.findMany()
return { props: { users } }
}
My mistake was that I did this:
interface IProps {
props: {
users: users[]
}
}
@GabenGar, aren't we returning an object with everything inside a props object? Why does including that in the interface not work? I'm confused about that.
aren't we returning an object with everything inside a props object? Why does including that in the interface not work? I'm confused about that.
Because the generic for GetServerSideProps interface defines the shape of the props object, not the entire result from it.
Thanks @GabenGar, that makes sense. I appreciate the help!
@balazsorban44, could this ticket track making the documentation here more clear? https://nextjs.org/docs/api-reference/data-fetching/get-server-side-props#getserversideprops-with-typescript
I'm not a TypeScript expert, but I could imagine others getting confused by it as well.
@balazsorban44 bumping this issue
I'm not a TypeScript expert, but I could imagine others getting confused by it as well.
@anthonyalayo you're absolute right! I was so confused on why this did not work.
Updating the documentation would certainly help other people.
This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.