抽象クラス

抽象クラス(abstract class)を使うと、あるプロパティ値の定義を必ず行ってほしいことを継承先のクラスへ伝えることができます。

抽象クラスは、単体では使うことができません。必ずクラスで継承して使います。
インターフェース(interface)との違いは、抽象クラスは共通になりそうな部分はプロパティ値を入れたりやメソッドを実装した状態で用意できる点です。

抽象クラスを定義する

クラスはclassというワードで定義していましたが、これはabstract classというワードで定義します。

abstract class A {
  abstract foo: string;

  abstract bar(): string;

  baz() {
    console.log('baz');
  }
}

そして、クラスの継承のようにextendsのあとに置くだけです。以下のように書いただけの時AAは型エラーになります。

class AA extends A {}
// Non-abstract class 'AA' does not implement inherited 
// abstract member 'bar' from class 'A'.
//
// Non-abstract class 'AA' does not implement inherited
// abstract member 'foo' from class 'A'.

これはabstractアクセス修飾子を付けて宣言したものは、継承先で必ず実装しなければならない為です。foobarを以下のように実装すれば型エラーは解消できます。

class AA extends A {
  foo = 'foo';
  bar() {
    return 'bar';
  }
}

インスタンスを作成した時に、bazは抽象クラスで宣言したものがそのまま使うことができます。もちろんAAで実装したfoobarも使えます。

const aa = new AA();
aa.baz();
// 'baz'

aa.foo;
aa.bar();

抽象クラスの継承

抽象クラスは以下のように継承することができます。

abstract class AA extends A {
  foo = 'foo';
  abstract qux: string;
}

fooを抽象プロパティではなくしたり、新たな抽象プロパティ・メソッドを宣言することができます。

これを継承して作るクラスはbarquxの実装が必須になります。

class AAA extends AA {
  bar() {
    return 'bar';
  }
  qux = 'qux';
}