Menu

TypeScript

Next.jsには組み込みのTypeScriptサポートがあり、create-next-appで新しいプロジェクトを作成すると、必要なパッケージが自動的にインストールされ、適切な設定が行われます。

既存のプロジェクトにTypeScriptを追加するには、ファイルの拡張子を.ts/.tsxに変更します。next devnext buildを実行すると、必要な依存関係が自動的にインストールされ、推奨設定を含むtsconfig.jsonファイルが追加されます。

補足: すでにjsconfig.jsonファイルがある場合は、古いjsconfig.jsonからpathsコンパイラオプションを新しいtsconfig.jsonファイルにコピーし、古いjsconfig.jsonファイルを削除してください。

IDE プラグイン

Next.jsにはカスタムTypeScriptプラグインと型チェッカーが含まれており、VSCodeやその他のコードエディタで高度な型チェックと自動補完を利用できます。

VS Codeでプラグインを有効にするには:

  1. コマンドパレットを開き(Ctrl/⌘ + Shift + P
  2. 「TypeScript: Select TypeScript Version」を検索
  3. 「Use Workspace Version」を選択
TypeScript Command Palette

これでファイルを編集する際にカスタムプラグインが有効になります。next buildを実行すると、カスタム型チェッカーが使用されます。

TypeScriptプラグインは以下のような支援を提供します:

  • セグメント設定オプションに無効な値が渡された場合の警告
  • 利用可能なオプションとコンテキスト内ドキュメントの表示
  • use clientディレクティブが正しく使用されていることの確認
  • クライアントフック(useStateなど)がクライアントコンポーネントでのみ使用されていることの確認

🎥 動画: 組み込みTypeScriptプラグインについて学ぶ → YouTube(3分間)

エンドツーエンドの型安全性

Next.jsのAppルーターは強化された型安全性を備えています。これには以下が含まれます:

  1. データ取得関数とページの間でのシリアライズが不要: サーバー上のコンポーネント、レイアウト、ページで直接fetchできます。このデータはクライアント側でReactで消費するために、シリアライズ(文字列に変換)する必要はありません。代わりに、appはデフォルトでサーバーコンポーネントを使用するため、追加手順なしでDateMapSetなどの値を使用できます。以前は、Next.js固有の型を使用してサーバーとクライアントの境界を手動で型付けする必要がありました。
  2. コンポーネント間のデータフローの合理化: ルートレイアウトを採用して_appが不要になったことで、コンポーネントとページ間のデータフローを視覚化しやすくなりました。以前は、個々のpages_appの間を流れるデータの型付けが難しく、混乱を招くバグが発生する可能性がありました。Appルーターの共存データフェッチングにより、この問題は解消されました。

Next.jsでのデータフェッチングは、データベースやコンテンツプロバイダの選択について制限することなく、可能な限りのエンドツーエンド型安全性を提供します。

通常のTypeScriptと同様に、レスポンスデータの型付けが可能です。例えば:

app/page.tsx
TypeScript
async function getData() {
  const res = await fetch('https://api.example.com/...')
  // 戻り値は*シリアライズされません*
  // Date、Map、Setなどを返すことができます
  return res.json()
}
 
export default async function Page() {
  const name = await getData()
 
  return '...'
}

完全なエンドツーエンド型安全性を実現するには、データベースやコンテンツプロバイダがTypeScriptをサポートしている必要もあります。これはORMや型安全なクエリビルダーを使用することで実現できます。

next.config.tsの型チェック

next.config.tsを使用して、Next.js設定でTypeScriptを使い、型をインポートすることができます。

next.config.ts
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  /* ここに設定オプション */
}
 
export default nextConfig

補足: next.config.tsでのモジュール解決は現在CommonJSに限定されています。これにより、next.config.tsで読み込まれるESMのみのパッケージとの非互換性が発生する可能性があります。

next.config.jsファイルを使用する場合、以下のようにJSDocを使用してIDEで型チェックを追加できます:

next.config.js
// @ts-check
 
/** @type {import('next').NextConfig} */
const nextConfig = {
  /* ここに設定オプション */
}
 
module.exports = nextConfig

静的に型付けされたリンク

Next.jsはnext/linkを使用する際のタイプミスやその他のエラーを防ぐために、リンクを静的に型付けすることができ、ページ間のナビゲーション時の型安全性を向上させます。

この機能を利用するには、experimental.typedRoutesを有効にし、プロジェクトでTypeScriptを使用している必要があります。

