TypeScriptで拡張メソッドを実現する
タイトルで違和感を感じれば多分正しくjavascrptを理解してる。
javascriptで拡張メソッドどうやってやるのみたいなアホな思考に浸っていた
— kamiya (@kam1yan___) 2014, 3月 19
TypeScript触っててprototypeの存在忘れてた
— kamiya (@kam1yan___) 2014, 3月 19
自分も調べていて気付いた。
c sharp
static class Extension { public static void Hoge(this string str){ Console.WriteLine(str); } } //"foo".Hoge()
みたいなやつ。これでstringの拡張メソッドが実現するわけだが、javascriptなんてそもそもがprototypeに勝手にバンバン定義していくだけのものだと理解すべきであって
javascript
String.prototype.hoge = function(){ console.log("Hoge!") } "foo".hoge();
これが当たり前。むしろこれ以外の手段は知らない。TypeScriptに汚染されてここらの概念すら忘れていたがおかげて少し理解が深まった。
本題
残念ながら上のjavascriptと同じようなコードをTypeScriptでやってもエラーになる。
proto.ts(2,18): error TS2094: The property 'hoge' does not exist on value of type 'String'. proto.ts(6,7): error TS2094: The property 'hoge' does not exist on value of type 'string'.
当然である。定義されてないものが使えたらもはやTypeScriptの存在意義すら怪しい。
解決
ところでWebページ作っている時も思ったがinterfaceはコンパイルする段階で消滅して、いわば実装側に[Interface Name].prototype.XXXXの部分を提供しているだけだということに気づく。
interface、もしかして名前の重複とか関係ないのでは?と気づいたのが幸いだった。
TypeScript
interface String { hoge(); } String.prototype.hoge = () => { console.log("Hoge!"); }; "foo".hoge;
吐出されるコードはjavascriptで書いたコードと全く同じだった。ちなみにinterfaceだけだとコンパイルすると何も残らない*1