TypeScriptでクラスを扱う際の基本的な概念から実践的な使い方まで、わかりやすく解説します。

クラスの基本

TypeScriptでクラスを定義する基本的な構文は以下の通りです:

class Person {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  greet() {
    console.log(`こんにちは、${this.name}です`);
  }
}

プロパティの型付け

クラスのプロパティには、明示的に型を指定することができます:

class User {
  private id: number;
  public name: string;
  protected email: string;
}

アクセス修飾子について:

  • `private`: クラス内からのみアクセス可能
  • `public`: どこからでもアクセス可能(デフォルト)
  • `protected`: クラスとそのサブクラスからアクセス可能

コンストラクタと初期化

TypeScriptでは、コンストラクタを使って効率的にプロパティを初期化できます:

class Employee {
  constructor(
    private id: number,
    public name: string,
    protected department: string
  ) {}
}

この書き方は、プロパティの宣言と初期化を同時に行えます。

継承の実装

TypeScriptでクラスを継承する方法:

class Animal {
  constructor(protected name: string) {}
  
  makeSound() {
    console.log("Some sound");
  }
}

class Dog extends Animal {
  constructor(name: string) {
    super(name);
  }

  makeSound() {
    console.log("Woof!");
  }
}

インターフェースの実装

クラスにインターフェースを実装する例:

interface Movable {
  move(): void;
  getPosition(): { x: number, y: number };
}

class Car implements Movable {
  constructor(private x: number, private y: number) {}

  move() {
    this.x += 1;
    this.y += 1;
  }

  getPosition() {
    return { x: this.x, y: this.y };
  }
}

抽象クラス

抽象クラスを使用した例:

abstract class Shape {
  abstract getArea(): number;
  
  printArea() {
    console.log(`面積は${this.getArea()}です`);
  }
}

class Rectangle extends Shape {
  constructor(private width: number, private height: number) {
    super();
  }

  getArea(): number {
    return this.width * this.height;
  }
}

staticメンバー

静的メンバーの使用例:

class MathUtil {
  static PI: number = 3.14159;
  
  static calculateCircleArea(radius: number): number {
    return this.PI * radius * radius;
  }
}

console.log(MathUtil.calculateCircleArea(5));

readonly プロパティ

読み取り専用プロパティの定義:

class Config {
  readonly API_KEY: string;

  constructor(key: string) {
    this.API_KEY = key;
  }
}

以上の内容を理解することで、TypeScriptでのクラスベースのオブジェクト指向プログラミングを効果的に行うことができます。各機能を適切に組み合わせることで、保守性の高い堅牢なコードを書くことが可能になります。

実際のプロジェクトでは、これらの機能を状況に応じて使い分けることが重要です。特に、カプセル化やインターフェースの使用は、大規模なアプリケーション開発において重要な役割を果たします。