Next.js は React の型情報をどのように拡張しているのか
はじめに
Next.js 14 では React 19 で搭載予定の新機能がすでにサポートされており React 19 でなくとも利用することができます。
たとえば、useTransition
フックは新しく非同期関数も扱えるようになりました。使い方はこちらの記事にて紹介しています。
この新機能自体は Next.js がサポートしてるので正常に動作するのはわかるのですが、型情報はどうでしょうか?
useTransition
フック自体は react
パッケージからインポートして利用するので React 19 でなければ新しい型情報は含まれていないように思えます。が、実際に試してみると Next.js と一緒に利用する場合は新しい型情報に対応しているのです。
react@18.2.0(@types/react@18.2.0)
の場合、非同期関数に対応してないので型エラーになる
react@18.2.0(@types/react@18.2.0) with Next.js 14
の場合、なぜか型エラーにならない
本記事では Next.js が react
パッケージの型情報をどのように拡張しているのかについて説明します。
TL;DR
最初に結論です。
-
@types/react@^18.2.0
パッケージにはすでに React 19 で搭載予定の新機能に対応した新しい型情報に拡張するための型定義ファイルが用意されている -
next@14
は新しい型情報に拡張するための型定義ファイルを読み込み適用させている
※ next@14
パッケージは互換性のある react
パッケージのバージョン範囲を ^18.2.0
としています[1]。@types/react
パッケージもライブラリ本体とバージョンを揃える必要があるため、^18.2.0
となります[2]。
詳細
@types/react@^18.2.0
パッケージにはすでに React 19 で搭載予定の新機能に対応した新しい型情報に拡張するための型定義ファイルが用意されている
react
パッケージの型情報は、@types/react
パッケージから配布されています。import {} from "react";
とすると、TypeScriptのモジュール解決により node_modules/@types/react/index.d.ts
型定義ファイルの型情報を参照します[3]。この型定義ファイルには React 19 の新しい型情報は含まれていません。
ではどのファイルが新しい型情報を提供しているのでしょうか?実際に Next.js のプロジェクトを用意し、コードエディタから型定義ファイルへ飛んで確かめてみるとします。
すると、node_modules/@types/react/canary.d.ts
型定義ファイルへジャンプしました。この型定義ファイルを読み込むと新しい型情報に拡張されるようです。ファイル先頭のコメント行を見ると親切にもこの型情報を適用させるための3つの方法が記載されています。このことから、きっと Next.js はこの3つの方法のどれかで型情報を適用させてるはずと予想できます。
next@14
は新しい型情報に拡張するための型定義ファイルを読み込み適用させている
用意した Next.js のプロジェクトで先程の canary.d.ts
を適用させているコードがないか検索をかけてみます。プロジェクト内のコードではヒットしなかったので、やはり node_modules
が怪しそうです。
Next.js は next
パッケージでライブラリ本体とその型情報も配布しているので node_modules/next
ディレクトリに検索をかけてみます。が、らしきコードは見つかりません。
探索範囲を広げて node_modules
内で試行錯誤しながら検索を続けていると node_modules/@types/react/experimental.d.ts
型定義ファイル内で canary.d.ts
を読み込むコードを見つけました。
どうやら @types/react
パッケージは canary.d.ts
による型拡張に加え、さらに experimental.d.ts
による型拡張もできるようです。バージョニングポリシーによると React は、Latest チャンネル、Canary チャンネル、Experimental チャンネルの3つのリリースチャンネルを提供しており、型定義ファイルはそれぞれのリリースチャンネルに対応している感じでしょうか。
話はそれましたが、試しに上記import文をコメントアウトしてみると、canary.d.ts
で提供されている新しい型情報を参照できなくなりました。experimental.d.ts
型定義ファイルがどこかで読み込まれているのは間違いなさそうです。
こちらもファイル先頭のコメント行に型情報を適用させるための3つの方法が記載されています。
experimental.d.ts
を適用させているコードがないかnode_modules/next
ディレクトリに再び検索をかけてみます。 すると node_modules/next/types/index.d.ts
型定義ファイル内で該当箇所を見つけることができました。ヨカッタ
プロジェクトのどこかで import {} from "next";
とすると上記ファイルが読み込まれ react
パッケージの型情報が拡張されます。
まとめ
いかがだったでしょうか?
今回は Next.js 14 が React の型情報をどのように拡張しているのかについて調査してみました。
参考になれば幸いです。
-
パッケージの互換性は
package.json
のpeerDependencies
で指定できます。実際の指定箇所は https://github.com/vercel/next.js/blob/v14.0.0/packages/next/package.json#L105 を参照 ↩︎
Discussion