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()
) のパラメータ名の前に、private
や public
といった可視性を指定すると、プロパティ定義とその値を設定するコードを省略することができます。
次のようなコードは、
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()
でコンストラクタを呼び出せるところがポイントです。
関連記事
- TypeScript のコーディング規約(ルール/ガイドライン)
- TypeScriptの型: 既存の JavaScript ライブラリに型情報を追加する(.d.ts ファイル)
- TypeScriptサンプル: ジェネリッククラスの定義例(MyStackクラス)
- TypeScriptサンプル: 文字列内のひらがなとカタカナを変換する (hiraToKana, kanaToHira)
- TypeScriptの型: クラス定数を定義する (static readonly)
- TypeScriptのモジュールのインポートには import を使う
- TypeScriptの型: インタフェースを結合する (交差型: Intersection types)