JavaScriptの限界を超える!TypeScriptで開発が劇的に変わった話

目次

真夜中のデバッグ地獄から抜け出せた理由

深夜2時。エディタの画面を睨みながら、私は何度目かのため息をついた。

「またか…」

クライアントから連絡が来たのは夕方だった。「本番環境でエラーが出てる」。急いで確認すると、数値を渡すべきところに文字列が入っていた。ローカルでは動いてたのに。テストも通ってたのに。なんで本番だけ…。

結局、原因は単純だった。APIから返ってくるデータの型が、ドキュメントと違ってた。JavaScriptは文句も言わずに動いてた。で、計算のタイミングでクラッシュ。

こういうの、何度目だろう。

夜遅くまでバグ対応に追われ、疲れた表情でノートパソコンに向かう30代男性の線画イラスト

JavaScriptでの開発は自由だ。型を気にせず、サクサク書ける。でもその自由さが、時に仇になる。変数の中身が何なのか、関数が何を返すのか。実行してみないとわからない。

「もっと早く気づけないのか」

そう思ってた矢先、同僚がTypeScriptを勧めてくれた。

「型があるから、こういうミスはコーディング中に気づけるよ」

半信半疑で導入した。最初は型を書くのが面倒に感じた。でも、1週間もしないうちに気づいた。

本番環境でのバグが、ゼロになった。

正確には、TypeScriptが事前に教えてくれるようになった。「ここ、型が違うよ」「このプロパティ、存在しないよ」。コンパイルの段階で。実行する前に。

あの真夜中のデバッグ地獄は、もう過去の話だ。

この記事では、JavaScriptからTypeScriptに移行して開発がどう変わったのか、実体験をベースに語っていく。型とか難しそう、面倒そう、そう思ってる人にこそ読んでほしい。

TypeScriptは学習コストに見合う価値がある。いや、正直に言うと、見合うどころじゃない。圧倒的にお釣りが来る。私が20年のエンジニア人生で学んだ技術の中でも、トップ3に入る。

今、JavaScriptで開発してて「もっとバグを減らしたい」「チーム開発を円滑にしたい」「将来性のあるスキルを身につけたい」って思ってる人。TypeScriptは、あなたの開発スタイルを変える。

なぜ今TypeScriptなのか - 市場が求める理由

求人数が前年比392%増という衝撃

TypeScriptの求人数が、2023年から2024年にかけて前年比392%増加した。これ、冗談じゃない。実際の数字だ。

他のプログラミング言語と比べても、この成長率は飛び抜けてる。Stack Overflowの人気調査でも、TypeScriptは2023年に38.87%の開発者が使用していて、全体で5位。

なんでこんなに人気なのか。

企業が求めてるからだ。特に、スタートアップから大企業まで、Web開発をしてる会社ならほぼ確実にTypeScriptを使ってる。React、Vue.js、Angular。主要フレームワークの全てがTypeScriptをサポートしてる。

私がメンターしてる受講生で、最近転職した人がいる。面接で「TypeScriptできます」って言ったら、即採用だった。他の候補者はJavaScriptしかできなかった。それだけで差がついた。

JavaScriptの課題を解決する唯一の選択肢

JavaScriptには、根本的な問題がある。

型がない。

動的型付け言語だから、変数が何を格納してるか、実行してみないとわからない。小規模なプロジェクトなら問題ない。でも、コードが数千行、数万行になってくると、管理しきれなくなる。

「この関数、何を返すんだっけ?」
「この変数、stringだっけ、numberだっけ?」

コメントに書いてあっても、コメントは嘘をつく。誰かが修正して、コメントを更新し忘れる。で、間違った情報を信じて、バグを埋め込む。

TypeScriptは、この問題を根本から解決する。

型を書く。型をチェックする。型が合わなければコンパイルエラー。

シンプルだけど、これが効く。Airbnbの分析によると、TypeScriptを使ってたら38%ものバグを未然に防げたらしい。38%だよ。4割近く。

大手企業がこぞって採用する理由

Google、Facebook、Microsoft、Netflix、Slack…。名だたる企業が、TypeScriptを採用してる。

なんでか。

大規模開発に耐えられるから。

