JavaScript
ActionScript
TypeScript

TypeScriptでのイベント名を管理・指定するもう一つの方法(+ストリングリテラル型にも対応)

More than 1 year has passed since last update.

TypeScriptでのイベント名をclickで指定するのはもう辞めようという記事を読んで。ActionScriptでも同様な管理を公式が用意してくれていたのでとても便利だったのを思い出しました。ところがTypeScriptはあんまり公式でこういったものを用意してくれません。こういったコードの安全性やメンテナンス製に関わる箇所は公式が運用を広めるべきなんですが…。

namespace + const

さて、TypeScriptでは上記の方法以外にもいい方法があります。それはnamespaceconstを使う方法です。

/**
 * イベント名を列挙したネームスペース
 */
export namespace EventName{
    export const LOAD = "load";
    export const CLICK = "click";
    export const MOUSE_MOVE = "mousemove";
}

window.addEventListener(EventName.LOAD, ()=>{alert("ウィンドウのロードが完了しました。")});

EnumClass1をつかった方法に比べると以下の利点があります。

  1. constで宣言できるので再代入がコンパイルエラーになる
  2. 無駄にクラスを作らず無駄が無い
    • クラスとして作ると、使いたい定数以外にコンストラクタやprototypeプロパティなど不要なフロパティも生成され、無駄が多いです
    • TypeScriptのnamespaceは只のObjectなのでシンプルです

ストリングリテラル型 + namespace + const

TypeScript1.8から ストリングリテラル型 が入りました。イベント名のような文字列で指定するものを型チェックできるもので、より厳密なチェックができます。

type SomeEvent = "click" | "load" | "mousemove";
function doSomething(ev: SomeEvent){}

doSomething("click");   //compile ok
doSomething("klik");    //compile error

ただし、この厳密さは上記のものにも適応され、そのままではコンパイルエラーになります。

文字列型はストリングリテラル型と合わないので中身が同じでもエラーになる
doSomething(EventName.CLICK); //compile error

ストリングリテラル型にも対応したイベント名の管理方法は以下になります。

ストリングリテラル型として定義
/**
 * イベント名を列挙したネームスペース(ストリングリテラル型ver.)
 */
export namespace EventName{
    export const LOAD:"load" = "load";
    export const CLICK:"click" = "click";
    export const MOUSE_MOVE:"mousemove" = "mousemove";
}

doSomething(EventName.CLICK);   //ok

文字列のEnumがないTypeScriptで、文字列Enumっぽいことをするには現状これが一番近いと思います。

まとめ

  • TypeScriptのイベント名はnamespace+constの管理方法もある
  • 無駄が少なく、再代入防止というメリットがある
  • ストリングリテラル型+namespace+constで文字列のEnumっぽくチェックと管理ができる

  1. 特にTSで名前はついてないと思いますが、ASではそう呼ばれていたと記憶しています 

  2. ただし、近い将来readonlyがプロパティに対して付けられるようになるので、メソッド等と一緒に管理するならその方法もありだと思います