問題概要
Next.jsプロジェクトにおいて、TypeScript4.9追加されたsatisfies
を使用したい場面がありました。しかし、TypeScriptのバージョンを5.xに上げても開発サーバー(next dev
)で以下のようなエラーが発生してしまいました。
Error:
x Expected a semicolon
,----
14 | const tag = { type: 'Post', id: 'LIST' } satisfies T;
: ^^^^^^^^^
`----
※ ただしVSCode上でエラーは表示されていません。
何故、最新のTypeScriptをインストールしているにもかかわらず新機能を利用できないのでしょうか。その原因と対策を探ることにします。
実行環境
- Next.js 12.3.4
- TypeScript 5.1.6
原因と解決策
結論から言うと、Next.js 14.x 等にアップグレードすることで使用できるようになりました。特に設定がない限りNext.jsは内部的にJavaScriptおよびTypeScriptコードを変換するためにSWCを使用しており、サポートされるTypeScript機能はこれに依存するためです。
ただ、SWCのドキュメントによれば、最新のTypeScriptのバージョンまでサポートしているという記載がありましたが、SWCのバージョンによる違いに関しては特に記載がありません。また、Next.jsの依存関係を辿っても正確なTypeScriptのバージョンは不明でした。
Babelの場合
※ Babelを使用している場合は以下で対応された模様。
package.json
との相違
Next.jsを使用したプロジェクトの依存関係として最新のTypeScriptがインストールされ、IDE上エラーが出ていないのはどのような状況と言えるでしょうか。これはコンパイル(TS→JS)と型解析の役割の違いに起因します。
プロジェクトの型はインストールされたTypeScriptによってチェックされるためIDE上では問題ないと判断される一方、SWCではそれを尊重せずコンパイルするため結果に相違が生じてしまっていました。
逆にTypeScriptのバージョンが古くIDEでエラーを表示している場合でも、コンパイラー側で解析することができれば、(以下のように型を無視して)ビルドが可能となります。
const nextConfig = {
eslint: { ignoreDuringBuilds: true },
typescript: { ignoreBuildErrors: true },
};
結論
IDE上の表示とビルド結果の一貫性を確保するにはNext.jsが使用するコンパイラーとTypeScriptの両方に注意する必要があります。しかし正確なバージョンの推定は困難でした。
備考
何故か検証した中でRTK QueryにおけるprovidesTags
の値を生成する関数内ではsatisfies
が使用可能でした。(何が他と異なるのか不明)
getPosts: builder.query({
// `providesList()`内では`satisfies`が使用可能
providesTags: () => providesList(undefined, 'Post'),
...
}),