プログラミング8分で読める

TypeScript入門 - JavaScriptに型を加えるメリット

TypeScriptの基本概念と、導入することで得られるメリットをわかりやすく解説します。

TypeScriptとは

TypeScriptは、JavaScriptに「型」の概念を追加したプログラミング言語です。Microsoftが開発し、現在はReact、Vue、Angular、Node.jsなど多くのプロジェクトで標準的に使用されています。

TypeScriptのコードは最終的にJavaScriptに変換(コンパイル)されるため、ブラウザやNode.jsでそのまま実行できます。既存のJavaScriptコードに段階的にTypeScriptを導入することも可能です。

なぜTypeScriptを使うのか

🐛

バグ削減

型エラーを実行前に検出

📝

可読性向上

コードの意図が明確に

🔧

開発効率

強力な自動補完

👥

チーム開発

コードの理解が容易

基本的な型の使い方

プリミティブ型

最も基本的な型です。変数名の後に : 型名 を付けて型を指定します。

プリミティブ型の例
// 文字列型
const name: string = "田中太郎";
const greeting: string = `こんにちは、${name}さん`;

// 数値型
const age: number = 25;
const price: number = 1980.5;

// 真偽値型
const isActive: boolean = true;
const hasPermission: boolean = false;

// 型が合わないとエラー!
// const age: number = "25";  // Error: 文字列を数値型に代入

配列型

配列の型は 型名[] または Array<型名> で指定します。

配列型の例
// 文字列の配列
const fruits: string[] = ["りんご", "バナナ", "オレンジ"];

// 数値の配列
const scores: number[] = [85, 92, 78, 95];

// Array形式でも書ける
const names: Array<string> = ["田中", "鈴木", "佐藤"];

// 配列操作も型安全
fruits.push("ぶどう");      // OK
// fruits.push(123);         // Error: number は string に代入不可

// 配列メソッドの戻り値も型推論される
const doubled = scores.map(score => score * 2);  // number[]型

オブジェクト型

オブジェクトのプロパティごとに型を指定できます。

オブジェクト型の例
// インラインでオブジェクトの型を定義
const user: { name: string; age: number; isAdmin: boolean } = {
  name: "田中太郎",
  age: 25,
  isAdmin: false
};

// オプショナルプロパティ(?をつける)
const product: { name: string; price: number; description?: string } = {
  name: "Tシャツ",
  price: 2980
  // descriptionは省略可能
};

インターフェースと型エイリアス

インターフェース(interface)

複雑なオブジェクトの型を再利用可能な形で定義します。

インターフェースの定義
// ユーザー情報の型を定義
interface User {
  id: number;
  name: string;
  email: string;
  age?: number;           // オプショナル
  readonly createdAt: Date; // 読み取り専用
}

// インターフェースを使用
const user: User = {
  id: 1,
  name: "田中太郎",
  email: "tanaka@example.com",
  createdAt: new Date()
};

// user.createdAt = new Date();  // Error: readonlyは変更不可

// インターフェースの拡張
interface AdminUser extends User {
  role: "admin" | "superadmin";
  permissions: string[];
}

const admin: AdminUser = {
  id: 100,
  name: "管理者",
  email: "admin@example.com",
  createdAt: new Date(),
  role: "admin",
  permissions: ["read", "write", "delete"]
};

型エイリアス(type)

typeを使うと、より柔軟な型定義が可能です。

型エイリアスの例
// 基本的な型エイリアス
type ID = string | number;  // ユニオン型
type Status = "pending" | "active" | "completed";  // リテラル型

const userId: ID = "user_123";   // OK
const orderId: ID = 456;         // OK
const status: Status = "active"; // OK
// const status: Status = "unknown"; // Error!

// オブジェクト型の定義
type Product = {
  id: number;
  name: string;
  price: number;
  category: "食品" | "衣料" | "家電";
};

// 交差型(複数の型を組み合わせ)
type Timestamped = {
  createdAt: Date;
  updatedAt: Date;
};

type ProductWithTimestamp = Product & Timestamped;

関数の型定義

関数の引数と戻り値の型

関数の引数と戻り値にも型を指定できます。

関数の型定義
// 基本的な関数
function add(a: number, b: number): number {
  return a + b;
}

const result = add(5, 3);  // result は number 型

// アロー関数
const multiply = (a: number, b: number): number => a * b;

// オプショナル引数とデフォルト値
function greet(name: string, greeting: string = "こんにちは"): string {
  return `${greeting}、${name}さん!`;
}

