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

InferGetStaticPropsType always returns { [key: string]: any; } #32434

Closed
timfee opened this issue Dec 13, 2021 · 7 comments
Closed

InferGetStaticPropsType always returns { [key: string]: any; } #32434

timfee opened this issue Dec 13, 2021 · 7 comments
Labels
bug Issue was opened via the bug report template.

Comments

@timfee
Copy link
Contributor

timfee commented Dec 13, 2021

What version of Next.js are you using?

12.0.7

What version of Node.js are you using?

17.2

What browser are you using?

Chrome latest

What operating system are you using?

macOS

How are you deploying your application?

next dev

Describe the Bug

See below:

import { GetStaticProps, InferGetStaticPropsType, NextPage } from 'next'
import { pick } from 'contentlayer/client'

import { allArticles } from '.contentlayer/data'

const Home: NextPage = ({ posts }: InferGetStaticPropsType<typeof getStaticProps>) => {
  return (
    <div>hello world</div>
  )
}

export const getStaticProps: GetStaticProps = async () => {
  const posts = allArticles.map((post) =>
    pick(post, ['slug', 'title', 'summary', 'date'])
  )

  return { props: { posts: posts } }
}

export default Home

Expected Behavior

Inside the getStaticProps function, I am able to correctly use the type of posts

const posts: ConvertPick<{
    slug: string;
    title: string;
    summary: string;
    date: string;
}>[]

But inside of the main function, that doesn't work.

To Reproduce

// tsconfig.json
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "baseUrl": ".",
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}
// package.json excerpt
"dependencies": {
    "contentlayer": "0.0.33",
    "next": "12.0.7",
    "next-contentlayer": "0.0.33",
    "next-images": "^1.8.4",
    "next-plausible": "^3.1.4",
    "next-themes": "0.0.15",
    "react": "17.0.2",
    "react-dom": "17.0.2",
  },
  "devDependencies": {
    "@types/node": "16.11.12",
    "@types/react": "17.0.37",
    "@typescript-eslint/eslint-plugin": "5.6.0",
    "@typescript-eslint/parser": "5.6.0",
    "eslint": "8.4.1",
    "eslint-config-next": "12.0.7",
    "eslint-config-prettier": "8.3.0",
    "eslint-plugin-mdx": "^1.16.0",
    "eslint-plugin-prettier": "4.0.0",
    "eslint-plugin-simple-import-sort": "7.0.0",
    "typescript": "4.5.3"
  }

Screen Shot 2021-12-12 at 18 37 45

@timfee timfee added the bug Issue was opened via the bug report template. label Dec 13, 2021
@timfee
Copy link
Contributor Author

timfee commented Dec 13, 2021

This seemed a little similar to issues like #29963, #18705, #15913 -- but different enough I figured I'd try a new issue.

@mohsen1
Copy link
Contributor

mohsen1 commented Dec 13, 2021

your code sample says InferGetStaticPropsType<typeof pick> what is pick?

@timfee
Copy link
Contributor Author

timfee commented Dec 13, 2021

your code sample says InferGetStaticPropsType<typeof pick> what is pick?

Sorry that was a copy paste error :)

@balazsorban44
Copy link
Member

balazsorban44 commented Dec 13, 2021

This is because you added GetStaticProps on line 12, without the generic passed to it. The default of prop for that type is { [key: string]: any; }.

See the docs: https://nextjs.org/docs/basic-features/data-fetching#typescript-use-getstaticprops

You want to let the return value be inferrable. If you need to type the params, you can use GetStaticPropsContext

@timfee
Copy link
Contributor Author

timfee commented Dec 14, 2021

@balazsorban44 thank you!

for future readers, this is what I changed to get things to work:

const Home: NextPage<InferGetStaticPropsType<typeof getStaticProps>> = ({
  posts
})

return (<div>hi</div>)

export const getStaticProps: GetStaticProps<{
  posts: {
    slug: string
    title: string
    summary: string
    date: string
  }[]
}> = async () => {
  const posts = allArticles.map((post) =>
    pick(post, ['slug', 'title', 'summary', 'date'])
  )

  return { props: { posts: posts } }
}

@timfee
Copy link
Contributor Author

timfee commented Dec 15, 2021

Hm. It seems like sometimes the verbosity of all of those type declarations aren't required for resolution.

For instance, the following works as is:

import { InferGetStaticPropsType, NextPage } from 'next'

import { allPages } from '.contentlayer/data'

const Home: NextPage<InferGetStaticPropsType<typeof getStaticProps>> = ({
  content
}) => {
  // typeof content = Page | undefined  (which is correct)
  return (<div>foo</div>)
}

export const getStaticProps = async () => {
  const content = allPages.find((page) => page.slug === 'index')

  return { props: { content } }
}

export default Home

@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 27, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue was opened via the bug report template.
Projects
None yet
Development

No branches or pull requests

3 participants