Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make GetStaticProps and GetServerSideProps types use generic props #11033

Closed
danilofuchs opened this issue Mar 13, 2020 · 10 comments
Closed

Make GetStaticProps and GetServerSideProps types use generic props #11033

danilofuchs opened this issue Mar 13, 2020 · 10 comments

Comments

@danilofuchs
Copy link

Feature request

The GetStaticProps and GetServerSideProps typescript types allow us to use the new data fetching methods with typescript, but there is no type check for props content.

Is your feature request related to a problem? Please describe.

The current implementation is as follows:

export type GetStaticProps = (ctx: {
  params?: ParsedUrlQuery
  preview?: boolean
  previewData?: any
}) => Promise<{
  props: { [key: string]: any }
  revalidate?: number | boolean
}>

Describe the solution you'd like

export type GetStaticProps<T = {}> = (ctx: {
  params?: ParsedUrlQuery
  preview?: boolean
  previewData?: any
}) => Promise<{
  props: T
  revalidate?: number | boolean
}>

This way, when defining a Props interface in our page, we can have type safety:

interface Props {
    name: string
}

const Page: NextPage<Props> = (props) => {
    return <div>{props.name}</div>
}

export const getStaticProps: GetStaticProps<Props> = async (context) => {
    const name = await getName(); // string
    return {
        props: {
            name, // yay! Type checked props
        },
    };
};

Something very similar would be implemented for GetServerSideProps.

Describe alternatives you've considered

As the new methods are not static properties of pages anymore, we cannot infer them via the page, so the user may need to add the generic Props type parameter in many places.

Perhaps the types could have more parameters to allow typing previewData?

@Timer
Copy link
Member

Timer commented Mar 13, 2020

Try out next@canary, we already added generics!

@timneutkens
Copy link
Member

Fixed by #10856

@abhijithvijayan
Copy link

abhijithvijayan commented Mar 25, 2020

What about types in context params?

in [id].ts

export const getServerSideProps: GetServerSideProps = async (context) => {
    const { id } = context.params;
}

I get this error

Property 'id' does not exist on type 'ParsedUrlQuery | undefined'.
    27 | 
    28 | export const getServerSideProps: GetServerSideProps = async (context) => {
  > 29 |     const { id } = context.params;

In VSCODE
Screenshot_20200325_195818

@elias551
Copy link

elias551 commented Apr 1, 2020

What about types in context params?

in [id].ts

export const getServerSideProps: GetServerSideProps = async (context) => {
    const { id } = context.params;
}

I get this error

Property 'id' does not exist on type 'ParsedUrlQuery | undefined'.
    27 | 
    28 | export const getServerSideProps: GetServerSideProps = async (context) => {
  > 29 |     const { id } = context.params;

In VSCODE
Screenshot_20200325_195818

You got to check first if context.params is not undefined before destructuring this value

@reaktivo
Copy link

reaktivo commented Apr 3, 2020

For anyone looking for a getStaticProps driven approach instead:

import { GetStaticProps, NextPageContext } from 'next';

export type Await<T> = T extends {
  then(onfulfilled?: (value: infer U) => unknown): unknown;
} ? U : T;

export type ExtractProps<T> = T extends { props: infer P } ? P : never;

export type StaticPageProps<T> = T extends GetStaticProps
  ? ExtractProps<Await<ReturnType<T>>>
  : never;

export type GetStaticPropsContext = Parameters<GetStaticProps>[0];

Then you can have your component read getStaticProps result:

export default function ProductDetailPage(props: StaticPageProps<typeof getStaticProps>) {
  return <>
    // the return type of getPost get's passed
    <h1>{props.post.title}</h1>
   </>;
};

export async function getStaticProps(ctx: GetStaticPropsContext) {
  return {
    post: getPost(ctx)
  }
}

@rubenzup
Copy link

Ok but how to solve it? none of @reaktivo and @elias551 worked for me.

@deadcoder0904
Copy link

I can't figure it out as well. I've opened up a discussion → #16522

@Pravasith
Copy link

What about types in context params?
in [id].ts

export const getServerSideProps: GetServerSideProps = async (context) => {
    const { id } = context.params;
}

I get this error

Property 'id' does not exist on type 'ParsedUrlQuery | undefined'.
    27 | 
    28 | export const getServerSideProps: GetServerSideProps = async (context) => {
  > 29 |     const { id } = context.params;

In VSCODE
Screenshot_20200325_195818

You got to check first if context.params is not undefined before destructuring this value

if(params){ const { slug } = params }

@jareks
Copy link

jareks commented Mar 30, 2021

You got to check first if context.params is not undefined before destructuring this valu

Under what circumstances context.params can be undefined in getServerSideProps?

@balazsorban44
Copy link
Member

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@vercel vercel locked as resolved and limited conversation to collaborators Jan 28, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests