TypeScriptでスタティックコンストラクタを書く方法の小ネタです。
C#では普通にスタティックコンストラクタを記述できますが、TypeScriptでは書けないようです。
先日「あったらいいな」という状況がありましたので、それっぽい記述を探ってみました。ちょっと無理やりなんですけどね。
スタティックコンストラクタ?
スタティックコンストラクタとは、主にクラスのスタティックフィールドを初期化するためのもので、最初のインスタンスが生成される前に一度だけ動いてほしいクラスメソッド(みたいなもの)です。
複数のスタティックフィールドを同時に初期化したい場合や、元情報を加工して実行時に使用する情報を作成するといった場合に有用です。
スタティックフィールドを即時実行関数で初期化する
スタティックコンストラクタがなくても、スタティックフィールドは普通に個別に初期化できます。 さらにこの時、以下のように無名関数を即時実行してその戻り値で初期化するのも可能です。
class MyClass { static foo:string = (()=> { return "foo"; })(); }
スタティックコンストラクタみたいな記述
無名関数の即時実行を利用すれば、TypeScriptでスタティックコンストラクタ(のようなもの)を以下のように書けます。
class MyClass { static foo:string = "foo"; /** * スタティックコンストラクタ(のようなダミーのフィールド)。 */ static ctor = (()=>{ MyClass.foo = "bar"; })(); }
static ctor
というダミーのスタティックフィールドを定義して、即時実行した無名関数の戻り値で初期化しています(ここでは無名関数が何も返していないので結果的には null になります)。
ダミーの名前は ctor
である必要はありませんが、本来のインスタンスのコンストラクタとかぶりますから constructor
にはできません。
注意すべき点
スタティックフィールドが上から初期化されるということには少し注意が必要です。
以下のように、スタティックコンストラクタよりも下でスタティックフィールドを宣言し、かつ初期化していると意図した動作になりません。コンパイルエラーが出ないので厄介です。
class MyClass { /** * スタティックコンストラクタ(のようなダミーのフィールド)。 */ static ctor = (()=>{ MyClass.foo = "bar"; })(); static foo:string = "foo"; }
初期化していなければ問題はありませんが、ややこしいのでスタティックフィールドはクラス宣言の上のほうで宣言しておいたほうがよさそうですね。
あと、確実にユニットテストを記述するのも有効です。