[TypeScript] 内部モジュール (Internal Module) の整理の仕方を考える

2014/10/31

こんにちは。きんくまです。

TypeScriptで内部モジュールを使うときのことです。(外部モジュールじゃないです)

>> 内部モジュール – TypeScript クイックガイド – phyzkit.net

仕事でクラスファイルが多くなり、1ファイル1クラスにして、各ファイルにそれぞれreferenceを書いていました。

そしたらコンパイルは通って js は生成されるのに、実行時にこんなエラーが発生して困りました!!

Uncaught TypeError: Cannot read property 'prototype' of undefined main.js:4
Uncaught TypeError: undefined is not a function 

コンパイルが通るのに、エラーが出てしまい原因が特定できず大変困りました。
すると、reference部分の順番を入れ替えると戻ることがありました。

クラスを継承していたり、moduleが分かれているといろいろと問題ありそうです。

それをTwitterでつぶやいたところ、教えてもらいました!ありがとうございます!!

それでどうやるか自分でも実験してみました。

どうやって内部モジュールをまとめるか

アイデアをいただいていろいろと試したところ、以下のようにしようかなと思いました。

1. moduleごとにjsファイルは分けてコンパイル
(最終的にはそれを、使用される順に連結して1枚にしてもOK)

ここでコンパイラに指定するtsファイルを、エントリクラスファイルとする。

2. moduleごとにそのmodule内のエントリクラスファイルを除いた全てのファイルを参照する専用ファイルを1枚作る

3. moduleのエントリクラスファイルから2のファイルだけを参照する

4. その他のファイルには一切 reference を書かない

2の参照ファイルを書く際には約束事があって

・継承を行うときは、必ずサブクラスは親クラスの後に書く
(これをしないと冒頭のCannot read property ‘prototype’エラーがでます)

・declarationファイル(.d.tsファイル)の位置はどこでもOK。
でも別moduleを参照する際は必ず記入

実際に試してみる

1. moduleごとにjsファイルは分けてコンパイル

今回はサンプルで2つのモジュールを使います。なので、2つコンパイルします。
gruntの設定はこんなのとか。

    	typescript:{
            qmodule:{
                src:[
                    'htdocs/src/q_Q.ts'
                    ],
                     
                dest:'htdocs/q_q.js',
                options:{
                    basePath:'htdocs/src',
                    target: 'es5',
                    sourceMap: false,
                    declaration: true
                }
            }
    		,default:{
    			src:[
                    'htdocs/src/main.ts'
                    ],
                     
    			dest:'htdocs/main.js',
    			options:{
                    basePath:'htdocs/src',
                    target: 'es5',
                    sourceMap: false
    			}
    		}
    	}

2. moduleごとにそのmodule内のエントリクラスファイルを除いた全てのファイルを参照する専用ファイルを1枚作る

今回のサンプルではAクラスを継承したM_extAクラスがあるとします。

kk_file_refs.ts

/*
 * declaration files
 */

/// <reference path="jquery.d.ts" />
/// <reference path="../q_q.d.ts" />

/*
 * class files
 *
 * A.ts と M_extA.ts の位置を入れ替えると実行時エラー
 */

/// <reference path="A.ts" />
/// <reference path="C.ts" />
/// <reference path="B.ts" />

/// <reference path="M_extA.ts" />

3. moduleのエントリクラスファイルから2のファイルだけを参照する

main.ts

/// <reference path="kk_file_refs.ts" />
module kk{
	export class Main{
		constructor(){
			console.log('hello');

			new M_extA();
		}
	}
}

4. その他のファイルには一切 reference を書かない

例えばこんな感じに全く書きません。

module kk{
	export class M_extA extends A{
		constructor(){
			super();

			console.log('M extends A');
			
			new B();

			new q.Q();
		}
	}
}

ファイル名とかぐっちゃぐちゃだけど、参考までにデータ一式アップします
internal_module.zip

とりあえずこれで整理はできそうかも。また何か問題があったら追記します。

エラーのおきていた70ファイルぐらいに分かれていたプロジェクトもこれで直りました。やったー。


自作iPhoneアプリ 好評発売中!
フォルメモ - シンプルなフォルダつきメモ帳
ジッピー電卓 - 消費税や割引もサクサク計算!

ページトップへ戻る