Chapter 00

環境構築

TypeScript + React の開発環境をセットアップします

20 min

このチャプターで学ぶこと

  • TypeScriptとは何かを理解できる
  • Vite + React + TypeScript のプロジェクトを作成できる
  • tsconfig.json の基本設定を理解できる
  • .ts と .tsx の違いを理解できる

環境構築

Reactコースを終えた皆さん、お疲れさまでした。ここからは TypeScript を導入して、より安全で快適な React 開発を目指しましょう。Laravel や Rails でバックエンド開発をしてきた方なら、「型がある」ことの安心感はすでにご存じのはずです。PHP の型宣言や Ruby の Sorbet/RBS に近い感覚で、JavaScript に型を追加できるのが TypeScript です。

TypeScript とは何か

TypeScript は Microsoft が開発した、JavaScript に 静的型付け を追加した言語です。拡張子は .ts(JSXを含む場合は .tsx)で、最終的にはすべて JavaScript にコンパイルされてからブラウザで実行されます。

// JavaScript(型がない)
function greet(name) {
  return `こんにちは、${name}さん!`;
}

// TypeScript(型がある)
function greet(name: string): string {
  return `こんにちは、${name}さん!`;
}

TypeScript のコードは直接ブラウザでは動きません。ビルド時に JavaScript に変換(トランスパイル)されます。この工程は Vite が自動でやってくれるので、開発者が手動で変換する必要はありません。

📝 メモ

Laravel で例えるなら、Blade テンプレートが最終的に PHP コードに変換されるのと同じ発想です。開発者は便利な構文で書き、ツールが実行可能な形に変換してくれます。

なぜ TypeScript を使うのか

TypeScript を導入する理由は主に3つあります。

1. 型安全性 — バグを未然に防ぐ

// JavaScript: 実行するまでバグに気づけない
function calculateTotal(price, quantity) {
  return price * quantity;
}
calculateTotal("1000", 3); // "100010001000" — 文字列が繰り返される!

// TypeScript: コードを書いた瞬間にエラーが出る
function calculateTotal(price: number, quantity: number): number {
  return price * quantity;
}
calculateTotal("1000", 3); // コンパイルエラー:string は number に代入できません

PHP でも declare(strict_types=1) を書いて型の厳格チェックを有効にしますよね。TypeScript はそれをさらに徹底したものだと考えてください。

2. IDEサポート — 開発速度の向上

型情報があると、VS Code などのエディタが強力な補完や候補を出してくれます。

Laravel で PHPStan や IDE Helper を使っている方は、その恩恵をさらに強くしたものだと想像してください。

3. チーム開発 — コードが仕様書になる

// 型定義がそのままインターフェースの仕様書になる
interface User {
  id: number;
  name: string;
  email: string;
  role: "admin" | "editor" | "viewer";
}

型定義を見れば、データの構造やとりうる値が一目で分かります。Laravel の Migration がテーブル構造のドキュメントになるように、TypeScript の型定義はAPIレスポンスやコンポーネントの props の仕様書になります。

💡 ヒント

TypeScript は「厳しい JavaScript」ではなく「親切な JavaScript」です。エラーメッセージは「ここが間違っているよ」と具体的に教えてくれるので、デバッグ時間が大幅に短縮されます。

Vite + React + TypeScript のプロジェクトを作成する

React コースでは --template react を使いましたが、TypeScript 版は --template react-ts を指定します。

npm create vite@latest my-ts-app -- --template react-ts

作成されたら、おなじみの手順でセットアップします。

cd my-ts-app
npm install
npm run dev

これだけで TypeScript 対応の React プロジェクトが完成します。

📝 メモ

既存の React(JavaScript)プロジェクトに TypeScript を後から追加することもできますが、最初から react-ts テンプレートを使うほうが圧倒的に楽です。設定ファイルや型定義がすべて整った状態でスタートできます。

プロジェクト構造の違い

