言語を切り替える
テーマを切り替える

Next.js TypeScript 設定完全ガイド:tsconfig 最適化と型安全の実践

午前3時、私はテストレポートのあの眩しい赤い文字を見つめていました。「Production Error: Cannot read property ‘id’ of undefined」。ユーザーからのフィードバックによると、マイページをクリックした瞬間に画面が真っ白になったそうです。コードを見返してみると、ルートが /user/profile ではなく /users/profile になっていました。余計な s がついていたのです。TypeScript からは何のヒントもなく、IDE もエラーを出しませんでした。そしてそのまま堂々とリリースされてしまったのです。

「ただの凡ミスじゃないか」と思うかもしれません。確かにそうです。でも正直なところ、私が保守しているプロジェクトでこの種の「凡ミス」が発生する頻度は、心が折れるほど高いのです。ルートのスペルミス、環境変数名のタイプミス、関数引数の型が全部 any… TypeScript は「型安全」を謳っているのに、実際に使ってみると JavaScript と大差ないように感じていました。

その後、悪いのは TypeScript ではなく、私の設定がひどすぎたのだと気づきました。tsconfig.json には選択肢が山ほどあり、どれをオンにしてどれをオフにすべきかわからない。ネット上のチュートリアルは言うことがまちまちで、ある人は「厳格モードは開発の負担を増やす」と言い、別の人は「厳格モードをオンにしないのは無意味だ」と言います。Next.js + TypeScript を1年近くやってきて、プロジェクトの中は any だらけでした。

この記事では、この1年間の試行錯誤の末にまとめた経験について話したいと思います。tsconfig の最適化設定から、型安全なルーティングの実装、環境変数の型定義まで、TypeScript を「つまずきの石」から「守護神」へと変える方法をステップバイステップで解説します。高尚な理論ではなく、実務ですぐに使える内容です。

tsconfig 最適化設定 - 基礎を固める

strict モードの真の意味

多くの人(以前の私を含む)は、strict: true は単なるスイッチで、オンにすると TypeScript が厳しくなるだけだと思っています。しかし、実はそうではありません。

TypeScript 公式ドキュメントを見ると、strict は実際には7つのコンパイラオプションのショートカットであることがわかります:

{
  "compilerOptions": {
    "strict": true,
    // 以下の7つがすべて true になるのと等価です
    "strictNullChecks": true,        // 厳格な null チェック
    "strictFunctionTypes": true,     // 厳格な関数型チェック
    "strictBindCallApply": true,     // 厳格な bind/call/apply チェック
    "strictPropertyInitialization": true, // 厳格なプロパティ初期化
    "noImplicitAny": true,          // 暗黙の any を禁止
    "noImplicitThis": true,         // 暗黙の this を禁止
    "alwaysStrict": true            // 常に厳格モードで解析
  }
}

最も有用なのは最初の3つです。まず strictNullChecks ですが、これをオンにすると、TypeScript は nullundefined を「あらゆる型の有効な値」ではなく、独立した型として扱います。

例を挙げましょう。データベースからユーザー情報を検索するとします:

// strictNullChecks オフ
const user = await db.user.findOne({ id: userId })
console.log(user.name) // TypeScript はエラーを出さないが、user は null の可能性がある

// オンにした場合
const user = await db.user.findOne({ id: userId })
console.log(user.name) // ❌ TypeScript エラー:オブジェクトは 'null' である可能性があります

// こう書く必要があります
if (user) {
  console.log(user.name) // ✅ OK
}

以前、古いプロジェクトで初めてこのオプションをオンにしたとき、IDE が瞬時に200以上の赤い波線で埋め尽くされました。パニックになり、危うく元に戻すところでした。しかし冷静になって見てみると、これらの「エラー」は実はすべて潜在的なバグ——null チェックが行われていない箇所であり、オンライン環境で本当にクラッシュする可能性がある場所でした。

noImplicitAny も非常に重要です。これは関数の引数や変数が「暗黙的に」any 型になることを禁止します:

// noImplicitAny オフ
function handleData(data) {  // data は自動的に any になる
  return data.value  // どんな操作もエラーにならない
}

// オンにした場合
function handleData(data) {  // ❌ エラー:パラメータには暗黙的に 'any' 型が含まれます
  return data.value
}

// 明示的な注釈が必要
function handleData(data: { value: string }) {  // ✅
  return data.value
}