チーム開発だと、他人が書いたコードを読む機会が増える。型があると、コードの意図が明確になる。「この関数は、文字列を受け取って、数値を返すんだな」。一目でわかる。

リファクタリングも楽になる。変数名を変えたら、使ってる箇所全部にエラーが出る。修正漏れがない。

TypeScriptは、Microsoft が開発してる。しかもオープンソース。サポートがしっかりしてる。バージョンアップも定期的。コミュニティも活発。

将来性で言えば、これ以上ない。少なくとも今後5年は、TypeScriptの需要は伸び続ける。

コワーキングスペースで、チームメンバーとTypeScriptのコードレビューをする40代男性の線画イラスト

TypeScriptの5つの魅力 - 実務で感じた本当のメリット

1. コンパイル時にバグを発見できる

これが一番大きい。

JavaScriptだと、バグは実行して初めて気づく。ユーザーが操作して、エラー画面が出て、問い合わせが来て。最悪だ。

TypeScriptは違う。

// TypeScriptの例
function calculateTotal(price: number, quantity: number): number {
  return price * quantity;
}

calculateTotal(1000, "5"); // エラー: string型はnumber型に代入できません

コードを書いてる段階で、エディタが教えてくれる。「ここ、型が違うよ」。

実行する前に気づける。テストの前に気づける。デプロイの前に気づける。ユーザーに届く前に気づける。

これだけで、どれだけ救われるか。

私の経験だと、TypeScript導入前は月に2~3回、本番環境でバグが見つかってた。導入後は、半年に1回あるかないか。それも、型チェックでは防げないロジックの問題だったり。

2. エディタの補完機能が超強力

VS Codeでコードを書いてると、勝手に候補が出てくる。

オブジェクトのプロパティ、関数の引数、戻り値の型。全部表示される。いちいち調べる必要がない。

const user = {
  id: 1,
  name: "Tanaka",
  email: "tanaka@example.com"
};

user. // ← ここで「id」「name」「email」が候補に出る

これ、地味だけど効く。開発速度が段違いに上がる。

JavaScriptだと、「このオブジェクト、どんなプロパティ持ってたっけ?」って、ソースコード全体を検索したり、ドキュメント見たり。時間かかる。

TypeScriptなら、ドット打った瞬間に候補が出る。しかも、型情報も一緒に表示される。「このプロパティはstring型だな」「ここはnumber型か」。一目でわかる。

3. リファクタリングが安全にできる

コードの整理をする時、JavaScriptだと怖い。

変数名を変えたら、使ってる箇所を全部探して、手作業で直す。見落としたらバグ。関数名を変えても同じ。テストがあれば気づけるけど、テストがカバーしてない部分は…。

TypeScriptは違う。

変数名を変えたら、使ってる箇所全部にエラーが出る。コンパイラが教えてくれる。「ここ、まだ古い名前使ってるよ」。

関数のシグネチャ(引数の数や型)を変えても同じ。呼び出してる箇所全部にエラー。修正漏れがない。

これ、大規模なリファクタリングをする時に、めちゃくちゃ助かる。安心して、思い切った変更ができる。

4. チーム開発での意思疎通が楽になる

型は、最高のドキュメントだ。

interface User {
  id: number;
  name: string;
  email: string;
  createdAt: Date;
}

function getUser(userId: number): Promise<User> {
  // ...
}

この関数を見たら、何が必要で、何が返ってくるか、一目でわかる。コメントを読む必要がない。

チームメンバーが書いた関数を使う時、型定義を見れば使い方がわかる。わざわざ質問しなくていい。Slackで「これ、何返すんですか?」みたいなやり取りが減る。

新しいメンバーが入ってきた時も楽。型があれば、コードの意図が伝わりやすい。オンボーディングの時間が短縮される。

5. JavaScriptの知識がそのまま使える

TypeScriptは、JavaScriptのスーパーセット。

つまり、JavaScriptのコードは、そのままTypeScriptとしても有効。学習コストが低い。

JavaScriptができる人なら、型アノテーションを追加するだけ。新しい言語を1から学ぶ必要はない。

// JavaScript
function add(a, b) {
  return a + b;
}