JavaScript 版と TypeScript 版のプロジェクト構造を比較してみましょう。

JavaScript版(react)          TypeScript版(react-ts)
my-react-app/                  my-ts-app/
├── src/                       ├── src/
│   ├── App.jsx     ←→        │   ├── App.tsx          # .jsx → .tsx
│   ├── App.css                │   ├── App.css
│   ├── main.jsx    ←→        │   ├── main.tsx         # .jsx → .tsx
│   └── index.css              │   ├── index.css
│                              │   └── vite-env.d.ts   # Vite の型定義(新規)
├── package.json               ├── package.json
├── vite.config.js  ←→        ├── vite.config.ts      # .js → .ts
└──                            └── tsconfig.json       # TypeScript設定(新規)

大きな違いは3つです:

  1. ファイル拡張子.jsx.tsx に、.js.ts に変わる
  2. tsconfig.json — TypeScript のコンパイル設定ファイルが追加される
  3. vite-env.d.ts — Vite 固有の型定義ファイルが追加される

.ts と .tsx の使い分け

ファイル拡張子の選び方は明確なルールがあります。

拡張子用途JSX を含む
.ts通常の TypeScript ファイル(ユーティリティ関数、型定義、API呼び出しなど)含まない
.tsxJSX を含む TypeScript ファイル(React コンポーネント)含む
// utils/formatDate.ts — JSX を使わないので .ts
export function formatDate(date: Date): string {
  return date.toLocaleDateString("ja-JP");
}
// components/DateDisplay.tsx — JSX を使うので .tsx
import { formatDate } from "../utils/formatDate";

function DateDisplay({ date }: { date: Date }) {
  return <p>今日の日付: {formatDate(date)}</p>;
}

export default DateDisplay;
⚠️ 注意

.ts ファイルの中に JSX(<div><Component /> など)を書くとコンパイルエラーになります。JSX を使うファイルは必ず .tsx にしてください。逆に .tsx ファイルで JSX を書かなくてもエラーにはなりませんが、慣習として使い分けましょう。

tsconfig.json を理解する

tsconfig.json は TypeScript のコンパイラ設定ファイルです。Laravel でいう .env ファイルや config/app.php のように、プロジェクト全体の挙動を制御します。

Vite の react-ts テンプレートが生成する設定を見てみましょう。

{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,

    /* バンドラー向け設定 */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "noEmit": true,
    "jsx": "react-jsx",

    /* 型チェックの厳格さ */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src"]
}

すべてを覚える必要はありません。特に重要な設定だけ押さえておきましょう。

重要な設定項目

設定意味推奨値
targetコンパイル先の JavaScript バージョンES2020
moduleモジュールシステムESNext
jsxJSX の変換方式react-jsx
strict厳格な型チェックを有効にするtrue
noUnusedLocals未使用の変数をエラーにするtrue
noUnusedParameters未使用の引数をエラーにするtrue

strict: true が有効にする設定

strict: true は複数の厳格チェックを一括で有効にするショートカットです。

{
  "strict": true
  // 以下がすべて有効になる:
  // "noImplicitAny": true       — 暗黙の any を禁止
  // "strictNullChecks": true    — null/undefined の安全なハンドリングを強制
  // "strictFunctionTypes": true — 関数型の厳密なチェック
  // "strictBindCallApply": true — bind/call/apply の型チェック
  // ... その他
}
💡 ヒント

strict: true は最初から有効にしておくことを強くおすすめします。後から有効にすると大量のエラーが出て修正が大変になるためです。Laravel で declare(strict_types=1) を最初から書くのと同じ発想です。

TypeScript 版の App.tsx を見てみる

生成された App.tsx を見てみましょう。

// src/App.tsx
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'

