モダンなWebアプリケーションでは、JavaScriptコードの量は日に日に増しています。多くのコードが必要になる中で、それらすべてを一つのファイル内で開発することは不可能といってよいでしょう。
そこでTypeScriptを利用すれば、ファイルが分かれている状態でも型が解決できるようになっており、モジュールごとにファイルを分割した開発が可能になります。加えて、型定義ファイルを用意することで、既存のJavaScriptライブラリを改変することなく、そのまま利用することができます。
今回は、Modules/AsynchronousDefinition(AMD)、または、CommonJSの仕様に準拠したモジュール機構や、既存のJavaScriptライブラリの利用方法について紹介します。
環境構築
連載第1回で紹介したSublimeText3用のプラグインは、現在のところ、ファイルを超えたインテリセンスなどの支援をサポートしていません。ですが開発版では利用できるため、プラグインをプロジェクトをdevブランチに切り替えます。
Sublime Textを開き、ツールバーから「Preferences」の「Browse Packages…」を選択します。開いたフォルダ内のT3Sフォルダをターミナルで開きます。
第1回目のインストール時にはGitを利用して導入しているので、ただブランチを切り替えるだけでプラグインの更新は完了です。
$ git checkout dev
次に、プロジェクトフォルダを作成します。SublimeTextは、任意のフォルダをプロジェクトとして開くことができます。ツールバーから「File」の「Open Folder…」を選択し、プロジェクトにするフォルダを開きます。この解説では、”ts_project”フォルダを新規作成したものとします。
そして、プロジェクトフォルダ直下に”.sublimets”ファイルを新規作成します。この設定ファイルにプロジェクトの設定を記述します。今回は次のように設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
{ "root": "app.ts", "settings": { "activate_build_system":true, "auto_complete":true, "node_path":"none", "error_on_save_only":false, "build_on_save":true, "show_build_file":true, "build_parameters":{ "pre_processing_commands":[], "post_processing_commands":[], "output_dir_path":"./build", "concatenate_and_emit_output_file_path":"none", "source_files_root_path":"none", "map_files_root_path":"none", "module_kind":"amd", "allow_bool_synonym":false, "allow_import_module_synonym":false, "generate_declaration":false, "no_implicit_any_warning":true, "skip_resolution_and_preprocessing":false, "remove_comments_from_output":false, "generate_source_map":true, "ecmascript_target":"ES5" } } } |
外部モジュール
前回(第三回)では、名前空間を構成する内部モジュールを紹介しました。TypeScriptでは、この内部モジュールとは異なり、外部モジュールと呼ばれるモジュール機構があります。外部モジュールでは、プログラムをファイル単位でモジュール化することができ、ビルドオプションによって、AMD、または、CommonJSの仕様に準拠したJavaScriptコードを生成することができます。
前回のおさらいですが、内部モジュールは、 module キーワードと exportキーワードを使用します。モジュール内がカプセル化され、export指定されたものだけが外部から参照できます。
1 2 3 4 5 6 |
module Sample{ export Class Class1{} class Class2{} } var class1 = new Sample.Class1(); var class2 = new Sample.Class2(); // error |
外部モジュールでは、TypeScriptファイル自体がモジュール化され、他のTypeScriptファイルからインポートすることができるようになります。外部モジュールを記述するには、トップレベルにexportキーワードを付け、インポートには import - require 文を利用します。外部モジュールのコンパイルには、 moduleビルドオプションの設定が必須のため、”.sublimets”ファイルの settings.build_parameters.module_kindが amdまたは commonjsのどちらかになっていることを確認します。
1 2 |
export class Class1(); class Class2(); |
1 2 3 |
import Sample = require("classes") var class1 = new Sample.Class1(); var class2 = new Sample.Class2(); // error |
requireに拡張子を除いたファイルパスを渡すことで、外部モジュールをインポートすることができます。内部モジュールと同様に、export指定されていないオブジェクトは参照するできません。また、外部モジュールと内部モジュールは併用できます。
1 2 3 4 5 6 7 |
export module A{ export class Class1{} class Class2{} } export module B { export class Class3{} } |
1 2 3 |
import modules = require("modules"); var class1 = new Modules.A.Class1(); var class3 = new Modules.B.Class3(); |
内部モジュールを利用し、名前空間を切りつつ、外部モジュールを利用して、コンポーネント化することができます。 外部モジュールのコードをコンパイルすると、require文が出力されますが、前述のとおりビルドオプションを設定することで、AMDまたはCommonJSのどちらかに出力することが可能です。フロントエンドで使用する場合はAMD形式に出力し、require.jsを利用してロードします。
リファレンスパス
require.jsを使わず、ただ、HTMLにscriptタグを連ねてファイル分けを行う場合には、リファレンスパスを利用します。リファレンスパスはコメント文を利用しており、 /// <reference path="sample.ts"/> によって記述します。
1 2 3 4 |
... <script src="sample.js"></script> <script src="app.js"></script> ... |
1 2 3 |
module Sample { export class Class1{} } |
1 2 |
/// <reference path="sample.ts"/> var class1 = new Sample.Class1(); |
型定義ファイル
先のリファレンスパスを利用することで、既存のJavaScriptライブラリを利用することができます。 TypeScriptでは、 declareキーワードを用いて、すでにあるオブジェクトに対して、型付けを行うことができます。これをアンビエント宣言と呼びます。アンビエント宣言を行うことで、既存のJSライブラリのクラスやオブジェクトに型付けを行い、TypeScriptから参照できるようになります。
アンビエントは、型の定義のみで実装を持ちません。そのため、インターフェースはすでにアンビエントです。インターフェース以外の変数やクラスは declareキーワードを先頭につけ、インターフェースと同様に実装を記述しないように型のみを定義することでアンビエントを定義できます。
アンビエント宣言は別ファイルに分離し、拡張子を .d.tsとした型定義ファイルファイルを作成することが慣習的になっています。 例えば、次のような既存JSファイルmylib.jsがあるとします。これをapp.tsで利用するには、型定義ファイルを作成し、リファレンスパスによって参照します。
1 2 3 4 5 6 7 |
var MyLib = { version: "1.0.0" , message: "Hello" , output: function () { console.log(this.message); } } |
1 2 3 4 5 |
declare var MyLib: { version: string; message: string; output: ()=>void; }; |
1 2 |
/// <reference path="mylib.d.ts"/> MyLib.output(); |
このように、型定義ファイルを用意することで既存のJSライブラリに手を加えず、そのままTypeScriptで利用できます。また、jQUeryなどの人気のあるJavaScriptライブラリの型定義ファイルはTSD(TypeScript Definition manager)を使用することでダウンロードできます。TSDは、型定義ファイルのリポジトリ、DefineTypedのマネージャでDefineTypedに集まっている多くの型定義ファイルを管理できます。
TSDはNPMからインストールします。
$ npm install -g tsd
このTSDを用いて、jQueryの型定義ファイルをダウンロードしてみます。
$ tsd query jquery --action install
ダウンロードした型定義ファイルをリファレンスパスで参照することで、jqueryを利用するコードをTypeScriptで記述することができます。
また、 declaration コンパイルオプションを指定することによってコンパイル時にTypeScriptファイルから型定義ファイルを自動生成できます。あくまで、生成できるのはTypeScriptからでJavaScriptをそのまま変換することはできないので注意が必要です。
まとめ
全4回でTypeScriptを紹介してきました。第1回目で述べた通り、TypeScriptは次の特徴を持った言語です。
- JavaScriptのコードそのまま解釈でき、既存コードから開発をスタートできる。
- また、クラスやインターフェース、モジュール化などでコンポーネント化がより容易になる。
- かつ、型の検査やインテリセンス、リッチデバッグ環境で大規模開発を助けてくれる。
繰り返しになりますが、TypeScriptは型注釈を行うことで、型の不一致から発生するバグを実行前に検知し修正することができます。また、クラスや内部モジュールや外部モジュールによって、コンポーネント化が容易になります。
また、TypeScriptはJavaScriptのスーパーセットでもあり、次世代JavaScriptの仕様を先取りしているだけでなく、アンビエント宣言を用いることで既存のJavaScriptライブラリも型注釈して利用できます。開発環境に関しても、この連載ではSublime Text 3を取り上げましたが、Visual StudioやIntelliJ IDEAなどTypeScriptを力強くサポートしてくれるIDEもあります。
ぜひ皆さんも、TypeScriptでモダンなWebアプリケーション開発を体験してみてください!
コメント