TypeScript
Next.jsには組み込みのTypeScriptが付属しており、create-next-appで新しいプロジェクトを作成する際に必要なパッケージを自動的にインストールし、適切な設定を構成します。
既存プロジェクトにTypeScriptを追加するには、ファイル名を.ts/.tsxに変更します。next devとnext buildを実行すると、必要な依存関係が自動的にインストールされ、推奨される設定オプション付きのtsconfig.jsonファイルが追加されます。
補足:既に
jsconfig.jsonファイルが存在する場合は、古いjsconfig.jsonからpathsコンパイラオプションを新しいtsconfig.jsonファイルにコピーし、古いjsconfig.jsonファイルを削除してください。
例
Next.js設定ファイルの型チェック
next.config.tsを使用して、TypeScriptをインポートし、Next.js設定で型を使用できます。
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  /* config options here */
}
 
export default nextConfignext.config.ts内のモジュール解決は現在、CommonJSに限定されています。ただし、ECMAScriptモジュール(ESM)構文は、Node.js v22.10.0以上でNode.jsネイティブTypeScript解決器を使用する場合に利用できます。
next.config.jsファイルを使用する場合は、以下のようにJSDocを使用してIDEで型チェックを追加できます:
// @ts-check
 
/** @type {import('next').NextConfig} */
const nextConfig = {
  /* config options here */
}
 
module.exports = nextConfignext.config.tsにNode.jsネイティブTypeScript解決器を使用する
注意:Node.js v22.10.0以上で、機能が有効になっている場合のみ利用可能です。Next.jsはそれを有効にしません。
Next.jsはNode.jsネイティブTypeScript解決器をprocess.features.typescriptを介して検出します。これはv22.10.0で追加されました。存在する場合、next.config.tsはトップレベルのawaitとダイナミックimport()を含むネイティブESMを使用できます。このメカニズムはNode解決器の機能と制限を継承します。
Node.jsバージョンv22.18.0以上では、process.features.typescriptはデフォルトで有効になっています。v22.10.0から22.17.xの間のバージョンについては、NODE_OPTIONS=--experimental-transform-typesでオプトインします:
NODE_OPTIONS=--experimental-transform-types next <command>CommonJSプロジェクト(デフォルト)の場合
next.config.tsはCommonJSプロジェクトでネイティブESM構文をサポートしていますが、Node.jsはデフォルトではnext.config.tsをCommonJSファイルと想定しており、モジュール構文が検出されるとNode.jsはファイルをESMとして再解析します。したがって、CommonJSプロジェクトの場合はnext.config.mtsファイルの使用をお勧めします。これはESMモジュールであることを明示的に示します:
import type { NextConfig } from 'next'
 
// トップレベルのawaitとダイナミックimportがサポートされています
const flags = await import('./flags.js').then((m) => m.default ?? m)
 
const nextConfig: NextConfig = {
  /* config options here */
  typedRoutes: Boolean(flags?.typedRoutes),
}
 
export default nextConfigESMプロジェクトの場合
package.jsonで"type"が"module"に設定されている場合、プロジェクトはESMを使用しています。この設定について詳しくはNode.jsドキュメントをご覧ください。この場合、ESM構文を使用してnext.config.tsを直接書くことができます。
補足:
package.jsonで"type": "module"を使用している場合、プロジェクト内のすべての.jsと.tsファイルはデフォルトでESMモジュールとして扱われます。必要に応じて、CommonJS構文を使用したファイルの名前を.cjsまたは.cts拡張子に変更する必要があります。
静的に型付けされたリンク
Next.jsはnext/linkを使用する場合、リンクを静的に型付けしてタイプミスなどのエラーを防ぎ、ページ間のナビゲーション時の型安全性を向上させることができます。
PagesルーターとApp Routerの両方でnext/linkのhrefプロップで機能します。App Routerでは、next/navigationのメソッド(push、replace、prefetchなど)も型付けされます。PagesRouterのnext/routerメソッドは型付けされません。
リテラルhref文字列は検証され、非リテラルhrefにはas Routeでのキャストが必要な場合があります。
この機能をオプトインするには、typedRoutesを有効にし、プロジェクトがTypeScriptを使用している必要があります。
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  typedRoutes: true,
}
 
