😊
Next.js の InferGetStaticPropsType が便利
Next.jsのサンプルリポジトリを眺めていたらInferGetStaticPropsTypeというものを見つけました。これを使うと、getStaticPropsでreturnされた値をもとに、Pageに渡されるPropsの型を類推してくれます。
↓ ドキュメントはこちら
これまではこんな感じで書いていた
これまではPropsの型宣言を自分で書いていました。
import { GetStaticProps } from 'next';
// 👇
type Props = { posts: Post[] };
export const getStaticProps: GetStaticProps<Props> = async () => {
const { posts } = await getPosts();
return {
props: {
posts,
},
revalidate: 1
};
};
const Page: NextPage<Props> = (props) => { ... }
export default Page;
InferGetStaticPropsTypeを使うと…
InferGetStaticPropsType<typeof getStaticProps>のように書くことで、getStaticProps()の返り値をもとにPageに渡される型を類推してくれます。
import { InferGetStaticPropsType } from 'next';
// 👇
type Props = InferGetStaticPropsType<typeof getStaticProps>;
export const getStaticProps = async () => {
const { posts } = await getPosts(); // => { posts: Post[] }
return {
props: {
posts,
},
revalidate: 1
};
};
const Page: NextPage<Props> = (props) => { ... }
export default Page;
いつの間にこんなものが使えるようになっていた……?と思い、調べてみるとドキュメントに記載されたのは2020年5月のようです。
getStaticProps() 自体には型アノテーションをつけないこと
Teratailで「InferGetStaticPropsTypeを使ったらany型になってしまった」という投稿を見つけたので、勝手にここで回答しちゃいます。
公式ドキュメントを参考にInferGetStaticPropsTypeを使ってみたのですが、コンポーネント内のitemsにマウスホバーするとany型が表示されています。
この質問者の方は以下のようなコードを書いている模様。
うまく類推が効かない例
import { GetStaticProps, InferGetStaticPropsType } from 'next';
export const getStaticProps: GetStaticProps = async () => {
const items: User[] = sampleUserData;
return { props: { items } };
};
// ...省略...
うまく類推が効かない理由はexport const getStaticProps: GetStaticProps = ...というようにgetStaticProps()に対してGetStaticPropsのアノテーションをつけてしまっているからだと思われます。: GetStaticPropsを外せばちゃんと類推されるはず。
そうするとgetStaticProps()の引数がanyにならない?
代わりにGetStaticPropsContextを引数にあててあげれば良いですね!
import { InferGetStaticPropsType, GetStaticPropsContext } from 'next';
type Props = InferGetStaticPropsType<typeof getStaticProps>;
export const getStaticProps = async (context: GetStaticPropsContext) => {
const { query } = context
};
Discussion
以下のように、
GetStaticPropsのGenericsにpropsの型を指定してやるとInferGetStaticPropsTypes側でもanyにならない様子でした。ここの指定がない場合、
propsが{[key: string]: any}になるのでInferGetStaticPropsTypesがanyになるのだと思います。