正直なところ、最初は面倒に感じるでしょう。以前は適当に関数を書けましたが、今は型を定義しなければなりません。しかし、しばらく使っていると、IDE のヒントが賢くなることに気づくはずです。data. と入力した瞬間にすべてのプロパティが表示され、ドキュメントを見に行く必要がなくなります。

Next.js 特有の TypeScript 設定

Next.js プロジェクトの tsconfig.json にはいくつか特別な設定があります。私が現在使用しているベストプラクティス版を共有します:

{
  "compilerOptions": {
    // 基本設定
    "target": "ES2020",
    "lib": ["dom", "dom.iterable", "esnext"],
    "jsx": "preserve",
    "module": "esnext",
    "moduleResolution": "bundler",

    // Next.js 必須
    "allowJs": true,
    "noEmit": true,
    "esModuleInterop": true,
    "isolatedModules": true,
    "resolveJsonModule": true,

    // 厳格モード(コア)
    "strict": true,
    "skipLibCheck": true,

    // パフォーマンス最適化
    "incremental": true,

    // Next.js プラグイン
    "plugins": [
      {
        "name": "next"
      }
    ],

    // パスエイリアス
    "paths": {
      "@/*": ["./src/*"],
      "@/components/*": ["./src/components/*"],
      "@/lib/*": ["./src/lib/*"],
      "@/styles/*": ["./src/styles/*"]
    }
  },
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx",
    ".next/types/**/*.ts"
  ],
  "exclude": ["node_modules"]
}

いくつか見落としがちな重要ポイントを解説します:

1. incremental:増分コンパイル

60%
コンパイル速度向上

このオプションは、大規模プロジェクトのコンパイル速度を大幅に向上させます。オンにすると、TypeScript は前回のコンパイル情報をキャッシュし、次回は変更されたファイルのみをコンパイルします。300以上のコンポーネントがあるプロジェクトでテストしたところ、コンパイル時間が45秒から約18秒に短縮されました。効果は絶大です。

2. paths:パスエイリアス

以前のインポートパスはこんな感じでした:

import Button from '../../../components/ui/Button'
import { formatDate } from '../../../../lib/utils'

.. がいくつあるか数えるのも面倒ですし、フォルダ構造を少し変えるだけですべてエラーになります。

エイリアスを設定した後:

import Button from '@/components/ui/Button'
import { formatDate } from '@/lib/utils'

ずっとすっきりしました。しかも TypeScript は型を正しく推論し、IDE のジャンプ機能も使えます。

3. plugins:Next.js プラグイン

"plugins": [{ "name": "next" }] は単純に見えますが、これによって TypeScript が app ディレクトリ下の layout.tsxpage.tsx などの特殊なファイルの型や、サーバーコンポーネントとクライアントコンポーネントの区別など、Next.js 特有の概念を理解できるようになります。

このプラグインを追加しないと、サーバーコンポーネントを書くときに TypeScript が意味不明な型エラーを出す可能性があります。

段階的な厳格モードの導入

プロジェクトが既にしばらく稼働していて、コード量も少なくない場合、いきなり strict: true をオンにするのは確かに苦痛です。私のアドバイスは、「無理をしない」ことです。

戦略1:新しいコードは厳格に、古いコードはゆっくり直す

tsconfig.json では strict: true を維持しつつ、一時的に修正しきれない古いファイルの先頭に以下を追加します:

// @ts-nocheck  // ファイル全体の型チェックをスキップ

または特定の行に対して:

// @ts-ignore  // 次の行の型エラーを無視

ただし、@ts-ignore@ts-expect-error には違いがあることに注意してください:

// @ts-ignore
const x = 1 as any  // 次の行にエラーがなくても文句を言わない

// @ts-expect-error
const y = 1  // 次の行にエラーがない場合、TypeScript は「不要なコメント」だと警告する

私は @ts-expect-error を推奨します。これは「コメントの消し忘れ」を防いでくれます。バグ修正後に TypeScript が「このコメントはもう必要ないよ」と教えてくれるからです。

戦略2:機能モジュールごとに段階的にオンにする

例えば、まずは components ディレクトリ下のファイルをきれいにし、他のディレクトリは一時的に緩くします。このように設定できます:

// tsconfig.strict.json(厳格モード)
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "strict": true
  },
  "include": ["src/components/**/*"]
}

普段の開発では通常の tsconfig.json を使い、あるモジュールをリファクタリングするときだけ strict 版に切り替えます。