// TypeScript(型を追加するだけ)
function add(a: number, b: number): number {
  return a + b;
}

既存のJavaScriptプロジェクトも、段階的に移行できる。いきなり全部をTypeScriptにする必要はない。1ファイルずつ、.jsを.tsに変えていけばいい。

しかも、JavaScriptのライブラリもそのまま使える。npm install した後、型定義ファイル(@types/…)を入れれば、型チェックもできる。

自宅で、TypeScriptのコード補完機能を使いながら開発する20代女性の線画イラスト

TypeScriptの導入手順 - 今日から始められる環境構築

必要なもの:Node.jsとエディタだけ

TypeScriptを使うのに、特別な環境は要らない。

必要なのは2つだけ。

  1. Node.js(npmコマンドが使えればOK)
  2. エディタ(VS Codeが断然おすすめ)

Node.jsは、公式サイトからインストーラーをダウンロードして実行すれば終わり。Macなら偶数バージョン(安定版)を選ぶのがいい。

VS Codeは無料。Microsoftが開発してて、TypeScriptをデフォルトでサポートしてる。TypeScript自体もMicrosoft製だから、相性は抜群。

ステップ1:プロジェクトの作成

まず、作業用のフォルダを作る。

mkdir typescript-project
cd typescript-project

次に、package.jsonを生成。

npm init -y

これで、Node.jsのプロジェクトができた。

ステップ2:TypeScriptのインストール

TypeScriptをプロジェクトにインストールする。

npm install -D typescript

-Dオプションは、開発時だけ使うパッケージってこと。

TypeScriptの型定義ファイルも入れとく。

npm install -D @types/node

これで、Node.jsの標準モジュールに対する型情報が使えるようになる。

ステップ3:設定ファイルの生成

TypeScriptコンパイラの設定ファイル、tsconfig.jsonを作る。

npx tsc --init

tsconfig.jsonが生成される。中身は色々書いてあるけど、最初はデフォルトでOK。

私がよく使う設定だけ紹介しとく。

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true
  }
}
  • outDir: コンパイル後のJavaScriptファイルを出力する場所
  • rootDir: TypeScriptのソースファイルがある場所
  • strict: 厳格な型チェックを有効にする(おすすめ)

ステップ4:最初のTypeScriptファイルを書く

srcフォルダを作って、その中にindex.tsを作る。

mkdir src

src/index.tsに以下を書く。

// シンプルな関数
function greet(name: string): string {
  return `Hello, ${name}!`;
}

// 型推論も効く
const message = greet("TypeScript");
console.log(message);

// 型が違うとエラー
// greet(123); // エラー: number型はstring型に代入できません

ステップ5:コンパイルして実行

TypeScriptをJavaScriptにコンパイルする。

npx tsc

distフォルダにindex.jsが生成される。

実行してみる。

node dist/index.js

「Hello, TypeScript!」って表示されたら成功。

よく使うコマンドをpackage.jsonに登録

毎回npx tscって打つの面倒だから、npm scriptに登録しとく。

package.jsonscriptsに追加。

{
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js"
  }
}

これで、以下のコマンドで使える。

npm run build  # コンパイル
npm start      # 実行

ファイルを保存するたびに自動でコンパイルしたいなら、--watchオプションを使う。

{
  "scripts": {
    "dev": "tsc --watch"
  }
}
npm run dev

これで、ファイルを保存するたびに、自動でコンパイルされる。

深夜、自宅のデスクでVS Codeを開き、初めてのTypeScriptコードを書く30代男性の線画イラスト

実際に書いてみる - 基本的な型の使い方

プリミティブ型:string、number、boolean

TypeScriptの基本は、変数に型を付けること。

let userName: string = "Tanaka";
let age: number = 30;
let isActive: boolean = true;

型推論も効くから、型を書かなくても自動で判定される。

let userName = "Tanaka"; // string型と推論される
let age = 30;            // number型と推論される
let isActive = true;     // boolean型と推論される

でも、最初のうちは明示的に書いた方がいい。自分の理解も深まるし、エディタの補完も効きやすくなる。

配列とオブジェクトの型定義

配列は、型[]で書く。

