モジュールの書き方
練習コードを書いてみて分かったことを備忘録的に書いてみる。
とりあえず、TypeScript っぽい構文のコードと JavaScript のコードを付きあわせて説明していくと思う。
% tsc --version message TS6029: Version 1.6.2
空のモジュール
TypeScript っぽいコードだとこういう風にすごい簡単だけど:
module M { }
M
はとりあえずモジュールの名前だとする。
JavaScript だとこんなにめんどい:
var M = (function (M) { return M; })( typeof M === 'undefined' ? M : {} );
匿名関数に渡している typeof M === 'undefined' ? M : {}
はコンテキストとして使われる。
もうひとつのパターン
外側のモジュールを入れておく変数である M
に代入しない方式もある:
var M; (function (M) { })( typeof M === 'undefined' ? M : {} );
この場合では:
var M; (function (M) { function piyo() { console.log( 'Hello, World!' ); } M.piyo = piyo; // 必ず M.piyo に piyo を設定しておくこと。 })( typeof M === 'undefined' ? M : {} ); M.piyo(); // error! piyo が存在しない!!
みたいにモジュールを定義した後にモジュールの中身を使うことができない。
また、M
が defined
な場合の {}
を exports
とか module.exports
にしておくと:
var M; (function (M) { })( typeof M === 'undefined' ? M : {} ); module.exports = M;
みたいに最後の方に module.exports = M
というようなことをしなくても済む。
エクスポートしたいモジュール
TypeScript にはモジュールやクラス、関数に export
と付けることで外部に見せたいなーという表明をすることができると私は理解しているんだけれど:
export module M { export function piyo() { console.log( 'Hello, World!' ); } }
というコードを tsc
でコンパイルすると:
var M; (function (M) { function piyo() { console.log('Hello, World!'); } M.piyo = piyo; })(M = exports.M || (exports.M = {}));
という感じになって:
var M = require( './M' ); M.piyo(); // error! piyo は存在しない!!!
はエラーになってしまう。
関数のエクスポート方法を見ると、別にこうでも良いのではないかという気がしている:
var M; (function (M) { function piyo() { console.log('Hello, World!'); } M.piyo = piyo; })(M || {}); exports = M;
で、今になって理解したのだけど、M.M.piyo();
ならいけるのか。
var M = require( './M' ); M.M.piyo(); // => Hello, World!
そこら辺、よくわかっていないのでアレなんだけど、TypeScript は require
関連が何かおかしいという気がする。
こうなって欲しい
ということで、さっきの TypeScript っぽいコードが:
export module M { export function piyo() { console.log( 'Hello, World!' ); } }
コンパイルするとどーなって欲しいかというと、こうなって欲しい:
var M = (function (M) { function piyo() { console.log( 'Hello, World!' ); } M.piyo = piyo; return M; })( typeof M === 'undefined' ? M : module.exports );
モジュールで他のモジュールを使いたいなーという時はまた後ほど書きたいかもしれない。 おしまい。