export default nextConfigNext.jsはアプリケーション内のすべての既存ルートに関する情報を含むリンク定義を.next/typesに生成し、TypeScriptはエディタで無効なリンクに関するフィードバックを提供するためにこれを使用できます。
補足:
create-next-appなしでプロジェクトをセットアップした場合は、生成されたNext.js型を含めることを確認してください。tsconfig.jsonのinclude配列に.next/types/**/*.tsを追加してください:
{
  "include": [
    "next-env.d.ts",
    ".next/types/**/*.ts",
    "**/*.ts",
    "**/*.tsx"
  ],
  "exclude": ["node_modules"]
}現在、サポートはダイナミックセグメントを含むあらゆる文字列リテラルに対応しています。非リテラル文字列については、as Routeで手動キャストが必要です。以下の例はnext/linkとnext/navigationの使用方法を示しています:
'use client'
 
import type { Route } from 'next'
import Link from 'next/link'
import { useRouter } from 'next/navigation'
 
export default function Example() {
  const router = useRouter()
  const slug = 'nextjs'
 
  return (
    <>
      {/* Link: リテラルとダイナミック */}
      <Link href="/about" />
      <Link href={`/blog/${slug}`} />
      <Link href={('/blog/' + slug) as Route} />
      {/* hrefが有効なルートでない場合、TypeScriptエラーが発生します */}
      <Link href="/aboot" />
 
      {/* Router: リテラルとダイナミック文字列が検証されます */}
      <button onClick={() => router.push('/about')}>Push About</button>
      <button onClick={() => router.replace(`/blog/${slug}`)}>
        Replace Blog
      </button>
      <button onClick={() => router.prefetch('/contact')}>
        Prefetch Contact
      </button>
 
      {/* 非リテラル文字列の場合、Routeにキャストします */}
      <button onClick={() => router.push(('/blog/' + slug) as Route)}>
        Push Non-literal Blog
      </button>
    </>
  )
}同じことはプロキシで定義されたリダイレクトルートに適用されます:
import { NextRequest, NextResponse } from 'next/server'
 
export function proxy(request: NextRequest) {
  if (request.nextUrl.pathname === '/proxy-redirect') {
    return NextResponse.redirect(new URL('/', request.url))
  }
 
  return NextResponse.next()
}import type { Route } from 'next'
 
export default function Page() {
  return <Link href={'/proxy-redirect' as Route}>Link Text</Link>
}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>
  )
}シンプルなデータ構造を型付けして反復処理し、リンクをレンダリングすることもできます:
import type { Route } from 'next'
 
type NavItem<T extends string = string> = {
  href: T
  label: string
}
 
export const navItems: NavItem<Route>[] = [
  { href: '/', label: 'Home' },
  { href: '/about', label: 'About' },
  { href: '/blog', label: 'Blog' },
]次に、項目をマッピングしてLinkをレンダリングします:
import Link from 'next/link'
import { navItems } from './nav-items'
 
export function Nav() {
  return (
    <nav>
      {navItems.map((item) => (
        <Link key={item.href} href={item.href}>
          {item.label}
        </Link>
      ))}
    </nav>
  )
}どのように機能しますか?
next devまたはnext buildを実行するときは、Next.jsはアプリケーション内のすべての既存ルートに関する情報を含む隠しファイル.d.tsを.next内に生成します(Linkのhref型としてのすべての有効なルート)。この.d.tsファイルはtsconfig.jsonに含まれており、TypeScriptコンパイラはこの.d.tsをチェックし、エディタで無効なリンクに関するフィードバックを提供します。
環境変数のType IntelliSense
開発中、Next.jsはエディタのIntelliSenseのための読み込まれた環境変数に関する情報を含む.d.tsファイルを.next/typesに生成します。同じ環境変数キーが複数のファイルで定義されている場合、環境変数ロード順序に従って重複が排除されます。
この機能をオプトインするには、experimental.typedEnvを有効にし、プロジェクトがTypeScriptを使用している必要があります。
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  experimental: {
    typedEnv: true,
  },
}
 
export default nextConfig補足:型は開発実行時に読み込まれた環境変数に基づいて生成され、デフォルトでは
.env.production*ファイルからの変数が除外されます。本番環境固有の変数を含めるには、NODE_ENV=productionでnext devを実行してください。
静的生成とサーバー側レンダリング
getStaticProps、getStaticPaths、getServerSidePropsについては、それぞれGetStaticProps、GetStaticPaths、GetServerSideProps型を使用できます:
import type { GetStaticProps, GetStaticPaths, GetServerSideProps } from 'next'
 
export const getStaticProps = (async (context) => {
  // ...
}) satisfies GetStaticProps
 
export const getStaticPaths = (async () => {
  // ...
}) satisfies GetStaticPaths
 
