実践
TypeScriptことはじめ
第1回 TypeScriptを取り巻く環境

TypeScriptは、書かれたコードをコンパイルするとJavaScriptに変換される言語です。また、静的型付けを備えているという特徴もあります。まずはこれらの特徴を見ていきましょう。

2017年09月14日発行

目次

はじめに

本シリーズではTypeScriptについて解説します。TypeScriptについて扱ったCodeGridの記事としては、過去に「探検、TypeScript」というシリーズがありますが、これはTypeScriptのバージョン0.9のときに書かれたものです(2013年に掲載)。本記事執筆現在の最新版はバージョン2.5.2ですので、本シリーズではこの4年間にTypeScriptを取り巻く環境で起こった変化や新しい話題を含めながら、改めてTypeScriptを紹介していきます。

TypeScriptとは

TypeScriptは、マイクロソフトによって開発され、2012年に発表されたプログラミング言語のひとつです。この言語の特徴は大きく2つあります。

1つ目に、TypeScriptで書かれたコードはJavaScriptのコードに変換されるという特徴があります。そのため、変換後のコードは純粋なJavaScriptとして動作します。TypeScriptで書かれたコードを変換することをコンパイル*といい、コンパイルするためのソフトウェア(コンパイラ)をtscといいます。

*注:コンパイル

コンパイルとは、本来はプログラムのソースコードをコンピュータが実行するための形式に一括で変換することを示します。しかし、TypeScriptの話題の中においては、JavaScriptに変換することを指します。

また、TypeScriptは型を備えています。型とは、文字列型、数値型、ブーリアン型といったデータの種類のことです。それだけでなく、変数や関数の引数、戻り値などのあらゆる値について、その型がプログラムの実行前にあらかじめ決められるという性質を持っているのが、2つ目の大きな特徴です。この性質を持つ言語を静的型付け言語と呼びます(前シリーズの記事でも詳しく解説しています)。静的型付けに対して、プログラムの実行時まで型が決まらない言語の性質を、動的型付けといいます。JavaScriptは動的型付け言語です。

これら2つの特徴から、TypeScriptはJavaScriptに変換される静的型付け言語と言えます。TypeScriptの静的型付けの利点については、このあと解説していきます。

2017年におけるAltJSの現状

こういったTypeScriptの特徴を踏まえつつ、2017年現在までのここ数年の、TypeScriptを取り巻く状況を見てみましょう。

5年ほど前から、TypeScriptの登場やCoffeeScriptの流行など、JavaScriptに変換できる言語が次々と開発されました。このような言語は俗にAltJSという言葉で総称されています。また、Babel*というツールも、大規模なJavaScriptの開発現場ではよく見かけるようになりました。

*注:AltJSやBabel

Babelや、AltJSのひとつであるCoffeeScriptについては次のシリーズを参照してください。

AltJSやBabelを用いて、わざわざ異なる言語や構文を現在のブラウザで動作するJavaScriptに変換している理由は、JavaScriptの言語仕様の実装速度がブラウザベンダーごとに異なり、同じJavaScriptでもブラウザごとに使える構文が揃っていないためです。その差を埋めるため、現状のどのブラウザでも問題なく動くように変換するというアプローチを取る方向に発展しました。

TypeScript登場当時の2012年には、まだES2015(「ECMAScriptとJavaScriptの関係」を参照)が存在せず、ES3やES5が主流でした。そのためクラス構文やアロー関数式が使えるTypeScriptを使うことは、後述する静的型付けの恩恵を得られるだけでなく、未来のECMAScriptの構文を先取りして書けるという利点も含まれていました。

しかし、2017年現在では、IE11以外のモダンブラウザ、すなわちChrome、Firefox、Edge、Safari(macOS最新またはiOS 10以上)でES2015のほぼすべての仕様が、変換を必要とせずに動作します。つまりTypeScriptの登場当時より、AltJSとしての利点は薄まっているといえます。

それでもなおTypeScriptが選ばれる理由は、なんといっても静的型付けを備えている点です。さらにいうと、TypeScriptはJavaScriptのスーパーセット*であるので「JavaScriptは何も書き換えずにそのままTypeScriptとして振る舞うことができる」という特性があり、これは「段階的に静的型付けを導入していける」というメリットにつながります。

