TypeScript入門|JavaScriptとの違いから基本的な型まで初心者向けに徹底解説
「TypeScriptって何が良いの?」という疑問にお答えします。JavaScriptとの違い・型の基本・実際のコード例・セットアップ方法まで、初心者にもわかりやすく解説。2026年現在、フロントエンド開発の標準スキルとなったTypeScriptをマスターしよう。
「JavaScriptのコードを書いていたら、突然 undefined is not a function というエラーが出てきて、どこが原因かわからずに1時間以上悩んだ……」
そんな経験はありませんか?こういった実行時エラーに悩まされたとき、TypeScript を使っていれば、コードを実行する前の段階でエラーを発見できることがあります。
2026年現在、TypeScriptはフロントエンド開発の事実上の標準となっており、GitHub Octoverse の調査ではコントリビューター数でPythonを抜いて世界第1位になるほど急成長しています。転職・就職・フリーランスどの道を選ぶにしても、TypeScript は避けて通れないスキルになっています。
この記事でわかること:
- TypeScript とは何か・なぜ必要なのか
- JavaScript との具体的な違い(コード例つき)
- 基本的な型の種類と使い方
- TypeScript のセットアップ・始め方
- よく使うユーティリティ型・よくあるエラーの対処法
TypeScript とは
TypeScript とは、Microsoft が開発・オープンソースで公開している、JavaScript に「型」を追加したプログラミング言語です。
正確には「JavaScript のスーパーセット(上位互換)」と呼ばれており、既存の JavaScript コードはそのまま TypeScript としても動作します。TypeScript で書いたコードは最終的に JavaScript に変換(コンパイル)されてブラウザや Node.js 上で実行されます。
TypeScript の誕生背景
TypeScript は 2012 年に Microsoft が公開しました。JavaScript がブラウザだけでなくサーバーサイド(Node.js)でも使われるようになり、コードベースが大規模化するにつれて「型なし言語では管理しきれない」という課題が生まれたことが背景にあります。
TypeScript の採用状況(2026年)
TypeScript の採用率は急速に拡大しています。
| 調査 | 結果 |
|---|---|
| Stack Overflow Developer Survey 2025 | プロ開発者の約 67% が TypeScript を使用 |
| GitHub Octoverse 2025 | コントリビューター数でPythonを抜き世界第1位(前年比 +66%) |
| 満足度 | 使用した開発者の 84.1% が「また使いたい」と回答 |
Microsoft、Google、Slack、任天堂など大手企業も採用しており、Next.js・Angular・NestJS などの主要フレームワークは TypeScript 対応が前提になっています。
なぜ TypeScript を使うのか
1. 型による早期エラー検出
JavaScript は実行するまでエラーに気づけないことがあります。TypeScript ではコードを書いている段階(コンパイル時)にエラーを検出できます。
// TypeScript の場合
function greet(name: string): string {
return "こんにちは、" + name + "さん!";
}
greet(42); // エラー:Argument of type 'number' is not assignable to parameter of type 'string'
// ↑ コードを実行する前に IDE やコンパイラがエラーを教えてくれる!2. IDE の補完・リファクタリングが強力に
型情報があることで、VS Code などの IDE がプロパティ名の候補を自動で表示したり、関数の引数に何を渡せばいいかをリアルタイムで教えてくれたりします。
変数名や関数名を変えるリファクタリング作業も、関連する箇所を一括変換できるため安全かつ高速になります。
3. チーム開発での可読性向上
「この関数は何を受け取って何を返すのか」が型定義から明確に読み取れるため、コードが自己文書化されます。コメントを書かなくても、型を見ればインターフェースが理解できます。
4. React・Next.js との相性が抜群
React では .tsx という拡張子で TypeScript を使います。コンポーネントの Props に型をつけることで、渡し忘れや型違いのバグを防げます。
// Props の型を定義
type ButtonProps = {
label: string;
onClick: () => void;
disabled?: boolean; // ? をつけるとオプショナル(省略可能)
};
// 型安全なコンポーネント
function Button({ label, onClick, disabled = false }: ButtonProps) {
return (
<button onClick={onClick} disabled={disabled}>
{label}
</button>
);
}JavaScript vs TypeScript の違い
実際のコードで違いを見てみましょう。
型なし(JavaScript)vs 型あり(TypeScript)
// JavaScript(型なし)
function add(a, b) {
return a + b;
}
console.log(add(1, 2)); // 3(期待通り)
console.log(add("1", 2)); // "12"(文字列結合になってしまう!)
// ↑ 実行するまでバグに気づけない// TypeScript(型あり)
function add(a: number, b: number): number {
return a + b;
}
console.log(add(1, 2)); // 3
console.log(add("1", 2));
// ↑ エラー:Argument of type 'string' is not assignable to parameter of type 'number'
// コードを書いた瞬間に IDE がエラーを表示してくれる!実行時エラー vs コンパイルエラー
| 比較項目 | JavaScript | TypeScript |
|---|---|---|
| エラー検出のタイミング | 実行時(ブラウザで動かしたとき) | コンパイル時(コードを書いた瞬間) |
| 型チェック | なし | あり |
| IDE の補完精度 | 低い | 高い |
| 学習コスト | 低い | 少し高い |
| 大規模開発の安全性 | 低い | 高い |
| 拡張子 | .js / .jsx | .ts / .tsx |
TypeScript の基本的な型
プリミティブ型
JavaScript の基本的なデータ型をそのまま TypeScript でも使えます。
// 文字列
const name: string = "田中太郎";
// 数値(整数・小数どちらも number)
const age: number = 25;
const price: number = 1980.5;
// 真偽値
const isLoggedIn: boolean = true;
// null と undefined
const empty: null = null;
const notDefined: undefined = undefined;配列とタプル
// 配列(number の配列)
const scores: number[] = [85, 92, 78];
// または
const names: Array<string> = ["田中", "佐藤", "鈴木"];
// タプル(要素数と各要素の型が固定された配列)
const user: [string, number] = ["田中太郎", 25];
// user[0] は string、user[1] は numberオブジェクト・interface・type
// インラインでオブジェクトの型を書く
const user: { name: string; age: number } = {
name: "田中太郎",
age: 25,
};
// interface で型に名前をつける(再利用可能)
interface User {
name: string;
age: number;
email?: string; // ? でオプショナル(あってもなくてもいい)
}
// type エイリアスでも同様に定義できる
type Product = {
id: number;
title: string;
price: number;
};
const product: Product = {
id: 1,
title: "TypeScript入門書",
price: 3200,
};any、unknown、never
// any:型チェックを無効化(なるべく使わない)
let anything: any = "文字列";
anything = 42; // エラーにならない
anything.foo.bar; // エラーにならないが、実行時にクラッシュする恐れ
// unknown:型が不明(any より安全。使う前に型チェックが必要)
let value: unknown = "文字列";
if (typeof value === "string") {
console.log(value.toUpperCase()); // 型チェック後は安全に使える
}
// never:絶対に到達しない型(網羅チェックなどに使用)
function throwError(message: string): never {
throw new Error(message);
// この関数は値を返さずに例外を投げるため never
}ユニオン型とインターセクション型
// ユニオン型(|):複数の型のどれかひとつ
type StringOrNumber = string | number;
let id: StringOrNumber = "user-001";
id = 42; // これも OK
// 特定の文字列値だけを許可するリテラル型
type Direction = "north" | "south" | "east" | "west";
let move: Direction = "north";
move = "up"; // エラー:'up' は Direction 型に含まれない
// インターセクション型(&):複数の型をすべて満たす
type WithTimestamp = {
createdAt: Date;
updatedAt: Date;
};
type UserWithTimestamp = User & WithTimestamp;
// User のプロパティと WithTimestamp のプロパティを両方持つ型型推論(Type Inference)
すべての変数に型を書かなくても、TypeScript は初期値から型を推論してくれます。
// 型を明示しなくても TypeScript が推論してくれる
const message = "こんにちは"; // string と推論
const count = 0; // number と推論
const flag = true; // boolean と推論
// 配列も推論
const items = [1, 2, 3]; // number[] と推論
// 関数の戻り値も推論(型を書かなくてもOK)
function double(n: number) {
return n * 2; // 戻り値は number と推論される
}型推論が効くので、実際の開発では引数の型だけ書けば十分なケースが多いです。
関数と型
引数の型・戻り値の型
// 引数と戻り値に型をつける
function greet(name: string, age: number): string {
return `こんにちは!${name}さん(${age}歳)`;
}
// アロー関数でも同様
const multiply = (a: number, b: number): number => a * b;オプショナルパラメータ(?)とデフォルト値
// ? をつけると省略可能(undefined も受け入れる)
function sendMessage(to: string, message: string, subject?: string): void {
console.log(`To: ${to}`);
console.log(`Subject: ${subject ?? "(件名なし)"}`);
console.log(`Message: ${message}`);
}
sendMessage("田中", "お疲れさまです"); // subject は省略OK
sendMessage("佐藤", "よろしく", "ミーティングについて"); // subject あり
// デフォルト値を設定することもできる
function createUser(name: string, role: string = "member") {
return { name, role };
}ジェネリクス入門
ジェネリクスとは「型をパラメータとして受け取れる仕組み」です。同じ処理を複数の型に対して使い回したいときに便利です。
// ジェネリクスなし(any を使うと型安全でなくなる)
function firstItem(arr: any[]): any {
return arr[0];
}
// ジェネリクスあり(T は「型の変数」)
function firstItem<T>(arr: T[]): T {
return arr[0];
}
const num = firstItem([1, 2, 3]); // T = number と推論される
const str = firstItem(["a", "b", "c"]); // T = string と推論される
// 呼び出し時に型を明示することもできる
const first = firstItem<string>(["hello", "world"]);セットアップと始め方
TypeScript のセットアップ手順
tsconfig.json の基本設定
{
"compilerOptions": {
"target": "ES2022", // 出力する JavaScript のバージョン
"module": "commonjs", // モジュール形式
"strict": true, // 厳格な型チェックを有効化(推奨)
"outDir": "./dist", // コンパイル後のファイルの出力先
"rootDir": "./src", // TypeScript ソースファイルのルート
"esModuleInterop": true, // CommonJS モジュールの import を楽にする
"skipLibCheck": true // ライブラリの型定義ファイルのチェックをスキップ
},
"include": ["src/**/*"], // コンパイル対象のファイル
"exclude": ["node_modules"]
}実際に動かしてみよう
// src/index.ts
interface Todo {
id: number;
title: string;
completed: boolean;
}
function createTodo(id: number, title: string): Todo {
return {
id,
title,
completed: false,
};
}
function completeTodo(todo: Todo): Todo {
return { ...todo, completed: true };
}
const todo1 = createTodo(1, "TypeScript の基本を学ぶ");
const todo2 = completeTodo(createTodo(2, "型定義を練習する"));
console.log(todo1); // { id: 1, title: 'TypeScript の基本を学ぶ', completed: false }
console.log(todo2); // { id: 2, title: '型定義を練習する', completed: true }# コンパイルして実行
npx tsc
node dist/index.jsよく使うユーティリティ型
TypeScript には便利なユーティリティ型が標準で用意されています。
| ユーティリティ型 | 説明 | 使い方の例 |
|---|---|---|
Partial<T> | T のすべてのプロパティをオプショナルに | 更新リクエストの型に |
Required<T> | T のすべてのプロパティを必須に | フォームのバリデーションに |
Readonly<T> | T のすべてのプロパティを読み取り専用に | 変更不可のオブジェクトに |
Pick<T, K> | T から K で指定したプロパティだけを抽出 | 一部のフィールドだけ使いたいとき |
Omit<T, K> | T から K で指定したプロパティを除外 | パスワードなど除きたいフィールドがあるとき |
Record<K, V> | キーが K、値が V のオブジェクト型 | マップ型を作るとき |
interface User {
id: number;
name: string;
email: string;
password: string;
}
// 更新リクエスト:どのフィールドも省略できる
type UpdateUserRequest = Partial<User>;
// 外部に公開するユーザー情報:パスワードを除く
type PublicUser = Omit<User, "password">;
// 読み取り専用のユーザー
type ReadonlyUser = Readonly<User>;
// id と name だけ必要な場面
type UserSummary = Pick<User, "id" | "name">;TypeScript でよくあるエラーと対処法
| エラーメッセージ | 原因 | 対処法 |
|---|---|---|
Type 'string' is not assignable to type 'number' | 型が一致しない | 正しい型の値を渡す、または型変換する |
Object is possibly 'null' | null チェックがない | if (value !== null) で確認するか ?? 演算子を使う |
Property 'xxx' does not exist on type 'yyy' | 存在しないプロパティにアクセス | スペルミスを確認、または型定義にプロパティを追加 |
Parameter 'xxx' implicitly has an 'any' type | 引数の型が未定義 | 引数に明示的な型を追加する |
Cannot find module 'xxx' | 型定義ファイルがない | npm install -D @types/xxx で型定義をインストール |
Argument of type 'xxx' is not assignable to parameter of type 'yyy' | 関数に間違った型の値を渡している | 渡す値の型を修正する |
null チェックのパターン
// 安全でない例(null の場合クラッシュする)
function getLength(str: string | null): number {
return str.length; // エラー:Object is possibly 'null'
}
// 安全な例①:if で確認
function getLength(str: string | null): number {
if (str === null) return 0;
return str.length; // ここでは string 型が保証される
}
// 安全な例②:オプショナルチェーン(?.)
function getLength(str: string | null | undefined): number {
return str?.length ?? 0; // null/undefined なら 0 を返す
}TypeScript のメリット・デメリット
◎ TypeScript のメリット
- ✓コードを書いた段階でバグを発見できる(実行前エラー検出)
- ✓IDE の補完・型ヒントが充実してコーディング効率が上がる
- ✓コードが自己文書化されてチーム開発の可読性が高まる
- ✓React・Next.js など主要フレームワークとの相性が抜群
- ✓リファクタリングが安全・高速にできる
- ✓求人市場での需要が高くスキルとして評価される
△ デメリット・注意点
- ✗JavaScript に比べて学習コストが少し高い
- ✗型定義を書く分、コード量がやや増える
- ✗外部ライブラリに型定義(@types)が必要な場合がある
- ✗小規模スクリプトや使い捨てコードには過剰な場合がある
- ✗コンパイルステップが増えるのでビルド時間が若干伸びる
まとめ
TypeScript は「JavaScript に型をつけた言語」ですが、その恩恵は非常に大きいです。
- コードを書いた段階でバグを発見できる
- IDE のサポートが強力になり、開発効率が上がる
- チーム開発での可読性・保守性が向上する
最初は型を書くのが面倒に感じるかもしれませんが、慣れてくると「型がないと不安」と感じるほど自然に使えるようになります。
学習の始め方としては、まず string, number, boolean, interface の基本4つをマスターすることをおすすめします。それだけでも JavaScript のコードがぐっと安全になります。
2026年のフロントエンド開発において TypeScript はもはや必須スキルです。ぜひ公式ドキュメントから一歩踏み出してみてください。