export const getServerSideProps = (async (context) => {
  // ...
}) satisfies GetServerSideProps補足:
satisfiesはTypeScript 4.9で追加されました。最新バージョンのTypeScriptへのアップグレードをお勧めします。
APIルートの使用
以下はAPIルートに組み込み型を使用する方法の例です:
import type { NextApiRequest, NextApiResponse } from 'next'
 
export default function handler(req: NextApiRequest, res: NextApiResponse) {
  res.status(200).json({ name: 'John Doe' })
}レスポンスデータを型付けすることもできます:
import type { NextApiRequest, NextApiResponse } from 'next'
 
type Data = {
  name: string
}
 
export default function handler(
  req: NextApiRequest,
  res: NextApiResponse<Data>
) {
  res.status(200).json({ name: 'John Doe' })
}カスタムAppの使用
カスタムAppがある場合は、組み込み型AppPropsを使用し、ファイル名を./pages/_app.tsxのように変更できます:
import type { AppProps } from 'next/app'
 
export default function MyApp({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />
}インクリメンタル型チェック
Next.js v10.2.1以降、tsconfig.jsonで有効になっている場合、インクリメンタル型チェックをサポートしています。これは大規模なアプリケーションで型チェックの高速化に役立つ可能性があります。
カスタムtsconfigパス
場合によっては、ビルドまたはツール用に異なるTypeScript設定を使用したい場合があります。そのためには、next.config.tsでtypescript.tsconfigPathを設定して、Next.jsに別のtsconfigファイルをポイントさせます。
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  typescript: {
    tsconfigPath: 'tsconfig.build.json',
  },
}
 
export default nextConfig例えば、本番ビルド用に別の設定に切り替えます:
import type { NextConfig } from 'next'
 
const isProd = process.env.NODE_ENV === 'production'
 
const nextConfig: NextConfig = {
  typescript: {
    tsconfigPath: isProd ? 'tsconfig.build.json' : 'tsconfig.json',
  },
}
 
export default nextConfigビルド用に別のtsconfigを使用する理由
モノレポなどのシナリオで別の設定が必要な場合があります。ビルドはプロジェクトの標準に適合しない共有依存関係を検証したり、CIで厳密なTypeScript設定に移行するために検査を緩和してデリバリを続けたい場合(同時にIDEに誤用を強調してほしい場合)があります。
例えば、プロジェクトがuseUnknownInCatchVariablesを使用していても、モノレポ依存関係の一部がまだanyを想定している場合:
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "useUnknownInCatchVariables": false
  }
}これにより、エディタはtsconfig.jsonを通じて厳密な状態に保ちながら、本番ビルドは緩和された設定を使用できます。
補足:
- IDEは通常、診断とIntelliSenseのために
tsconfig.jsonを読み取るため、本番ビルドが別の設定を使用する場合でもIDEの警告を表示できます。エディタでのパリティが必要な場合は、重要なオプションをミラーリングしてください。- 開発では、
tsconfig.jsonのみ変更が監視されます。typescript.tsconfigPathで別のファイル名を編集する場合は、開発サーバーを再起動して変更を適用してください。- 設定されたファイルは
next dev、next build、next typegenで使用されます。
本番環境でのTypeScriptエラーの無効化
Next.jsは、プロジェクトにTypeScriptエラーが存在する場合、本番ビルド(next build)を失敗させます。
アプリケーションにエラーがあっても、Next.jsが危険な方法で本番コードを生成するようにしたい場合は、組み込み型チェックステップを無効にすることができます。
無効にした場合は、ビルドまたはデプロイプロセスの一部として型チェックを実行していることを確認してください。そうしないと、非常に危険な可能性があります。
next.config.tsを開き、typescript設定でignoreBuildErrorsオプションを有効にします:
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で参照する必要があります:
{
  "compilerOptions": {
    "skipLibCheck": true
    //...truncated...
  },
  "include": [
    "new-types.d.ts",
    "next-env.d.ts",
    ".next/types/**/*.ts",
    "**/*.ts",
    "**/*.tsx"
  ],
  "exclude": ["node_modules"]
}バージョン変更
| バージョン | 変更内容 | 
|---|---|
| v15.0.0 | TypeScriptプロジェクト向けの next.config.tsサポートが追加されました。 | 
| v13.2.0 | 静的に型付けされたリンクがベータで利用可能になりました。 | 
| v12.0.0 | SWCがデフォルトでTypeScriptとTSXをコンパイルするために使用されるようになり、ビルドが高速化されました。 | 
| v10.2.1 | tsconfig.jsonで有効になっている場合、インクリメンタル型チェックサポートが追加されました。 |