厳格モードは私たちを苦しめるためのものではありません。ある古いコンポーネントをリファクタリングしたとき、strictNullChecks をオンにして5箇所の null チェック漏れを発見しました。そのうち3箇所は本番環境ですでにエラーを起こしていましたが、try-catch に握りつぶされて表面化していなかっただけでした。その瞬間、これらの赤い波線がとても愛おしく思えました。

型安全なルーティングの実装 - スペルミスとの決別

Next.js 内蔵の Typed Routes

冒頭で触れたオンラインバグを覚えていますか? ルートに s を余分につけてしまい、ページが 404 になった件です。この種のエラーは完全に回避できます。

Next.js 13 は typedRoutes という実験的機能を導入しました。これをオンにすると、TypeScript はすべてのルートの型定義を生成します。

有効化する方法

next.config.ts に1行追加します:

// next.config.ts
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  experimental: {
    typedRoutes: true,  // 型安全なルートを有効化
  },
}

export default nextConfig

そして開発サーバーを再起動(npm run dev)すると、Next.js は自動的に app ディレクトリをスキャンし、.next/types フォルダ内にルート型定義を生成します。

どんな効果があるか?

プロジェクト構造が以下のようだとします:

app/
├── page.tsx           // トップページ
├── blog/
│   ├── page.tsx      // ブログ一覧
│   └── [slug]/
│       └── page.tsx  // ブログ詳細
└── user/
    └── [id]/
        └── profile/
            └── page.tsx  // ユーザープロフィール

typedRoutes を有効にすると、Link コンポーネントや useRouter でルートを書く際、IDE が自動補完してくれます:

import Link from 'next/link'

export default function Nav() {
  return (
    <nav>
      <Link href="/">トップ</Link>
      <Link href="/blog">ブログ</Link>
      <Link href="/blog/hello-world">記事詳細</Link>
      <Link href="/user/123/profile">プロフィール</Link>

      {/* ❌ TypeScript エラー:ルートが存在しません */}
      <Link href="/users/123/profile" />  // ここが user ではなく users になっている
    </nav>
  )
}

href="/ と入力した時点で、IDE は使用可能なすべてのルートをポップアップ表示します。間違って書くとすぐに赤くなります。

嘘ではありません、この機能を初めて体験したとき、心に浮かんだのは「最高」の一言でした。

制限事項

ただし、この機能には現在いくつかの制限があります:

  1. App Router のみサポート:プロジェクトがまだ pages ディレクトリを使用している場合、この機能は使えません。
  2. 動的ルートパラメータは手動で渡す必要がある:例えば /blog/[slug] の場合、slug の値は自分で結合する必要があります。
  3. クエリパラメータはチェックされない/user?tab=settingstab パラメータは型チェックされません。

要するに、パス自体のスペルミスがないことは保証されますが、パラメータ値は自分で注意する必要があります。

サードパーティライブラリ:nextjs-routes

もしあなたがまだ pages ディレクトリを使っていたり、より完全なルート型安全性(クエリパラメータを含む)を求めているなら、nextjs-routes というライブラリを試してみてください。

インストールと設定:

npm install nextjs-routes

そして next.config.ts に追加します:

const nextRoutes = require('nextjs-routes/config')

const nextConfig = nextRoutes({
  // 元の Next.js設定
})

export default nextConfig

使用方法:

このライブラリは route 関数を生成し、オブジェクト形式でルートを定義できるようにします:

import { route } from 'nextjs-routes'

// 型安全なルートオブジェクト
const profileRoute = route({
  pathname: '/user/[id]/profile',
  query: {
    id: '123',
    tab: 'settings',  // クエリパラメータも型チェックされる
  }
})

router.push(profileRoute)  // 完全に型安全

// パスを間違えた場合
const wrongRoute = route({
  pathname: '/users/[id]/profile',  // ❌ TypeScript エラー:パスが存在しません
})

Next.js 内蔵ソリューションと比較した場合の nextjs-routes の利点:

  • pages ディレクトリをサポート
  • クエリパラメータの型チェックあり
  • 文字列の手動結合ではなく、オブジェクト形式でルートを定義できる

欠点は、追加の依存関係が必要であることと、ルート構造を変更するたびに型ファイルを再生成する必要があることです(ただしこれは自動です)。

ルートパラメータの型推論

動的ルートのパラメータはどうでしょうか? 例えば app/blog/[slug]/page.tsxslug パラメータの型は何でしょうか?

Next.js は params の型を自動的に生成します:

// app/blog/[slug]/page.tsx
export default function BlogPost({
  params,
}: {
  params: { slug: string }
}) {
  return <h1>記事:{params.slug}</h1>
}

