はじめに
前回に引き続き、グレープシティがHTML/JavaScript環境に向けて提供するJavaScriptライブラリWijmo(ウィジモ)と、さまざまなJavaScriptフレームワークやライブラリと組み合わせてアプリケーションを作成します。
前回は、Web技術デスクトップアプリを開発するフレームワークであるElectronとReactを利用しました。今回はさらにTypeScriptを組み合わせていきます。
なお、今回もサンプルコードは以下のリポジトリに用意しています。
TypeScriptとは
Microsoftが開発するTypeScriptは、動的型言語であるJavaScript(ECMAScript)に、静的型を導入した言語です。
ECMAScriptは、国際機関が制定しているECMA-262という規格で、JavaScriptから言語仕様のみを抜き出したものです。毎年6月ごろに仕様が追加されています。JavaScriptとは、言語仕様としてのECMAScriptに、Webブラウザ向けの仕様であるDOM(Document Object Model)などを総合したものと言えます。
すなわち、TypeScriptはECMAScriptの上位互換として、静的型の機能を追加した言語仕様ということです。また、TypeScriptのコードをECMAScriptに変換するコンパイラ(TypeScript compiler)も提供されています。
今やJavaScript開発はSPA(Single Page Application)が当たり前となり、片手間で開発できるものではなくなってきています。TypeScriptはそういった大規模・高度化している開発を、ある程度安全にできるため、世界的にもシェアを伸ばし続けている人気の言語です。
コンパイラの設定によっては型チェックなどを緩めることも可能なので、JavaScriptのコードを段階的に移行できることも人気のポイントです。
型の恩恵
例えば、Reactのコンポーネントを型定義しておくと、呼び出し元で誤ったプロパティを入れたときや、必須プロパティが足りないときに、コンパイラが静的にエラーを出してくれます。
// Labelコンポーネント const Label: React.FC<{ color: string; label: string; size: number; }> = ({ color, label, size }) => { return <label style={{ color, fontSize: ${size}px }}>{label}</label>; };
こうして定義したLabel
コンポーネントは、<Label color="#cc0000" label="ラベル" size={24} />
のように利用します。
このコンポーネントは、color
label
size
の3つのパラメータの指定が必須であり、color
とlabel
は文字列(string
)で、size
は数値型(number
)でなければいけません。
例えば、<Label color={1} label="ラベル" size={24} />
のように誤ったプロパティを渡そうとすると、Type 'number' is not assignable to type 'string'.
という、数値型と文字列型が食い違っていることを知らせるエラーが出ます。
また<Label color="#cc0000"/>
のように必須プロパティを省略した場合には、Type '{ color: string; }' is missing the following properties from type 'Props': label, size
という、label
とsize
が足りないことを知らせるエラーが出ます。
このようにTypeScriptを使えば、関数の引数やReactコンポーネントのプロパティに指定すべき値を必須にしたり、型を指定したりすることで、不注意でバグを出してしまう可能性を減らせます。
IDE支援
TypeScriptの効能はこれだけではありません。
Web開発で人気のあるVisual Studio CodeはTypeScriptコンパイラを使って、IDE機能を実現しています。JavaScriptで書かれたコードでも、ある程度のIDEによる支援を受けられますが、本領を発揮できるのはTypeScriptのコードです。
先ほど紹介したLabel
のようなコンポーネントがいっぱいあるプロジェクトに新しく入ったとします。いちいちラベルコンポーネントの使い方を他の人に聞き回るのも非効率でしょう。
VSCodeでReact+TypeScript開発を行う場合、その程度の情報であれば、エディタ(IDE)が教えてくれます。
function App() { return <L }
「L」まで打ち込んだ状態で、スペルを覚えていなかったとしても、IDEが候補を出してくれます。
先頭にあるLabel
を選択すると、
function App() { return <Label }
この通り補完されます。
パラメータはどうでしょうか? 先ほどの必須パラメータを省略したときと同じ挙動を示してくれます。
Label
コンポーネントがどう定義されているか表示されていますし、エラーメッセージとしてcolor
label
size
が必須パラメータであることを教えてくれます。
では、パラメータを入力していきましょう。color
のためにc
を打ち込んだ時点で候補が出てきます。
function App() { return <Label c }
color
かchildren?
の2択に絞り込めます。children?
のように末尾に?
がついているものは省略可能です。
ここでもcolor
はstring
型であると教えてくれるので、color
に該当しそうな文字列を指定すれば大丈夫です。
同様の手順を踏んで、color
label
size
を指定すれば、正しくLabel
コンポーネントを利用できるでしょう。
JSDocを活用する
コンポーネントの設計が明確、つまりプロパティの名前がわかりやすく、型が適切であれば使い方がある程度理解できるはずですが、より適切な開発をするためには JSDocと呼ばれる、コード内に記述するドキュメントを活用するといいでしょう。
/** ラベルコンポーネント */ const Label: React.FC<{ /** CSSのcolorで指定可能なカラーコード */ color: string; /** ラベルの内容 */ label: string; /** フォントサイズ(px) */ size: number; }> = ({ color, label, size }) => { return <label style={{ color, fontSize: ${size}px }}>{label}</label>; };
このように/** 中身の説明 */
をコメントするだけで、参照可能なドキュメントになります。コンポーネント名や関数名、引数名やプロパティを、マウスホバーすると参照できます。
Label
をマウスホバーした場合は「ラベルコンポーネント」という説明が表示されるようになりました。
color
なら「CSSのcolor
で指定可能なカラーコード」という説明が表示されます。
TypeScriptでより快適な開発を
ここまでの説明の通り、TypeScriptはECMAScriptに静的型を導入した言語であり、大規模・複雑化するJavaSrcipt開発を、より安全に行える人気の言語です。関数や、Reactコンポーネントなどに型をつけることで、引数やプロパティの型を、適切に制限できるため、誤った使い方を事前に検出できます。
VSCodeなどのIDEを使えば、コード入力中の候補や、使い方についての表示を出してくれるため開発効率を上げることができます。特にJSDocと呼ばれるコード内ドキュメントを活用すれば、IDE上で簡単に参照できます。
次のページではReact+TypeScript+Electron+Wijmoのコードを書きながらTypeScriptのパワーを見ていきましょう。