function App() {
  // useState に number 型が自動推論される
  const [count, setCount] = useState(0)

  return (
    <>
      <div>
        <a href="https://vite.dev" target="_blank">
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://react.dev" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
      <div className="card">
        <button onClick={() => setCount((count) => count + 1)}>
          count is {count}
        </button>
        <p>
          Edit <code>src/App.tsx</code> and save to test HMR
        </p>
      </div>
      <p className="read-the-docs">
        Click on the Vite and React logos to learn more
      </p>
    </>
  )
}

export default App

一見すると JavaScript 版とほとんど同じです。しかし TypeScript が裏側で型推論を行っており、countnumber であること、setCountnumber を受け取る関数であることなどを自動的に把握しています。

開発サーバーで TypeScript のコンパイルを確認する

開発サーバーが起動している状態で、意図的に型エラーを起こしてみましょう。

// src/App.tsx の関数内に追加してみる
function App() {
  const count: number = "これは文字列です"; // 型エラー!
  // ...
}

VS Code では赤い波線が表示され、ターミナル(Vite のコンソール)にもエラーが表示されます。

Type 'string' is not assignable to type 'number'.

このように、コードを書いた瞬間にエラーが検知されるのが TypeScript の最大の強みです。

⚠️ 注意

Vite の開発サーバーはデフォルトでは型エラーがあってもブラウザにページを表示します。型チェックは VS Code やビルド時(npm run build)に行われます。厳密に型チェックしたい場合は vite-plugin-checker などのプラグインを追加すると、開発サーバーでもエラーをオーバーレイ表示できます。

Laravel / Rails との比較

バックエンド開発者の視点で、TypeScript の設定をおなじみの概念と対比してみましょう。

TypeScriptLaravel / Rails
tsconfig.json.env + config/app.php(プロジェクト設定)
strict: truedeclare(strict_types=1)(PHP)/ Sorbet の typed: strict(Ruby)
.ts / .tsx ファイル.php / .blade.php ファイル
型エラー(コンパイル時)PHPStan / Larastan のエラー
interface / typePHP の interface / Laravel の Form Request バリデーション
npm run build で型チェックphpstan analyse でコード解析
💡 ヒント

TypeScript の型チェックは PHPStan のレベル設定に似ています。strict: true は PHPStan の最大レベル(レベル9)に相当します。最初から最大レベルで始められるのが、新規プロジェクトの特権です。

vite-env.d.ts について

プロジェクトに含まれる vite-env.d.ts は短いファイルです。

// src/vite-env.d.ts
/// <reference types="vite/client" />

これは Vite が提供する型定義を読み込む宣言です。画像ファイルの importimport.meta.env といった Vite 固有の機能に型を付けてくれます。このファイルは触らずにそのまま残しておきましょう。

✍ やってみよう:TypeScript プロジェクトを作成する

以下の手順で Vite + React + TypeScript のプロジェクトを作成してみましょう。

ステップ 1: プロジェクトを作成する

npm create vite@latest my-ts-app -- --template react-ts
cd my-ts-app
npm install

ステップ 2: 開発サーバーを起動する

npm run dev

ブラウザで http://localhost:5173 を開き、画面が表示されることを確認してください。

ステップ 3: 型エラーを体験する

src/App.tsx を開き、関数の先頭に以下のコードを追加してみましょう。

function App() {
  // わざと型を間違えてみる
  const message: number = "Hello TypeScript";
  console.log(message);
  // ...
}

VS Code に赤い波線が表示され、エラーメッセージが出ることを確認してください。確認できたら、追加したコードは削除しておきましょう。

ステップ 4: プロジェクト構造を確認する

ファイルエクスプローラーで以下のファイルを開いて中身を確認してみましょう。

  • tsconfig.jsonstrict: true になっていますか?
  • src/App.tsx — 拡張子が .tsx になっていますか?
  • src/vite-env.d.ts/// <reference types="vite/client" /> と書かれていますか?

まとめ

このチャプターでは TypeScript + React の開発環境を構築しました。

次のチャプターでは、TypeScript の基本的な型(stringnumberboolean など)を学んでいきます。