*注:スーパーセット

すべてのJavaScriptは、いっさい書き換えることなくTypeScriptのコードとして振る舞うことができます。逆にTypeScriptにしか定義されない構文を含んだコードは、JavaScriptとしては振る舞えません。このような上位互換をもつ言語をスーパーセットと呼びます。

TypeScriptへの追い風

マイクロソフトによって開発されたTypeScriptですが、大きなニュースとして2017年4月7日、Google社内の標準言語として採用されたことが発表されました。これは、Googleが中心となって開発しているJavaScriptライブラリ「Angular」のイベントである、「ng-conf 2017」にて行われたものです。

Googleには社内標準言語というものがいくつか存在しており、Google社内では、標準言語以外の言語を開発に用いることはできなかったようです。しかし、TypeScriptが2年の社内審査を経て標準言語として採用、追加されたと発表されました。そのため、今後Google社内でも広く普及していくことが予想できます。

また、Angularは「AngularJS」の次世代バージョンですが、このライブラリも利用時の推奨言語としてTypeScriptを挙げています。つまりAngularを用いた開発の際には、JavaScriptのままではなくTypeScriptを採用することが推奨されているのです。

これらの話題はTypeScriptにとって、とても追い風となるものです。マイクロソフトが開発する「Visual Studio Code」はWindows、macOS、Linuxで動作するフリーのIDE(統合開発環境)ソフトウェアですが、TypeScriptが最初からサポートされており、これはAngularを開発するGoogleのエンジニアも愛用しているものです。こういった言語の普及やサポートの充実は、TypeScriptの言語としての安定性が増すことにつながり、多くの開発者はこの言語を採用しやすくなります。

大規模開発におけるTypeScript

さて、TypeScriptの特徴として、静的型付けを備えている点があると前述しました。この利点について、現在のWeb開発における大規模案件の現状を含めて考えてみましょう。

ES2015が策定され、ES5から大幅に機能が追加されたJavaScriptでは(「ECMAScript 2015の新機能」を参照)、クラス構文やアロー関数式、Promise、コレクションクラスといった機能は昨今のWebアプリケーション開発には欠かせないものとなりました。Web標準のAPIも充実し、表現力の増したフロントエンドでは、これまでより大規模なソフトウェアの開発が求められることも少なくありません。

大規模なソフトウェアの開発の場合、少人数では開発に時間がかかってしまいます。そのため開発の速度を上げるために、しばしば開発チームは増員されます。増員された結果、開発者ごとのスキルやコードを書く癖はバラつくようになり、コードレビューや自動テストの実施が強く求められるようになります。こういった仕組みで統一的にチェックをしないと、大人数では品質を均一に保てなくなるためです。

コードのミスをすべて実行時に発見しているようでは、バグは減らせません。そうかと言って、すべてのif文を手動でひとつひとつ通して検証するのは、時間の無駄となります。こういった問題は機械に自動的に指摘させるのがよいでしょう。

TypeScriptは静的型付け言語のため、変数名のtypo、値の渡し忘れなど、コンパイルに失敗するような記述のミスについて、すべて自動的にコンパイルエラーとして落とします。自動テストを増やすことももちろん大事ですが、ある程度の範囲の問題については、TypeScriptのコンパイルエラーによっても防ぐこともできます。そうすることで、自動テストでは純粋にビジネスロジックの複雑な計算について検証でき、些細なミスをわざわざ自動テストによって防ぐ必要はなくなります。リファクタリングの際も、ある一箇所を変更したときにどこに影響が及ぶか、コンパイラが検知してくれます。

また、コード内に型注釈(Type annotations)を記述していくため、これは有益なドキュメントとなります。コメント形式の記述とは違い、コンパイラが解釈するためその内容には嘘がなく、常にメンテナンスされた状態のドキュメントのようになり得ます。

このようなことを考えると、ES2015や、もっと新しいJavaScriptの言語仕様が充実したとしても、TypeScriptの優位性がなくなることはありません。

TypeScriptを始める

ここまで、TypeScriptのここ数年の事情や、採用される理由について紹介しました。続いては具体的にTypeScriptの始め方を紹介します。

