TypeScriptによる型指定やクラスの実装を体験
次に、TypeScriptについて説明します。図4のサンプルでは、図3と同じ内容を、Vue.jsを利用せず、TypeScriptで実装しています。
図4のサンプルを表示するHTMLファイルの<body>部はリスト4の通りです。Vue.jsを利用しないため、テキストボックス(1)、名前表示(2)、ボタン(3)の各要素に、後でJavaScriptで操作するためのIDをつけています。また、これから実装するJavaScript(my-first-ts.js、index.js)を(4)で参照しています。
<div> あなたの名前:<input id="name-input" value=""><!-- テキストボックス ...(1)--> <div>→あなたは<span id="name-disp"></span>さん</div><!-- 名前の表示 ...(2)--> <button id="greet-btn">あいさつ</button> <!-- ボタン ...(3)--> </div> <script src="my-first-ts.js"></script><!-- JavaScriptを参照 ...(4)--> <script src="index.js"></script>
リスト4の(4)で参照されるJavaScriptを、TypeScriptで実装する方法を以下で説明していきます。
TypeScriptを利用するための環境準備
TypeScriptを利用するには環境の準備が必要です。まずリスト5のコマンドでTypeScript環境をプロジェクトに導入します。「--save-dev」オプションは、開発時に利用するパッケージとしてTypeScriptを導入することを表します。
npm install --save-dev typescript
TypeScript環境には、TypeScriptファイルをJavaScriptに変換するコンパイラー(tscコマンド)が含まれます。サンプルコードではtscコマンドを利用するために、プロジェクト設定ファイルpackage.jsonに以下コマンドを定義しています。
"scripts": {
"tsinit": "tsc --init", // ...初期化(1)
"build": "tsc", // ...コンパイル(2)
"serve": "lite-server" // ...実行(3)
},
(1)の「tsc --init」は、「npm run tsinit」コマンドで実行できます。このコマンドは、プロジェクトにTypeScriptの設定ファイルtsconfig.jsonを初期設定します(tsconfig.jsonは、今回は初期設定のまま利用します)。このプログラムはtsconfig.jsonを生成する最初の1回だけ実行します。
tsconfig.jsonがプロジェクトに存在する状態で、(2)の「tsc」(つまり「npm run build」コマンド)を実行すると、プロジェクトに含まれるTypeScriptのファイル(*.tsファイル)が、対応するJavaScriptファイル(*.jsファイル)に変換されます。
なお(3)は、「npm run serve」コマンドでlite-server(Webサーバー)を起動してWebページを表示する定義です。
TypeScriptの実装とコンパイル
TypeScriptの利用準備が完了したので、リスト7の通り、あいさつ文を取得するMyFirstTSクラスをTypeScriptファイルで実装していきます。
class MyFirstTS {
// プライベート変数 ...(1)
private name = '' // 型推論でstring型となる
// コンストラクター ...(2)
public constructor(newName: string) {
// this.nameはstring型なのでstring型のnewNameが代入できる ...(3)
this.name = newName
}
// あいさつのメソッド ...(4)
public getGreetText(): string {
return `${this.name}さん、TypeScriptの世界にようこそ!`
}
}
(1)ではプライベート変数nameを記述しています。ここで「name = ''」と空文字列を初期設定することで、内部的にnameは文字列型であると決定されます。このようにTypeScriptでは、実装内容から型を決定する機能(型推論)が利用できます。
(2)のconstructorはクラスのコンストラクターです。ここで引数の「newName: string」は、newName引数が文字列(string)型であることを表します。このようにTypeScriptでは、明示的に変数の型を指定できます。ここでは(3)の通り、プライベート変数nameに、引数のnewNameを代入しています。nameとnewNameは両方とも文字列型なので代入可能です。
(4)はあいさつを取得するメソッドです。プライベート変数nameを「this.name」で参照して、あいさつ文の文字列にして返却しています。
リスト7のmy-first-ts.tsを実装後、「npm run build」コマンド(で内部的に実行される「tsc」コマンド)でコンパイルすると、リスト8のJavaScriptファイルmy-first-ts.jsが生成されます。型定義の記述がなくなり、クラスやメソッドの定義が変換されていることに注目してください。
"use strict";
// クラスの実装
var MyFirstTS = /** @class */ (function () {
// コンストラクター
function MyFirstTS(newName) {
// プライベート変数
this.name = ''; // 型推論でstring型となる
// this.nameはstring型なのでstring型のnewNameが代入できる
this.name = newName;
}
// あいさつのメソッド
MyFirstTS.prototype.getGreetText = function () {
return this.name + "\u3055\u3093\u3001TypeScript\u306E\u4E16\u754C\u306B\u3088\u3046\u3053\u305D!";
};
return MyFirstTS;
}());
TypeScriptからJavaScriptへのコンパイル例をもう一つ示します。HTMLファイルに処理内容を設定するindex.tsを、TypeScriptでリスト9の通り実装します。
// 名前の初期設定 ...(1)
(document.getElementById('name-input') as HTMLInputElement).value = // ...(1a)
document.getElementById('name-disp')!.textContent = '吉川英一' // ...(1b)
// テキストボックス変更時の処理 ...(2)
document.getElementById('name-input')!.addEventListener('input', function () {
// テキストボックスの文字列を取得 ...(2a)
const inputValue
= (document.getElementById('name-input') as HTMLInputElement).value
// 文字列をラベルに設定 ...(2b)
document.getElementById('name-disp')!.textContent = inputValue
})
// ボタンクリック時の処理 ...(3)
document.getElementById('greet-btn')!.addEventListener('click', function () {
// テキストボックスの文字列を取得 ...(3a)
const inputValue
= (document.getElementById('name-input') as HTMLInputElement).value
// MyFirstTSクラスを利用してあいさつ文を作ってダイアログ表示 ...(3b)
const myFirstTS = new MyFirstTS(inputValue)
alert(myFirstTS.getGreetText())
}
)
(1)はWebページに表示する名前の初期設定です。document.getElementByIdメソッドでHTML要素を取得して値を設定しています。(1a)の「as HTMLInputElement」は、HTML要素が<input>であることを明示的に表し、(1b)の「!.」はメソッドがnullを返却する可能性を無視してプロパティを参照することを表します。これらはTypeScriptで型定義を厳密に行うための記法です。
(2)はテキストボックス変更時の処理です。テキストボックスのinputイベントが発生するごとに、(2a)で文字列を取得し、(2b)でラベルに設定します。
(3)はボタンクリック時の処理です。(3a)で文字列を取得後、(3b)でMyFirstTSクラスのインスタンスを生成して、そのgetGreetTextメソッドであいさつ文を作ってダイアログ表示します。
TypeScript固有の記述を含むリスト9をコンパイルすると、JavaScriptファイルindex.jsがリスト10の通り生成されます。リスト10では、TypeScript固有の「as HTMLInputElement」や「!.」の記述が削除されます。また細かいところでは、リスト9で「const」としたところがリスト10では「var」になっています。
"use strict";
// 名前の初期設定
document.getElementById('name-input').value =
document.getElementById('name-disp').textContent = '吉川英一';
// テキストボックス変更時の処理
document.getElementById('name-input').addEventListener('input', function () {
// テキストボックスの文字列を取得
var inputValue = document.getElementById('name-input').value;
// 文字列をラベルに設定
document.getElementById('name-disp').textContent = inputValue;
});
// ボタンクリック時の処理
document.getElementById('greet-btn').addEventListener('click', function () {
// テキストボックスの文字列を取得
var inputValue = document.getElementById('name-input').value;
// MyFirstTSクラスを利用してあいさつ文を作ってダイアログ表示
var myFirstTS = new MyFirstTS(inputValue);
alert(myFirstTS.getGreetText());
});
このようにTypeScriptのコードを実装後にコンパイルすると、対応するJavaScriptのコードが得られます。
TypeScriptで型指定を誤ってエラーになる様子を体験
ここで、TypeScriptの型指定を誤った時の挙動を説明します。リスト7(2)のnewName変数を数字(number)型に直した後でコンパイルを実行すると、図5の通りエラーが表示され、コンパイルが完了しません。
また、開発環境によっては、テキストエディターで型チェックを行ってエラーを表示してくれます。図6は、図5のエラーが出る状態のコードをVisual Studio Codeで表示した時のエラーです。
このようにTypeScriptでは、データ型などの記述誤りはエラーになるため、プログラマーは誤りを事前に知ることができ、JavaScriptのコードが抱えがちなあいまいさを排除して実装が行えます。
なお、今回はTypeScriptを単独で利用するため、TypeScriptインストールなどの環境準備が必要でしたが、Vue.jsのプロジェクトを生成するVue CLIでは、TypeScriptが利用できるプロジェクトを自動で生成できます。詳細は次回説明します。
まとめ
本記事では、TypeScriptを利用してVue.jsを活用する連載の1回目として、Vue.jsとTypeScriptのそれぞれについて、簡単なサンプルで実装例を紹介しました。Vue.jsを利用して動的なWebページを構築できること、TypeScriptを利用して型を意識したあいまいさのない実装が行えることを示しました。
次回は、Vue CLIを利用してVue.jsのプロジェクトを生成し、実際にVue.jsとTypeScriptを組み合わせて実装する方法を説明していきます。
