ひ孫

犬のこととか書いていきたい

/// reference path やだー

typescript大好き。
でも、許せなことがひとつある。

/// <reference path="node.d.ts">

↑こいつ。

何をする時に使うかって言うと他のtsファイルを参照している時に使うものだ。
どうやら出典としてはVisual Studioあたりで/// みたいなことをすると補完してくれるというところからっぽい。

しかし結局補完のされない普通のエディタでやってる分には恩恵がない。(typescriptオンリーで使う分には正直visual studioは使いものにならない・・)
が、こいつが無いとコンパイルが通らなかったりする。(正確には通すこともできたけど)

なんとかならんかとちょっと調べてみた。

そもそも reference path とは

公式ドキュメントを読んでも上記の構文が出てくるのは一箇所だけで、ファイルの依存関係を解決するものだよとの事。
更に非公式なとこでの情報だがこれは別にjs変換後まで保たれるわけじゃないのでそこらへんは知らんよという事らしい。

使わなくても良いパターン

exportでモジュールを書いてそれを呼び出し先でimportするやり方の場合、reference pathはいらない(内部でちゃんと解決してくれる)
例えばこんなかんじ
module.js

export class hoge{
   fuga(){
     console.log("aaa");
   }
}

main.js

import mod = module('module');
new mod.hoge().fuga() // aaa

*1

module('module_path')はパスをたどってくれたりもするので、自分で組む分には全部上記の様な感じでexportとimportで書くと良い。

が、やっぱりこれでは解決しない問題がある。
それが例にあげたようなnode.d.tsとか。
http://typescript.codeplex.com/SourceControl/changeset/view/fe3bc0bfce1f#samples%2fnode%2fnode.d.ts
サンプルコードを掲示する。
見ると、exportされていない。
ひたすらにdecrareが書かれている。

色々調べたり試行錯誤したりしていると幾つか打開策が見つかった

打開策その1

特定プロジェクト下のtsファイル全てにインポートするファイルのを埋め込むスクリプトを書く!

打開策その2
tsc hoge.ts node.d.ts

つまりコンパイル時にまとめてコンパイルしちゃえばいい!
毎回コンパイルするスクリプトをバッチ化しておけば問題無さそう。
「必ずgruntjsでコンパイルしましょう」ってルールとかにしちゃうとかすればありかも。

打開策その3

完全にやる必要が無いレベル。だけどちょっと面白いなあと思ったのでメモ

grunt-typescriptのソースを読んで
あれあれ?これだったらいけちゃうんじゃない?と思った部分がこのへん

 compiler.addUnit(unit.code, unit.fileName, false);

本家のtypescriptのコードを見てみてもlib.d.tsを読み込んでるとこでも使ってるみたい。
こうやって複数ファイルを読み込んでるんだったら先にライブラリ系のやつをモリモリ食わせておいたコンパイラー作っとけばよくね?
ということでこれを応用すれば最初からいろんな物を増々にした独自Typescriptコンパイラーが作れるのでは!と思いました。
https://gist.github.com/4061517

結局打開策2でやってることとほとんど変わんねーじゃんっていう話な気がしました。
馬鹿でかくなった時1ファイルごとにライブラリ全部読んでコンパイルとかよりはもしかして高速になるんじゃないかなあ(願望)

まとめ

そもそもreference pathsってなくていいの?という疑問は未だ払拭できていません。
正直ドキュメントを見た感じだと必ず書きなさいって具合なのかどうかはちょっとわからない。
結局書かなくても通ってしまうし動きは変わらないのだから良いんじゃないか(逆に言うともしダメならコンパイラの段階でこかさないといかんのでは?)
と思うしlib.d.tsはコンパイラがreference path無しでも読み込んでいるんだから他のファイルがそういうふうになってたっていいじゃないか!
とは思ったりします。(そもそもreference pathがきもいなーと思っている人自体少ないかもしれないですね。今更)
オープンなプロジェクトだったりしたらやめたほうがいいのかもしれないですね。

*1:requireが有効なnode環境などじゃないとちゃんと動かないコード