let numbers: number[] = [1, 2, 3, 4, 5];
let names: string[] = ["Tanaka", "Suzuki", "Sato"];

オブジェクトは、{}で書く。

let user: { id: number; name: string; email: string } = {
  id: 1,
  name: "Tanaka",
  email: "tanaka@example.com"
};

でも、これだと読みにくい。同じ型を何度も使うなら、interfaceで定義する。

interface User {
  id: number;
  name: string;
  email: string;
}

let user: User = {
  id: 1,
  name: "Tanaka",
  email: "tanaka@example.com"
};

関数の型定義:引数と戻り値

関数は、引数と戻り値に型を付ける。

function add(a: number, b: number): number {
  return a + b;
}

const result = add(10, 20); // 30

戻り値の型は省略できる(型推論される)けど、書いた方がわかりやすい。

アロー関数でも同じ。

const multiply = (a: number, b: number): number => {
  return a * b;
};

オプショナルな引数は、?を付ける。

function greet(name: string, greeting?: string): string {
  if (greeting) {
    return `${greeting}, ${name}!`;
  }
  return `Hello, ${name}!`;
}

greet("Tanaka");              // "Hello, Tanaka!"
greet("Tanaka", "Good morning"); // "Good morning, Tanaka!"

Union型:複数の型を許可する

変数が複数の型を取りうる場合、Union型を使う。

let id: number | string;

id = 123;      // OK
id = "ABC123"; // OK
id = true;     // エラー: boolean型は許可されてない

関数の引数にも使える。

function displayId(id: number | string): void {
  console.log(`ID: ${id}`);
}

displayId(123);      // OK
displayId("ABC123"); // OK

実際のコード例:TODOリストの型定義

実務っぽい例を見てみる。

// TODOアイテムの型定義
interface Todo {
  id: number;
  title: string;
  completed: boolean;
  createdAt: Date;
}

// TODOリストの管理クラス
class TodoList {
  private todos: Todo[] = [];
  private nextId: number = 1;

  // TODOを追加
  addTodo(title: string): Todo {
    const newTodo: Todo = {
      id: this.nextId++,
      title: title,
      completed: false,
      createdAt: new Date()
    };
    this.todos.push(newTodo);
    return newTodo;
  }

  // TODOを完了にする
  completeTodo(id: number): boolean {
    const todo = this.todos.find(t => t.id === id);
    if (todo) {
      todo.completed = true;
      return true;
    }
    return false;
  }

  // 全てのTODOを取得
  getAllTodos(): Todo[] {
    return this.todos;
  }

  // 未完了のTODOを取得
  getIncompleteTodos(): Todo[] {
    return this.todos.filter(t => !t.completed);
  }
}

// 使用例
const todoList = new TodoList();
todoList.addTodo("TypeScriptを学ぶ");
todoList.addTodo("記事を書く");
todoList.completeTodo(1);

console.log(todoList.getIncompleteTodos());

このコード、JavaScriptでも書ける。でも、TypeScriptだとエディタが補完してくれるし、型の間違いがあればすぐにわかる。

開発体験が、段違いに良くなる。

よくあるつまずきポイントと解決策

つまずき1:型エラーが多すぎて嫌になる

TypeScript導入直後、エラーだらけになって「もういいや」ってなる人、多い。

私も最初そうだった。「JavaScriptなら動いてたのに」「型付けるの面倒くさい」。

でも、これ、考え方を変えるといい。

エラーは敵じゃない。味方だ。

JavaScriptだったら、実行して初めて気づくバグ。それを、コーディング中に教えてくれてる。ありがたい話だ。

最初は厳格なルール(strict: true)をオフにしてもいい。徐々に慣れてから、厳しくしていく。

{
  "compilerOptions": {
    "strict": false  // 最初はfalseでもOK
  }
}

つまずき2:any型を多用してしまう

エラーが出た時、any型を使えば消える。

let data: any = "hello";
data = 123;  // エラーにならない

でも、これやっちゃうと、TypeScriptの意味がない。

anyは「型チェックを諦める」ってこと。せっかくTypeScript使ってるのに、JavaScriptに逆戻り。

どうしても型がわからない時は、unknown型を使う。