しかし、問題は slug が単なる string 型であり、どんな文字列でも入ってくる可能性があることです。もっと厳格にしたい場合——例えば特定フォーマットの slug のみを許可したい場合は、zod を使ってランタイム検証を行います:

import { z } from 'zod'

const slugSchema = z.string().regex(/^[a-z0-9-]+$/)

export default function BlogPost({
  params,
}: {
  params: { slug: string }
}) {
  // slug フォーマットを検証
  const validatedSlug = slugSchema.parse(params.slug)

  return <h1>記事:{validatedSlug}</h1>
}

slug がフォーマットに合わない(大文字や特殊文字が含まれているなど)場合、zod はエラーを投げます。

これは API ルートを処理する際に特に役立ちます。ユーザーが何を送信してくるかは制御できないので、事前に検証することはオンライン爆発を防ぐよりも優れています。

環境変数の型定義 - any を完全に排除する

問題の根本

環境変数に関して言えば、TypeScript のデフォルトサポートは実にお粗末です。

こんなコードを書いたことがあるはずです:

const apiKey = process.env.API_KEY

マウスを apiKey に合わせると、型は string | undefined です。まあ、少なくとも undefined の可能性があることはわかっています。

しかし、より一般的な状況はこれです:

const apiUrl = process.env.NEXT_PUBLIC_API_URL
console.log(apiUrl.toUpperCase())  // ランタイムエラー:apiUrl is undefined

TypeScript はエラーを出さず、実行時に初めて環境変数が設定されていないことに気づきます。

さらに、環境変数名のスペルミスも TypeScript は検知しません:

const key = process.env.API_SECRE  // 少打了个 T
// TypeScript:問題ありません、これは string | undefined です

これは非常に気まずいです。TypeScript を使っているのに、結局は目視で変数名をチェックしなければならないなんて、JavaScript を書いているのと何の違いがあるでしょうか?

T3 Env ソリューションの使用(推奨)

この問題を解決するために、現在コミュニティで最も支持されているソリューションは T3 Env です。これは型チェックランタイム検証の両方を提供します。

インストール:

npm install @t3-oss/env-nextjs zod

設定:

プロジェクトルートに env.mjs(または env.ts)を作成します:

import { createEnv } from "@t3-oss/env-nextjs"
import { z } from "zod"

export const env = createEnv({
  // サーバーサイド環境変数(クライアントからはアクセス不可)
  server: {
    DATABASE_URL: z.string().url(),
    API_SECRET: z.string().min(32),
    SMTP_HOST: z.string().min(1),
  },

  // クライアントサイド環境変数(NEXT_PUBLIC_ で始まる必要あり)
  client: {
    NEXT_PUBLIC_APP_URL: z.string().url(),
    NEXT_PUBLIC_ANALYTICS_ID: z.string().optional(),
  },

  // ランタイム環境変数マッピング
  runtimeEnv: {
    DATABASE_URL: process.env.DATABASE_URL,
    API_SECRET: process.env.API_SECRET,
    SMTP_HOST: process.env.SMTP_HOST,
    NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
    NEXT_PUBLIC_ANALYTICS_ID: process.env.NEXT_PUBLIC_ANALYTICS_ID,
  },
})

使用:

import { env } from './env.mjs'

// ✅ 完全に型安全、自動補完あり
const dbUrl = env.DATABASE_URL  // string
const appUrl = env.NEXT_PUBLIC_APP_URL  // string

// ❌ TypeScript エラー:スペルミス
const wrong = env.DATABASE_UR

// ❌ TypeScript エラー:クライアントはサーバー変数にアクセス不可
// クライアントコンポーネント内
'use client'
const secret = env.API_SECRET  // コンパイルエラー

最高のポイント:

  1. 起動時検証:環境変数が欠けていたりフォーマットが間違っていたりすると、実行時ではなくアプリ起動時にエラーになります。
  2. 型推論:すべての環境変数が正確な型を持ち、もはや string | undefined ではありません。
  3. 漏洩防止:クライアントコードがサーバー変数にアクセスすると、コンパイルエラーになります。

T3 Env を使う前は、テスト環境である環境変数の設定を忘れてサービスが起動せず、ログを調べて初めて何が足りないか気付く、ということがよくありました。今では起動時にわかるので、時間を大幅に節約できています。

カスタム型定義ファイルソリューション

T3 Env を導入したくない場合や、プロジェクト規模が小さい場合は、手動で ProcessEnv 型を拡張することもできます:

