TanStack Query v5がリリースされてSuspense利用時の型定義の問題が解決されていたので試してみました

TanStack Query v5 がリリースされてSuspense利用時の型定義の問題が解決していたので、それを実際にコードを書いて試してみました。
2023.10.18

こんばんは、CX事業本部Delivery部サーバーサイドチームのmorimorikochanです。

表題の通り、TanStack Query v5 が2023年10月17日にリリースされました。それに合わせて、TypeScriptでSuspenseとTanStack Queryを併用した際にundefinedにならないはずの値がundefinedになってしまう型定義の問題が解決しているようです。公式ブログでも以下の部分で言及されています。

https://tanstack.com/blog/announcing-tanstack-query-v5#1st-class-suspense-support

この問題の改善を待っていた人は多いと思いますし僕もその一人です。今回は早速TanStack Query v5でのSuspense対応を試してみました。

undefinedにならないはずの値がundefinedになってしまう型定義の問題とは?

TanStack QueryのSuspenseサポートを有効にした状態では、useQuery()から取得したデータの型は本来queryFnの返り値の型のままであるはずなのですが、TanStack Query側でSuspense有効時の型定義が厳密にされておらず、undefinedになりえる型(queryFnの返り値の型とundefinedとのユニオン型)として表現されていました。
Suspenseを利用することでコンポーネントに不要な型定義を持ち込まない様にできるにもかかわらず、この問題があるためにSuspenseのメリットを十分に受けれない状態になっていました。
詳細は以下のissueをご覧ください。

https://github.com/TanStack/query/issues/2306

TanStack Query v5ではどうなった? どうやってSuspenseサポートを有効にするのか?

TanStack Query v5ではこの問題が解決されており、Suspenseサポートを有効にした状態でuseQuery()経由で取得したデータの型は全てqueryFnの返り値の型のままになるようになっています。
ただし1点注意しなければならないのが、v4までのようにuseQuery()でデータフェッチすることはできません。v5でSuspense利用時はSuspense専用のhooksである useSuspenseQuery(), useSuspenseInfiniteQuery(), useSuspenseQueries()を利用する必要があります

https://tanstack.com/query/v5/docs/react/guides/suspense

v5のuseQuery()のドキュメントにはsuspenseオプションが存在していますがこれは誤りです。
せっかくなのでドキュメント修正のPRを出してみました

https://github.com/TanStack/query/pull/6187/files

実際にSuspense書いてみた

useSuspenseQuery()を利用してみましたが、確かに以前の問題は改善されており、以下コードのdata変数の型はGithubRepositoryのみになっていました

const GithubRepository = ({ repository }: { repository: string }) => {
  const { data } = useSuspenseQuery<GithubRepository>({
//         ^? const data: GithubRepository
    queryKey: ["githubRepository"],
    queryFn: () =>
      fetch(`https://api.github.com/repos/${repository}`).then((res) =>
        res.json()
      ),
  });

  return (
    <div>
      <h2>GitHub Repository Detail</h2>
      <h3>{data.full_name}</h3>
      <ul>
        <li>id: {data.id}</li>
        <li>name: {data.name}</li>
      </ul>
      <img src={data.owner.avatar_url} />
    </div>
  );
};

実際に書いたコードはこちらです

まとめ

  • TanStack Query v5 では、Suspenseの型定義が改善されて、よりSuspenseが使いやすくなりました。
  • ただし、v5ではuseQuery()が使えないのでv4からv5にアップデートする方は注意しましょう