let data: unknown = "hello";

// 使う前に型チェックが必要
if (typeof data === "string") {
  console.log(data.toUpperCase()); // OK
}

unknownは、使う前に型を確認することを強制する。anyより安全。

カフェで、TypeScriptのエラーメッセージと向き合いながらデバッグする20代男性の線画イラスト

つまずき3:nullやundefinedのチェック忘れ

JavaScriptだと、null や undefined のチェックを忘れがち。

function getUser(id: number): User | null {
  // ユーザーが見つからない場合はnullを返す
  return null;
}

const user = getUser(1);
console.log(user.name); // エラー: userはnullかもしれない

TypeScriptは、nullの可能性を教えてくれる。

対処法は2つ。

1. nullチェックをする

const user = getUser(1);
if (user !== null) {
  console.log(user.name); // OK
}

2. オプショナルチェーン(?.)を使う

const user = getUser(1);
console.log(user?.name); // userがnullなら undefined が返る

つまずき4:ライブラリの型定義がない

外部ライブラリを使う時、型定義ファイルがないことがある。

npm install some-library

インポートしたら、エラー。

import someLibrary from 'some-library'; // エラー: 型定義が見つかりません

対処法は2つ。

1. 型定義ファイルをインストールする

npm install -D @types/some-library

DefinitelyTypedっていうコミュニティが、有名なライブラリの型定義を作ってる。大抵はここにある。

2. 自分で型定義を書く

型定義ファイルがない場合、自分で書く。

プロジェクトのルートにtypesフォルダを作って、some-library.d.tsを作る。

declare module 'some-library' {
  export function someFunction(): void;
}

最初は面倒だけど、慣れてくるとそんなに大変じゃない。

つまずき5:コンパイルエラーと実行エラーの区別がつかない

TypeScriptには2種類のエラーがある。

1. コンパイルエラー(型チェックのエラー)

コードを書いてる段階で出るエラー。型が合わないとか。これは、TypeScriptコンパイラが検出する。

2. 実行エラー(ランタイムエラー)

実際にコードを実行した時に出るエラー。ロジックの問題とか、サーバーとの通信エラーとか。

TypeScriptは、コンパイルエラーは防げるけど、実行エラーは防げない。

例えば、APIから返ってくるデータが想定と違ってたら、実行時にエラーになる。

TypeScriptは銀の弾丸じゃない。でも、多くのバグを事前に防げる。それだけで、十分価値がある。

よくある質問(FAQ)

Q1: JavaScriptの経験がなくても、TypeScriptから始めていい?

できないことはないけど、おすすめしない。

TypeScriptは、JavaScriptのスーパーセット。JavaScriptの知識が前提になってる。

まずはJavaScriptの基礎を学んで、それからTypeScriptに移行するのがいい。Progateとか、JavaScript Primerとか、無料のリソースがたくさんある。

JavaScript の基礎ができてれば、TypeScriptは1~2ヶ月で習得できる。

Q2: 既存のJavaScriptプロジェクトを、TypeScriptに移行できる?

できる。しかも、段階的に移行できる。

最初は、1つのファイルだけ.tsに変える。残りは.jsのまま。TypeScriptとJavaScriptは共存できる。

慣れてきたら、少しずつ.tsファイルを増やしていく。全部を一気に移行する必要はない。

私がやった案件でも、10万行のJavaScriptプロジェクトを、半年かけて段階的にTypeScriptに移行した。問題なくできた。

Q3: TypeScriptを学ぶのに、どれくらい時間がかかる?

JavaScriptができる人なら、基礎は1~2ヶ月で身につく。

  • 基本的な型(string、number、boolean)
  • 配列とオブジェクトの型
  • 関数の型
  • interface と type
  • Union型とIntersection型

これくらいができれば、実務で使える。

ジェネリクスとか、Conditional Typeとか、高度な型は後から学べばいい。最初は基礎を固める。

Q4: 小規模なプロジェクトでもTypeScriptを使うべき?

私の意見だと、規模に関わらず使った方がいい。

小規模なプロジェクトでも、バグは出る。型があれば、バグは減る。シンプルな話だ。