// env.d.ts
namespace NodeJS {
  interface ProcessEnv {
    // サーバー変数
    DATABASE_URL: string
    API_SECRET: string
    SMTP_HOST: string

    // クライアント変数
    NEXT_PUBLIC_APP_URL: string
    NEXT_PUBLIC_ANALYTICS_ID?: string  // オプション変数は ? を使う
  }
}

これで TypeScript はこれらの変数の型を認識します:

const dbUrl = process.env.DATABASE_URL  // string
const apiSecret = process.env.API_SECRET  // string

// ❌ TypeScript エラー
const wrong = process.env.DATABASE_UR  // Property 'DATABASE_UR' does not exist

欠点:

  • ランタイム検証がないため、環境変数の欠落は実行時まで気づかない
  • クライアントからのサーバー変数アクセスを防げない
  • 型定義を手動でメンテナンスする必要がある

小規模なプロジェクトや、型安全性の要求がそれほど高くないシナリオに適しています。しかし正直なところ、せっかく TypeScript を使っているなら、T3 Env で一発解決することをお勧めします。

TypeScript 厳格モードの応用 - 実践テクニック

サードパーティライブラリの型問題の処理

時にはあなたのコードではなく、サードパーティライブラリが型定義を提供していなかったり、型定義にバグがあったりすることがあります。

ケース1:ライブラリに型定義が全くない

古いnpmパッケージを使っていて、import したら全部 any になる場合:

import oldLib from 'some-old-lib'  // any

まず npm で @types/some-old-lib があるか検索しましょう:

npm install -D @types/some-old-lib

なければ、自分で書く必要があります。types/some-old-lib.d.ts を作成します:

declare module 'some-old-lib' {
  export function doSomething(param: string): number
  export default someOldLib
}

これで TypeScript はこのライブラリの型を認識します。

ケース2:型定義に問題がある

@types パッケージの型定義が実際の API と一致しないことがあります(特に更新の速いライブラリ)。この場合、「型アサーション」で一時的に対処できます:

import { someFunction } from 'buggy-lib'

// 型定義は string を返すとあるが、実際は number
const result = someFunction() as unknown as number

ただしこれは一時的な解決策であり、ライブラリの GitHub で issue か PR を出すのがベストです。

skipLibCheck はオンにすべき?

tsconfig に skipLibCheck オプションがあります。これをオンにすると、TypeScript は node_modules 内の型チェックをスキップします。

私のアドバイスは:オンにすることです。

なぜなら、node_modules 内の型エラーはあなたが修正できるものではなく、コンパイル速度を低下させるからです。サードパーティライブラリの型問題をチェックさせるより、自分のコードに集中したほうがいいでしょう。

よくある any 逃れシナリオと解決策

厳格モードをオンにしていても、any 型が「逃げ出す」場所がいくつかあります。

シナリオ1:イベントハンドラ

// ❌ 悪い例
const handleSubmit = (e: any) => {
  e.preventDefault()
}

// ✅ 正しい例
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
  e.preventDefault()
  // e.currentTarget が完全な型ヒントを持つ
}

よく使うイベントタイプ:

  • React.MouseEvent<HTMLButtonElement>
  • React.ChangeEvent<HTMLInputElement>
  • React.KeyboardEvent<HTMLDivElement>

シナリオ2:API レスポンスデータ

// ❌ 悪い例
const res = await fetch('/api/user')
const data = await res.json()  // any

// ✅ 案1:インターフェースを手動定義
interface User {
  id: string
  name: string
  email: string
}

const data: User = await res.json()

// ✅ 案2:zod で検証(推奨)
import { z } from 'zod'

const UserSchema = z.object({
  id: z.string(),
  name: z.string(),
  email: z.string().email(),
})

const data = UserSchema.parse(await res.json())  // 自動的に型推論される

zod を使う利点は、型チェックだけでなくランタイム検証もあることです。万が一バックエンドが返すデータ構造が変わっても、すぐに発見できます。

シナリオ3:動的インポート

// ❌ 悪い例
const module = await import('./utils')  // any

// ✅ 正しい例
const module = await import('./utils') as typeof import('./utils')

または具体的なインポートを使用する:

const { formatDate } = await import('./utils')  // 自動的に型推論される

TypeScript ユーティリティ型を活用して開発効率を上げる

TypeScript には便利なユーティリティ型が組み込まれており、うまく使えばコード量を減らせます。

Pick:一部のプロパティを抽出

interface User {
  id: string
  name: string
  email: string
  password: string
  createdAt: Date
}

