コンテンツにスキップ

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 を使用して、Next.js 設定で TypeScript を使用し、型をインポートできます。

next.config.ts
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  /* config options here */
}
 
export default nextConfig

next.config.ts のモジュール解決は現在 CommonJS に限定されています。ただし、Node.js v22.10.0 以降では、Node.js ネイティブ TypeScript リゾルバを使用する場合、ECMAScript Modules (ESM) 構文が利用可能です。

next.config.js ファイルを使用する場合、JSDoc を使用して IDE で型チェックを追加できます。

next.config.js
// @ts-check
 
/** @type {import('next').NextConfig} */
const nextConfig = {
  /* config options here */
}
 
module.exports = nextConfig

next.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 はネイティブ ESM、トップレベル await および動的 import() を使用できます。このメカニズムは、Node のリゾルバの機能と制限を継承します。

Node.js バージョン v22.18.0+ では、process.features.typescript はデフォルトで有効になっています。v22.10.022.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 モジュールであることを明示的に示すことをお勧めします。

next.config.mts
import type { NextConfig } from 'next'
 
// Top-level await and dynamic import are supported
const flags = await import('./flags.js').then((m) => m.default ?? m)
 
const nextConfig: NextConfig = {
  /* config options here */
  typedRoutes: Boolean(flags?.typedRoutes),
}
 
export default nextConfig

ESM プロジェクトの場合

package.json"type""module" に設定されている場合、プロジェクトは ESM を使用します。この設定については、Node.js ドキュメント で詳細をご確認ください。この場合、next.config.ts を ESM 構文で直接記述できます。

補足: package.json"type": "module" を使用すると、プロジェクト内のすべての .js および .ts ファイルはデフォルトで ESM モジュールとして扱われます。必要に応じて、CommonJS 構文のファイル名を .cjs または .cts 拡張子にリネームする必要がある場合があります。

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

Pages および App Router の next/linkhref プロパティで機能します。App Router では、pushreplaceprefetch などの next/navigation メソッドも型付けされます。Pages Router の next/router メソッドは型付けされません。

リテラルの href 文字列は検証されますが、非リテラルの hrefas Route でキャストする必要がある場合があります。

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

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

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

補足: create-next-app なしでプロジェクトを設定した場合、生成された Next.js の型が tsconfig.jsoninclude 配列に .next/types/**/*.ts を追加することで含まれるようにしてください。

tsconfig.json
{
  "include": [
    "next-env.d.ts",
    ".next/types/**/*.ts",
    "**/*.ts",
    "**/*.tsx"
  ],
  "exclude": ["node_modules"]
}

現在、サポートには動的セグメントを含む任意の文字列リテラルが含まれます。非リテラル文字列の場合は、as Route で手動でキャストする必要があります。以下の例は、next/linknext/navigation の両方の使用方法を示しています。

app/example-client.tsx
'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: literal and dynamic */}
      <Link href="/about" />
      <Link href={`/blog/${slug}`} />
      <Link href={('/blog/' + slug) as Route} />
      {/* TypeScript error if href is not a valid route */}
      <Link href="/aboot" />
 
      {/* Router: literal and dynamic strings are validated */}
      <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>
 
      {/* For non-literal strings, cast to Route */}
      <button onClick={() => router.push(('/blog/' + slug) as Route)}>
        Push Non-literal Blog
      </button>
    </>
  )
}

リダイレクトされるルートでも同様です。

proxy.ts
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()
}
app/some/page.tsx
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>
  )
}

単純なデータ構造を型付けして、リンクをレンダリングするために反復処理することもできます。

components/nav-items.ts
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 をレンダリングします。

components/nav.tsx
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 は .next 内に非表示の .d.ts ファイルを生成し、アプリケーション内のすべての既存のルート (Linkhref 型として有効なすべてのルート) に関する情報を含みます。この .d.ts ファイルは tsconfig.json に含まれ、TypeScript コンパイラは .d.ts をチェックし、エディタで無効なリンクに関するフィードバックを提供します。

環境変数に対する型インテリセンス

開発中、Next.js は .next/types.d.ts ファイルを生成し、エディタのインテリセンスのためにロードされた環境変数に関する情報を含みます。同じ環境変数キーが複数のファイルで定義されている場合、環境変数ロード順に従って重複排除されます。

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

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

補足: 型は開発ランタイムでロードされた環境変数に基づいて生成されるため、デフォルトでは .env.production* ファイルからの変数は除外されます。本番環境固有の変数を含めるには、NODE_ENV=productionnext dev を実行してください。

静的生成とサーバーサイドレンダリング

getStaticPropsgetStaticPaths、および getServerSideProps では、それぞれ GetStaticPropsGetStaticPathsGetServerSideProps 型を使用できます。

pages/blog/[slug].tsx
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 Routes と共に

API Routes の組み込み型を使用する方法の例を以下に示します。

pages/api/hello.ts
import type { NextApiRequest, NextApiResponse } from 'next'
 
export default function handler(req: NextApiRequest, res: NextApiResponse) {
  res.status(200).json({ name: 'John Doe' })
}

レスポンスデータも型付けできます。

pages/api/hello.ts
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} />
}

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

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

カスタム tsconfig パス

場合によっては、ビルドまたはツール用に異なる TypeScript 設定を使用したい場合があります。そのために、next.config.tstypescript.tsconfigPath を設定して、Next.js が別の tsconfig ファイルを指すようにします。

next.config.ts
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  typescript: {
    tsconfigPath: 'tsconfig.build.json',
  },
}
 
export default nextConfig

たとえば、本番ビルド用に別の設定に切り替える

next.config.ts
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 でチェックを緩める場合、プロジェクトの標準に一致しない共有依存関係も検証する場合、または CI でチェックを緩めて、より厳格な TypeScript 設定への移行中にローカルで提供を継続しつつ (IDE で誤用をハイライトしたい場合)、チェックを緩める場合があります。

たとえば、プロジェクトが useUnknownInCatchVariables を使用しているが、一部のモノレポ依存関係がまだ any を想定している場合。

tsconfig.build.json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "useUnknownInCatchVariables": false
  }
}

これにより、IDE は tsconfig.json を介して厳格に保たれ、本番ビルドは緩和された設定を使用できます。

知っておくと良いこと:

  • IDE は通常、診断とインテリセンスのために tsconfig.json を読み取ります。そのため、IDE の警告は引き続き表示され、本番ビルドは代替設定を使用します。エディタで同等の機能を持たせたい場合は、重要なオプションをミラーリングしてください。
  • 開発中は、tsconfig.json のみが変更を監視されます。typescript.tsconfigPath を介して別のファイル名を編集した場合、変更を適用するには開発サーバーを再起動してください。
  • 構成されたファイルは、next devnext build、および next typegen で使用されます。

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

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

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

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

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

next.config.ts
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  typescript: {
    // !! WARN !!
    // Dangerously allow production builds to successfully complete even if
    // your project has type errors.
    // !! WARN !!
    ignoreBuildErrors: true,
  },
}
 
export default nextConfig

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

カスタム型宣言

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

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.0next.config.ts のサポートが TypeScript プロジェクトに追加されました。
v13.2.0静的に型付けされたリンクがベータ版で利用可能になりました。
v12.0.0SWC がデフォルトで使用されるようになり、TypeScript および TSX のコンパイルが高速化されました。
v10.2.1インクリメンタル型チェック のサポートが tsconfig.json で有効になった場合に利用可能になりました。