TypeScriptはMicrosoftが開発したJavaScriptのスーパーセットで、静的型付けを追加した言語です。2024年以降、多くの企業でJavaScriptに代わりTypeScriptが標準採用されており、現代のフロントエンド・バックエンド開発の必須スキルとなっています。
本記事では、JavaScriptは分かるがTypeScriptを使ったことがない方から、TypeScriptをより深く理解したい中級者まで、実践的な内容を体系的に解説します。
なぜTypeScriptを使うべきか?
1. バグを事前に防げる
TypeScriptの最大のメリットは、コンパイル時にエラーを検出できることです。JavaScriptでは実行時に初めて気づくバグも、TypeScriptなら開発中にIDEが警告してくれます。
// JavaScript(実行するまでエラーが分からない)
function greet(name) {
return "Hello, " + name.toUpperCase();
}
greet(42); // 実行時エラー: name.toUpperCase is not a function
// TypeScript(コンパイル時にエラー検出)
function greet(name: string): string {
return "Hello, " + name.toUpperCase();
}
greet(42); // コンパイルエラー: Argument of type 'number' is not assignable to parameter of type 'string'
2. コードの可読性・保守性が向上
型情報がドキュメントの役割を果たします。関数の引数・戻り値の型を見るだけで、その関数の使い方が理解できます。チーム開発での協力が格段に楽になります。
3. IDEサポートの強化
VS Codeなどのエディターで強力な自動補完・リファクタリング支援が受けられます。コードを書くスピードが大幅に上がります。
TypeScript 基本の型
// プリミティブ型
const name: string = "田中太郎";
const age: number = 25;
const isActive: boolean = true;
// 配列
const scores: number[] = [85, 92, 78];
const names: Array<string> = ["Alice", "Bob", "Charlie"];
// オブジェクト型
type User = {
id: number;
name: string;
email: string;
role?: "admin" | "user"; // オプショナル・ユニオン型
};
const user: User = {
id: 1,
name: "田中太郎",
email: "tanaka@example.com"
};
// 関数の型
function add(a: number, b: number): number {
return a + b;
}
// アロー関数
const multiply = (a: number, b: number): number => a * b;
インターフェースと型エイリアス
// Interface(継承可能)
interface Animal {
name: string;
sound(): string;
}
interface Dog extends Animal {
breed: string;
}
const dog: Dog = {
name: "ポチ",
breed: "柴犬",
sound: () => "ワン!"
};
// Type Alias(ユニオン型・交差型に使いやすい)
type ID = string | number;
type AdminUser = User & { permissions: string[] };
ジェネリクス(Generics)
ジェネリクスを使うと、型に依存しない汎用的なコードを書けます。
// ジェネリック関数
function identity<T>(arg: T): T {
return arg;
}
const str = identity<string>("hello"); // "hello"
const num = identity<number>(42); // 42
// ジェネリックなAPIレスポンス型
type ApiResponse<T> = {
data: T;
status: number;
message: string;
};
type UserResponse = ApiResponse<User>;
type PostListResponse = ApiResponse<Post[]>;
実践的なTypeScriptパターン
Discriminated Union(判別可能なユニオン型)
type Shape =
| { kind: "circle"; radius: number }
| { kind: "rectangle"; width: number; height: number }
| { kind: "triangle"; base: number; height: number };
function area(shape: Shape): number {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "rectangle":
return shape.width * shape.height;
case "triangle":
return (shape.base * shape.height) / 2;
}
}
Utility Types(組み込みユーティリティ型)
type User = {
id: number;
name: string;
email: string;
password: string;
};
// 全フィールドをオプショナルに
type PartialUser = Partial<User>;
// 特定フィールドのみ抽出
type PublicUser = Pick<User, "id" | "name" | "email">;
// 特定フィールドを除外
type SafeUser = Omit<User, "password">;
// 読み取り専用
type ReadonlyUser = Readonly<User>;
tsconfig.jsonの重要な設定
{
"compilerOptions": {
"target": "ES2022", // 出力するJSのバージョン
"module": "ESNext", // モジュールシステム
"strict": true, // 厳格モード(推奨)
"noImplicitAny": true, // any型の暗黙的な使用を禁止
"strictNullChecks": true, // null/undefinedの厳格なチェック
"esModuleInterop": true, // CommonJSとの互換性
"paths": { // パスエイリアスの設定
"@/*": ["./src/*"]
}
}
}
まとめ:TypeScriptでコードの品質を高めよう
TypeScriptは習得するほどにコードの品質・開発体験・チーム協力の効率を高めてくれる強力なツールです。JavaScriptのコードは基本的にそのままTypeScriptとして動くため、既存プロジェクトへの段階的な導入も可能です。
まずはstrict: trueでプロジェクトを設定し、型エラーと向き合いながら少しずつ理解を深めていきましょう。