greet("田中");              // "こんにちは、田中さん!"
greet("田中", "おはよう");  // "おはよう、田中さん!"

// void型(戻り値なし)
function logMessage(message: string): void {
  console.log(message);
}

コールバック関数の型

コールバックの型定義
// 配列のforEachのコールバック
const numbers: number[] = [1, 2, 3];
numbers.forEach((num: number, index: number) => {
  console.log(`${index}: ${num}`);
});

// 関数型の定義
type CalculateFunc = (a: number, b: number) => number;

const subtract: CalculateFunc = (a, b) => a - b;
const divide: CalculateFunc = (a, b) => a / b;

// 高階関数
function applyOperation(
  a: number,
  b: number,
  operation: CalculateFunc
): number {
  return operation(a, b);
}

applyOperation(10, 5, subtract);  // 5
applyOperation(10, 5, divide);    // 2

実践的なコード例

例1: API レスポンスの型定義

APIレスポンスの型安全な処理
// APIレスポンスの型定義
interface ApiResponse<T> {
  success: boolean;
  data: T;
  error?: string;
}

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

// API呼び出し関数
async function fetchUser(id: number): Promise<ApiResponse<User>> {
  const response = await fetch(`/api/users/${id}`);
  return response.json();
}

// 使用例
async function displayUser() {
  const result = await fetchUser(1);

  if (result.success) {
    console.log(result.data.name);   // 型安全にアクセス
    console.log(result.data.email);  // 自動補完も効く
  } else {
    console.error(result.error);
  }
}

例2: フォームバリデーション

型安全なフォームバリデーション
// フォームの型定義
interface RegistrationForm {
  username: string;
  email: string;
  password: string;
  confirmPassword: string;
}

// バリデーションエラーの型
type ValidationErrors = Partial<Record<keyof RegistrationForm, string>>;

// バリデーション関数
function validateForm(form: RegistrationForm): ValidationErrors {
  const errors: ValidationErrors = {};

  if (form.username.length < 3) {
    errors.username = "ユーザー名は3文字以上必要です";
  }

  if (!form.email.includes("@")) {
    errors.email = "有効なメールアドレスを入力してください";
  }

  if (form.password.length < 8) {
    errors.password = "パスワードは8文字以上必要です";
  }

  if (form.password !== form.confirmPassword) {
    errors.confirmPassword = "パスワードが一致しません";
  }

  return errors;
}

// 使用例
const formData: RegistrationForm = {
  username: "taro",
  email: "taro@example.com",
  password: "password123",
  confirmPassword: "password123"
};

const errors = validateForm(formData);
if (Object.keys(errors).length === 0) {
  console.log("バリデーション成功!");
}

例3: ジェネリクスの活用

ジェネリクスで汎用的な関数を作成
// 配列の最初の要素を取得(型安全)
function getFirst<T>(arr: T[]): T | undefined {
  return arr[0];
}

const firstNumber = getFirst([1, 2, 3]);      // number | undefined
const firstString = getFirst(["a", "b"]);    // string | undefined

// 汎用的なデータストア
class DataStore<T> {
  private items: T[] = [];

  add(item: T): void {
    this.items.push(item);
  }

  getAll(): T[] {
    return [...this.items];
  }

  find(predicate: (item: T) => boolean): T | undefined {
    return this.items.find(predicate);
  }
}

// 使用例
const userStore = new DataStore<User>();
userStore.add({ id: 1, name: "田中", email: "tanaka@test.com" });
userStore.add({ id: 2, name: "鈴木", email: "suzuki@test.com" });

const user = userStore.find(u => u.id === 1);  // User | undefined

始め方

1
インストール

npm install -g typescript でグローバルインストール

2
ファイル作成

.ts拡張子でファイルを作成(例: app.ts)

3
コンパイル

tsc app.ts でJavaScriptに変換

4
設定ファイル

tsc --init で tsconfig.json を生成

まとめ

TypeScriptは初期の学習コストはありますが、バグの早期発見、コードの可読性向上、強力なIDEサポートなど、それ以上のメリットがあります。特にチーム開発や長期プロジェクトでは必須と言えるでしょう。まずは既存のJavaScriptプロジェクトに少しずつ導入してみることをお勧めします。

H
honualohak編集部

テクノロジーで人々の日常をより便利に。AI、プログラミング、Web開発に関する情報を発信しています。