Visual Studio 2017やVisual Studio 2015 Update 3には、TypeScriptが最初からインストール内容に含まれていますが、ここでは、Visual Studioを用いないTypeScript単独の導入方法として解説します。

TypeScriptのインストールにはnpmが必要です。npmで次のコマンドを実行します。

$ npm install -g typescript

TypeScriptのインストールはこの1行で完了します。そして、次のコマンドを実行してバージョンが出力されれば、インストールは成功しています。

$ tsc -v
Version 2.5.2

それではTypeScriptのコードを書いてみましょう。お好きなエディタを使って新規ファイルを作成し、ファイル名はgreeter.tsとしてみましょう。内容は次のようにします。

function greeter(person) {
    return "Hello, " + person;
}
var user = "Jane User";
document.body.innerHTML = greeter(user);

続いて、TypeScriptのコードをJavaScriptにコンパイルします。コンパイルするためにはgreeter.tsが保存されているディレクトリ内で、次のコマンドを実行してください。

$ tsc greeter.ts

これでgreeter.jsが生成されました。内容を見てみましょう。

function greeter(person) {
    return "Hello, " + person;
}
var user = "Jane User";
document.body.innerHTML = greeter(user);

変換結果が変換前と同じですね。TypeScriptはJavaScriptのスーパーセットのため、JavaScriptの構文のみで記述したとき、このように変換前後で内容が同じ場合もあります。

続いて、静的型付けの性質を確かめるために、greeter.tsに型注釈を追加してみましょう。1行目に注目してください。

function greeter(person: string) {
    return "Hello, " + person;
}
var user = "Jane User";
document.body.innerHTML = greeter(user);

greeter()という関数の引数に: stringという記述を追加しました。こういったコロンで区切って記述するものを型注釈といいます。stringは型名で、これは文字列型を意味しています。

この内容をコンパイルしてみましょう。コマンドは先程と同じく、tsc ファイル名です。

$ tsc greeter.ts

変換されたgreeter.jsをみると、TypeScriptにしか含まれない型注釈の構文: stringだけが取り除かれ、JavaScriptとして正しい内容に変換されていることがわかります。この時点ではエラーは起こっていないため、コンパイラが止まることはありません。

それでは次に、意図的に型をまちがえて、コンパイルエラーが出力されることを確かめてみましょう。変数userの内容を、stringではない型の値に書き換えます。

function greeter(person: string) {
    return "Hello, " + person;
}
var user = [0, 1, 2];
document.body.innerHTML = greeter(user);

書き換えたらコンパイルします。すると、次のようなエラーが出力されました。

greeter.ts(5,35): error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'string'.

エラー文の冒頭greeter.ts(5,35):は、greeter.tsの5行目35文字目でエラーが起こっているという意味です。次にエラー番号error TS2345が出力されます。この番号は同様のエラーで困っている人を検索する際にも役立ちます。そしてエラーの本文が続きます。

今回は、string(文字列)であると定義している引数personnumber[](数の配列)が渡されたため、型が一致せずエラーとなりました。関数greeter()の想定していない値を渡しているため、これはバグにつながります。このように、うっかり関数に渡せない値を指定してしまっても、コンパイラがバグ発生の懸念を教えてくれます。

こういった型注釈とコンパイル時の型検証を活用して記述していくのが、TypeScriptを用いた開発フローとなります。

ここまでのまとめ

今回はTypeScriptの昨今の状況や、始めるための第一歩について紹介しました。次回はTypeScriptの中でもっとも重要な要素である「型とは何か」を中心に、TypeScriptの基礎的な文法について紹介します。

奥野 賢太郎
奥野 賢太郎
フロントエンド・エンジニア

音楽業界に飛び込み、音楽制作・ディレクター・DTM科講師などをつとめる。同時期にWebデザインのバイトをきっかけにAngularJSと出会う。その後、フロントエンド・エンジニアへの転身を決心し、自社サービスを運営する企業に入社。設計や実装に携わる。2017年1月に株式会社ピクセルグリッドへ入社。得意分野はAngularを用いたWebアプリケーションの構築。音楽知識を基にしたWeb Audio、Web MIDIの技術にも明るい。