まくろぐ
更新: / 作成:

TypeScript のクラスは、Java や Kotlin に似た文法で定義します。 インタフェースの定義に似ていますが、コンストラクタやメソッドを持つことができるという大きな違いがあります。

簡単なクラス

次の Greeter クラスは、1 つのプロパティ、1 つのコンストラクタ、1 つのメソッドを持っています。

class Greeter {
  // プロパティの定義(デフォルトで public)
  private name: string;

  // コンストラクタの定義
  constructor(name: string) {
    this.name = name;
  }

  // メソッドの定義(デフォルトで public)
  greet() {
    console.log(`Hello, ${this.name}`);
  }
}

コンストラクタやメソッドの前に function というキーワードは必要ないことに注意してください。 プロパティやメソッドの可視性は デフォルトで public になるため、外部からアクセスできないようにするには、明示的に private と指定する必要があります。

クラスのインスタンスを生成するには、次のように new キーワードを使用します。

const greeter = new Greeter('Maku');
greeter.greet();  //=> 'Hello, Maku'

プロパティ定義の省略

コンストラクタ (constructor()) のパラメータ名の前に、privatepublic といった可視性を指定すると、プロパティ定義とその値を設定するコードを省略することができます。

次のようなコードは、

class Book {
  private name: string;

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

次のように省略して記述することができます。

class Book {
  constructor(private name: string) {}
}

public でリードオンリーなプロパティとして定義する場合は、こんな感じ。

class Book {
  constructor(public readonly name: string) {}
}

コンストラクタのデフォルト引数

関数のパラメータと同様に、コンストラクタのパラメータでもデフォルト引数の仕組みを使用できます。

class Indentor {
  constructor(private indentStr: string = '  ') {}

  indent(level: number): string {
    return this.indentStr.repeat(level);
  }
}

// コンストラクタのパラメータは省略可能
const indentor = new Indentor();
console.log(indentor.indent(0) + 'AAA');  //=> 'AAA'
console.log(indentor.indent(1) + 'BBB');  //=> '  BBB'
console.log(indentor.indent(2) + 'CCC');  //=> '    CCC'

プロパティの setter/getter を定義する

メソッド名の前に set キーワード、 get キーワードを付けて定義することで、プロパティの setter/getter を定義することができます。 setter はプロパティへの代入時 (obj.prop = value) に呼び出され、getter はプロパティの参照時 (value = obj.prop) に呼び出されます。 setter/getter には可視性を指定することはできず、必ず public として扱われます。

次の例では、title という名前の setter/getter を定義しています。 実際の値は、_title というプライベートプロパティに保存しています。

class Book {
  private _title: string = '';

  set title(value: string) {
    console.log('setter が呼ばれたよ');
    this._title = value;
  }

  get title(): string {
    console.log('getter が呼ばれたよ');
    return this._title;
  }
}

const b = new Book();
b.title = 'タイトル';  // setter が呼ばれたよ
console.log(b.title);  // getter が呼ばれたよ → タイトル

次のように getter だけを定義しておけば、外からは値を変更できないリードオンリーなプロパティを定義することができます。 下記の Counter クラスの count プロパティは参照専用で、外から値を代入できないようになっています。

class Counter {
  constructor(private _count: number = 0) {}
  tick() { this._count += 1; }
  get count(): number { return this._count; }
}

const counter = new Counter();
counter.tick();
counter.tick();
counter.tick();
console.log(counter.count);  //=> 3

上記のように getter のみを提供することは、プロパティ自体に readonly キーワードを付けるのとは異なることに注意してください。 プロパティに readonly を付けると、クラスの中からもその値を変更できなくなります。 次のようにクラス定数を定義するときに使えます。

class TaxCalculator {
  private static readonly RATE = 0.10;
  static calc(price: number) : number {
    return Math.floor(price * (1 + TaxCalculator.RATE));
  }
}

console.log(TaxCalculator.calc(100));  //=> 110

(応用)プライベートコンストラクタ

コンストラクタ (constructor) を private 定義することで、外部からの new 呼び出しを禁止することができます。 代わりに、static なファクトリメソッドを用意してインスタンス生成できるようにします。

export class MyData {
  static of(value: string): MyData {
    return new this(value)
  }

  // 外部からのコンストラクタ (new) の直接呼出しは禁止
  private constructor(public readonly value: string) {}
}

static メソッドから、this() でコンストラクタを呼び出せるところがポイントです。

関連記事

まくろぐ
サイトマップまくへのメッセージ