Open3

【typescript】クラス自体を変数で扱う

yuuyuyuuyu

クラス自体とは。

class A {
  a: string;
  constructor(a: string) {
    this.a = a;
  }
}

Aのこと。インスタンス化していないクラスそのもの。
名前自体がいまだによく分かっていない(コンストラクタ関数?)

staticや動的インスタンス化などで使いたいが、その時のメモ(まとめたら記事にするかもしれない)

yuuyuyuuyu

変数に代入してみる

普通に変数に代入しようとすると、エラーが出る。

const classA: A = A; // Property 'a' is missing in type 'typeof A' but required in type 'A'.

書いていて気がついたが、エラーで型書いてあった[1]。typeof Aと書くことで代入することが出来る。

ちなみに、この型には、Aを継承したクラスも代入できる。

class B extends A {
  b: string;
  constructor(a: string, b: string) {
    super(a);
    this.b = b;
  }
}
const classA: typeof A = A; // OK
const classB: typeof A = B; // OK
脚注
  1. const classA: A = A;とは書けないなぁ、どうやって書くことが出来るんだろう?という考えが先に来てコード書くより先に調べてた。 ↩︎

yuuyuyuuyu

変数に代入できるかを判定する

今度は逆に、クラス自体を変数に入れるために、与えられたクラスがAを継承しているかどうかを判定する。
これを判定する方法を調べたところ、prototypeを使うことで判定することが出来る。

function checkClass(targetClass: any) { // targetClassはクラス自体
  if (targetClass.prototype instanceof A) {
    console.log("targetClass is an instance of A or its subclass");
  } else {
    console.log("targetClass is not an instance of A or its subclass");
  }
}
checkClass(A); // targetClass is not an instance of A or its subclass...?
checkClass(B); // targetClass is an instance of A or its subclass
checkClass(class C {}); // targetClass is not an instance of A or its subclass

これでいけると思ったが、checkClass(A)の結果がelse文の方になった。
調べたところ、prototypeは継承元を参照するためのプロパティであるため、本体であるAのprototypeにAは存在しないからtrueにならない。

ではどうやって判定するかというと、、、まだ分かっていない。
とりあえず思いつくのは直接比較する。

function checkClass(targetClass: any) {
  if (targetClass === A || targetClass.prototype instanceof A) {
    console.log("targetClass is an instance of A or its subclass");
  } else {
    console.log("targetClass is not an instance of A or its subclass");
  }
}

おそらく他の方法がある、気がする。