// ユーザーの公開情報だけが必要
type PublicUser = Pick<User, 'id' | 'name' | 'email'>
// { id: string; name: string; email: string }

Omit:特定のプロパティを除外

// ユーザー作成時に id と createdAt は不要
type CreateUserInput = Omit<User, 'id' | 'createdAt'>

Partial:全プロパティをオプションに

// ユーザー更新時、全フィールドがオプション
type UpdateUserInput = Partial<User>

Required:全プロパティを必須に

type RequiredUser = Required<Partial<User>>  // 逆操作

カスタムユーティリティ型

組み込みで足りない場合は、自分で書くこともできます:

// すべての文字列プロパティをオプションにする
type PartialString<T> = {
  [K in keyof T]: T[K] extends string ? T[K] | undefined : T[K]
}

正直なところ、これらのユーティリティ型は最初は怖く見えるかもしれませんが、慣れると本当に便利です。特に複雑なオブジェクト型を扱う際に、重複コードを大量に削減できます。

結論

ここまで書いて、冒頭の午前3時のバグを思い出しました。

もし当時私が Next.js の typedRoutes を有効にしていれば、ルートのスペルミスがリリースされることはあり得ませんでした。T3 Env を使っていれば、環境変数の欠落は起動時にエラーになっていました。厳格モードが設定されていれば、それらの暗黙的な any はとっくに TypeScript に摘発されていたでしょう。

TypeScript の型安全性は人を苦しめるためのものではなく、バグを「実行時」から「記述時」に前倒しするためのものです。本番環境でユーザーがホワイトスクリーンに遭遇するのを待つより、コードを書いている最中に IDE に赤く警告してもらうほうがずっとマシです。

最後に、この記事の要点をまとめます:

  1. tsconfig 最適化:strict モードをオンにし、incremental と paths を設定し、Next.js プラグインを使用する
  2. 型安全なルーティング:Next.js 13+ の typedRoutes を有効にするか、nextjs-routes ライブラリを使用する
  3. 環境変数の型:T3 Env を使用して型チェック + ランタイム検証を実現する
  4. 厳格モードの実践:段階的に導入し、サードパーティライブラリの型問題を処理し、一般的な any 逃れシナリオを撲滅する

最初は設定が面倒で、型注釈が煩わしく感じるかもしれません。しかし、IDE の正確なヒントに慣れ、コード修正時に潜在的な問題を即座に発見することに慣れれば、もう「裸」の JavaScript 時代には戻れなくなります。

今すぐ tsconfig.json を開き、stricttrue に変えてみてください。赤い波線が多ければ多いほど、あなたが発見した潜在的なバグが多いということです——それは良いことです。

FAQ

strict モードはプロジェクトのコンパイルを遅くしますか?
いいえ。厳格モードは型チェックの厳しさを増すだけで、コンパイル速度に顕著な影響はありません。incremental オプションと組み合わせることで、大規模プロジェクトのコンパイル速度はむしろ30〜50%向上します。
古いプロジェクトで安全に厳格モードを有効にするには?
段階的な戦略を推奨します。まず tsconfig.json で strict をオンにし、一時的に修正できないファイルには @ts-expect-error をマークします。新しいコードは強制的に厳格にし、古いコードは徐々にリファクタリングします。モジュールごとに順次オンにしていく方法もあります。
T3 Env と手動の ProcessEnv 型定義の違いは何ですか?
T3 Env はランタイム検証を提供し、アプリ起動時に環境変数の欠落やフォーマットエラーをチェックできます。また、クライアントからのサーバー変数へのアクセスも防止します。手動の型定義はコンパイル時のチェックのみで、ランタイム保護が欠けています。
Next.js の typedRoutes は pages ディレクトリをサポートしていますか?
サポートしていません。typedRoutes は Next.js 13+ の App Router 用に設計された実験的機能で、app ディレクトリでのみ使用可能です。pages ディレクトリを使用している場合は、nextjs-routes というサードパーティライブラリを推奨します。
skipLibCheck をオンにするとセキュリティリスクがありますか?
いいえ。skipLibCheck は node_modules の型チェックをスキップするだけで、あなたのコードは依然として厳格にチェックされます。サードパーティライブラリの型エラーは修正できないため、チェックをスキップすることでコンパイル速度を向上させ、自分のコードに集中できるようにするのが得策です。

7 min read · 公開日: 2026年1月6日 · 更新日: 2026年1月22日

コメント

GitHubアカウントでログインしてコメントできます

関連記事