【TS】クラスのメソッドとプロパティは違うよって話

1 min読了の目安(約1500字TECH技術記事

はじめに

今回はTypescriptで継承関係にあるクラスにおいて、親のメソッドをsuperで呼び出した際に発生したエラーについてご紹介します。
原因が分かればなんてことない話だったのですが、思ったよりハマったので情報共有もかねて。

問題のコード

hogeという関数を持つParentClassと、それを継承したChildClassの2クラスです。
ChildClasshogeでは、親であるParentClasshogeを呼び出しています。

/**
 * 親クラス
 */
class ParentClass {
  hoge : () => void = () => console.log("Hoge");
}

/**
 * 子クラス
 */
class ChildClass extends ParentClass {
  hoge : () => void = () => {
    super.hoge();
    console.log("Hoge2");
  }
}

const child = new ChildClass();
console.log(child.hoge()); // ---> "Hoge"のあとで"Hoge2"が表示されそうだが・・・?

"super"でエラーが出る

実は上記のコードだとChildClasshoge内でエラーが出ます。
具体的には親クラスのhogeを呼び出しているsuper.hoge()の箇所で以下エラーとなります。

'super' キーワードを使用してアクセスできるのは、基底クラスのパブリック メソッドと保護されたメソッドのみです。ts(2340)

省略していますがhoge自体はpublicになっているので問題はなさそうです。
では、どのあたりが原因でこのエラーが出ているのでしょうか?

なぜエラーになる?

これはParentClasshogeの書き方に問題があります。
アロー関数を使って今風な書き方をしていますが、これは実は 「クラスのプロパティ」 を定義していることになります。

superで扱うことができるのは 「クラスメソッド」 なので、メソッドでないプロパティに対してsuperを指定しても当該のエラーが発生するという仕組みです。

修正

ParentClasshogeの書き方を修正します。
もともとあったアロー関数の書き方ではなく、クラス内メソッドとして定義します。

class ParentClass {
  // これはプロパティ
  //hoge : () => void = () => console.log("Hoge");
  // これはメソッド
  hoge() {
    console.log("Hoge");
  }
}

実行結果

Hoge
Hoge2

これで期待通りの結果になりました。

まとめ

今回はTypescriptの継承関係があるクラスにおけるプロパティとメソッドについて紹介しました。
ここ最近はReactReactNativeでも関数コンポーネントばかり書いているので、そもそもクラスを書く機会がなく、なかなか原因に気づけずにハマりました。

プロパティとして記載している場合でも動作はするので、super等を使わない限りなかなか発生しにくいエラーだと思います。