next.config.ts
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  experimental: {
    typedRoutes: true,
  },
}
 
export default nextConfig

Next.jsは.next/typesにリンク定義を生成し、アプリケーション内の既存のすべてのルートに関する情報を含めます。TypeScriptはこれを使用して、無効なリンクに関するフィードバックをエディタで提供できます。

現在、実験的なサポートには動的セグメントを含むすべての文字列リテラルが含まれています。リテラルでない文字列については、現在hrefas Routeで手動でキャストする必要があります:

import type { Route } from 'next';
import Link from 'next/link'
 
// hrefが有効なルートの場合、TypeScriptエラーはありません
<Link href="/about" />
<Link href="/blog/nextjs" />
<Link href={`/blog/${slug}`} />
<Link href={('/blog' + slug) as Route} />
 
// hrefが有効なルートでない場合、TypeScriptエラーが発生します
<Link href="/aboot" />

next/linkをラップするカスタムコンポーネントでhrefを受け入れるには、ジェネリックを使用します:

import type { Route } from 'next'
import Link from 'next/link'
 
function Card<T extends string>({ href }: { href: Route<T> | URL }) {
  return (
    <Link href={href}>
      <div>My Card</div>
    </Link>
  )
}

仕組み

next devまたはnext buildを実行すると、Next.jsはアプリケーション内の既存のすべてのルート(Linkhref型として有効なすべてのルート)に関する情報を含む隠れた.d.tsファイルを.next内に生成します。この.d.tsファイルはtsconfig.jsonに含まれており、TypeScriptコンパイラはその.d.tsをチェックして、無効なリンクに関するフィードバックをエディタで提供します。

非同期サーバーコンポーネントでの使用

TypeScriptでasyncサーバーコンポーネントを使用するには、TypeScript 5.1.3以上と@types/react 18.2.8以上を使用していることを確認してください。

古いバージョンのTypeScriptを使用している場合、'Promise<Element>' is not a valid JSX elementという型エラーが表示されることがあります。TypeScriptと@types/reactを最新バージョンに更新することで、この問題が解決するはずです。

インクリメンタル型チェック

v10.2.1以降、Next.jsはtsconfig.jsonで有効にするとインクリメンタル型チェックをサポートしています。これにより、大規模なアプリケーションでの型チェックの速度を向上させることができます。

本番環境でのTypeScriptエラーの無効化

プロジェクトにTypeScriptエラーがある場合、Next.jsは本番ビルドnext build)を失敗させます。

アプリケーションにエラーがあっても、Next.jsが危険に本番コードを生成するようにしたい場合は、組み込みの型チェック手順を無効にすることができます。

無効にする場合は、ビルドまたはデプロイプロセスの一部として型チェックを実行していることを確認してください。そうでなければ非常に危険です。

next.config.tsを開き、typescript設定でignoreBuildErrorsオプションを有効にします:

next.config.ts
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  typescript: {
    // !! 警告 !!
    // プロジェクトに型エラーがあっても本番ビルドが
    // 成功するように危険に許可します。
    // !! 警告 !!
    ignoreBuildErrors: true,
  },
}
 
export default nextConfig

補足: ビルド前にTypeScriptエラーをチェックするには、tsc --noEmitを実行できます。これはデプロイ前にTypeScriptエラーをチェックしたいCI/CDパイプラインで便利です。

カスタム型宣言

カスタム型を宣言する必要がある場合、next-env.d.tsを変更したくなるかもしれませんが、このファイルは自動生成されるため、変更は上書きされます。代わりに、新しいファイル(例:new-types.d.ts)を作成し、tsconfig.jsonで参照してください:

tsconfig.json
{
  "compilerOptions": {
    "skipLibCheck": true
    //...省略...
  },
  "include": [
    "new-types.d.ts",
    "next-env.d.ts",
    ".next/types/**/*.ts",
    "**/*.ts",
    "**/*.tsx"
  ],
  "exclude": ["node_modules"]
}

バージョン変更履歴

バージョン変更内容
v15.0.0TypeScriptプロジェクト用のnext.config.tsサポートが追加されました。
v13.2.0静的に型付けされたリンクがベータ版で利用可能になりました。
v12.0.0より高速なビルドのためにSWCがデフォルトでTypeScriptとTSXをコンパイルするようになりました。
v10.2.1tsconfig.jsonで有効にするとインクリメンタル型チェックのサポートが追加されました。