「小さいプロジェクトだから、JavaScriptで十分」って思ってても、プロジェクトは成長する。気づいたら大規模になってる。そうなってからTypeScriptに移行するのは大変。

最初からTypeScriptにしとけば、スケールしても安心。

Q5: TypeScriptのデメリットは?

正直に言うと、デメリットもある。

  • コンパイルが必要(そのままブラウザで動かない)
  • 型を書く手間がかかる
  • 学習コストがある

でも、これらのデメリットは、メリットに比べたら小さい。

コンパイルは自動化できる(--watchオプション)。型を書く手間は、バグ修正の手間と比べたら楽。学習コストは、1~2ヶ月で回収できる。

メリットとデメリットを天秤にかけたら、圧倒的にメリットが勝つ。

Q6: Reactやvueと一緒に使える?

もちろん。

むしろ、ReactやVue.jsと組み合わせて使うのが主流。

Reactなら、Create React Appでテンプレートを選べる。

npx create-react-app my-app --template typescript

Vue.jsも、Vue CLIでTypeScriptを選択できる。

どちらも、最初からTypeScriptの環境が整ってる。設定不要で使える。

Q7: フリーランスや副業でも役立つ?

めちゃくちゃ役立つ。

TypeScriptができるだけで、案件の幅が広がる。単価も上がる。

クラウドソーシングで「TypeScript」で検索すると、高単価の案件がたくさん出てくる。JavaScriptだけの案件より、1.5倍くらい単価が高い。

企業も、TypeScriptができるエンジニアを求めてる。需要は高い。供給は少ない。つまり、稼ぎやすい。

Q8: 型定義を書くのが面倒…どこまで厳密にやればいい?

最初は、緩くてもいい。

strict: falseにして、エラーが出ないようにする。それでも、型があるだけで十分恩恵はある。

慣れてきたら、徐々に厳格にしていく。strict: trueにして、null チェックをちゃんとやって。

完璧を目指さなくていい。少しずつ、改善していけばいい。

夕方、オフィスのデスクで、TypeScriptでの開発が軌道に乗って満足そうな表情の40代男性の線画イラスト

まとめ:TypeScriptは開発人生を変える

ここまで読んでくれてありがとう。

TypeScriptの魅力、伝わっただろうか。

私がTypeScriptに出会って変わったこと。

  • 本番環境でのバグが激減した
  • デバッグの時間が減って、開発に集中できるようになった
  • チーム開発での意思疎通が楽になった
  • エディタの補完が効いて、コーディングが速くなった
  • リファクタリングが怖くなくなった

あの真夜中のデバッグ地獄は、もう過去の話だ。

TypeScriptは、学習コストに見合う価値がある。いや、それ以上だ。

今すぐ始められる

環境構築は、30分もあればできる。Node.jsをインストールして、VS Codeをインストールして、npm install -D typescript。これだけ。

最初の一歩を踏み出すのは、今日だっていい。

型を書くのが面倒?確かに最初はそう感じるかもしれない。でも、1週間もすれば慣れる。1ヶ月もすれば、型がないコードの方が不安になる。

エラーが多い?それは、将来のバグを教えてくれてるんだ。感謝すべきエラーだ。

完璧を目指さなくていい。最初は型を緩くしてもいい。anyを使ってもいい。少しずつ、改善していけばいい。

TypeScriptは、あなたの開発を変える

バグを減らしたい人。チーム開発を円滑にしたい人。将来性のあるスキルを身につけたい人。TypeScriptは、全てに応えてくれる。

私がメンターしてる受講生の中にも、TypeScriptを学んで転職に成功した人、フリーランスで高単価案件を取れるようになった人、たくさんいる。

あなたも、その一人になれる。

さあ、始めよう。今日から、TypeScriptで開発しよう。

型のある世界へ、ようこそ。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いたエンジニア

新垣 亮のアバター 新垣 亮 Webアプリエンジニア

Webアプリ開発で幅広く活躍するフルスタック寄りのエンジニア。堅実で素早い対応力が魅力。好奇心旺盛で新技術を試すのが好き。周囲を明るくする軽快さがあり、チームコミュニケーションを円滑にする潤滑油的存在。休日はランニングで汗を流す。

目次