まくろぐ

Next.js のプロジェクトを TypeScript 化する

更新:
作成:

何をするか?

create-next-app コマンドで Next.js プロジェクトを生成するときに --typescript (--ts) オプションをつけて実行すると、TypeScript 対応したプロジェクトを生成することができます。

$ npx create-next-app myapp --typescript

# ただ、こっちのテンプレートを使う方法の方が若干洗練されてる気はする
$ npx create-next-app myapp --example with-typescript

また、Next.js は既存の JavaScript プロジェクトを TypeScript 化する機能も備えています。 ここから先は、その方法を説明します。

参考リンク

TypeScript 環境の導入

Next.js は、プロジェクトのルートに tsconfig.json ファイルがあると、自動的に TypeScript モードで動作するようになります。 次のようにして、空の tsconfig.json ファイルを作成し、TypeScript 用のパッケージをインストールします。

$ touch tsconfig.json
$ npm install typescript @types/node @types/react --save-dev

なんと、これだけで Next.js プロジェクトへの TypeScript 導入は完了です。 お手軽〜

自動生成される設定ファイルを見ておく

上記のステップで、TypeScript の設定ファイル (tsconfig.json) に何も記述していないことに気づいたかもしれません。 実は、Next.js のビルド(next devnext build)を実行すると、自動的に設定ファイルの内容を更新してくれるようになっています。

Next.js 開発サーバーの起動 (next dev)
$ npm run dev

例えば上記のように開発サーバーを起動すると、空っぽだった tsconfig.json が次のような内容に初期化されます。 まさにゼロコンフィグです。

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve"
  },
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

さらに、Next.js はプロジェクトのルートに next-env.d.ts というファイルを生成します。 このファイルには、Next.js が提供するコンポーネントなどの型情報が含まれています。

next-env.d.ts
/// <reference types="next" />
/// <reference types="next/types/global" />

デフォルトでは上記のような内容になっていて、node_modules/next 下にインストールされた型情報ファイルを参照するようになっています。 このファイルは Next.js が勝手に更新するので、マニュアルで更新する必要はありません。

既存の JavaScript コードを TypeScript コードに置き換える

拡張子を .js から .tsx に置換する

TypeScript 環境の導入をサクッと完了したら、既存の JavaScript ファイル (.js) を TypeScript ファイル(.ts および .tsx)に置き換えていきます。 JavaScript ファイルは pages ディレクトリ以下に格納されているので、まずは、それらのファイルの拡張子を変更します。

pages/
  +-- _app.js  (→ _app.tsx)
  +-- api/
  |     +-- hello.js  (→ hello.ts)
  +-- index.js  (→ index.tsx)

api ディレクトリの中の .js ファイルには JSX が含まれていないので、それだけは .ts にして、他のファイルは .tsx にしてしまえばよいでしょう。

厳格な型チェック(strict モード)を ON にする

ファイルの拡張子を .ts.tsx にしたので、ビルド時に TypeScript の型チェックが働くようになるはずが、npm run devnpm run build してもビルドエラーにはなりません。 なぜなら、tsconfig.jsonstrict 設定が false になっており、暗黙的な any 型の使用が許されているからです。 次のように tsconfig.json を修正して、型チェックを強制するようにしましょう。 ついでに、allowJs はもう必要ないので false にしておきます。

tsconfig.json(修正箇所抜粋)
{
  ...
  "allowJs": false,  // ← js ファイルは扱わない
  "skipLibCheck": true,
  "strict": true,  // ← 型チェックなどを厳密に行う
  ...
}

これで、ビルド時にちゃんと型情報に関するエラーを出してくれるようになります。

$ npm run build
...
Failed to compile.

./pages/_app.tsx:3:18
Type error: Binding element 'Component' implicitly has an 'any' type.
...

TypeScript コードの修正

ビルドエラーにならないように、TypeScript コードに型情報を追加していきます。

pages/_app.tsx
import type { AppProps } from 'next/app'

function MyApp({ Component, pageProps }: AppProps): JSX.Element {
  return <Component {...pageProps} />
}

export default MyApp
pages/api/hello.ts
import type { NextApiRequest, NextApiResponse } from 'next'

export default (req: NextApiRequest, res: NextApiResponse) => {
  res.status(200).json({ name: 'John Doe' })
}

これで、正しくビルドが通るようになります。 Next.js が提供する他の型情報に関しては、下記のサイトを参考にしてください。

おまけ(example オプションでさまざまな環境が整ったプロジェクトを作成する)

create-next-app コマンドで Next.js プロジェクトを作成するときに、--example オプションを使用すると、GitHub 上の任意のテンプレートを使ってプロジェクトを作成できます。 Next.js (Vercel) 公式のテンプレートが、下記のリポジトリにたくさん用意されています。

例えば、TypeScript + ESLint + Jest 導入済みのテンプレートである with-typescript-eslint-jest を使って Next.js プロジェクトを作成したいときは、次のように create-next-app コマンドを実行します。

$ npx create-next-app myapp --example with-typescript-eslint-jest

こうすれば、最初から色々な環境が整った状態でプロジェクトが作成されるので、すぐに本質的な開発作業に取りかかることができます。 とはいえ、 ひとつずつ手作業で導入していった方が理解しやすいという側面もあるので、好きな導入方法を選べばよいと思います。

関連記事

まくろぐ
サイトマップまくへのメッセージ