Javaを4年間実務で取り扱った私が、「プロを目指すためのTypeScript入門」(著:uhyo氏)
でTypeScriptを学んだ際に感じたことを書いていきます。
Javaと比較して、どう違うのかに着目して書いています。
JavaとTypeScriptは同じ静的型付け言語ということで、共通する部分は多くありますが、細かな違いがありました。
同じようにJava技術者がTypeScriptを学ぶ際の助けになればと思います。
この記事の読み方
各節ごとに上段は本の内容
線を挟んで下段は私の所感になります。
TypeScriptとは
Microsoftによって開発されているプログラミング言語。
もともとはブラウザ上で動作しWebページに動きを与えるための言語だったJavaScript(以下JS)だったが、現在ではサーバサイドなど幅広い用途に応用されている。
だが、JSは静的型付け言語ではなかった故、大規模なシステム開発には苦労が伴っていた。
それを克服するためにTypeScript(以下TS)が開発されている。
Javaなどが担っていたサーバサイドの用途にも、JSが台頭しているということだった。
今までもフロントはJS、バックはJavaといった構成が多かったが、
フロントとバックのどちらも同じ言語で開発可能になると、様々なメリットが受けられそうだ。
そもそも静的型付けとは
静的型付けとは、変数や式が型を持つ、静的型システムを備えていることを指す。
コンパイル時に型が決まり、プログラムを実行しなくても型にまつわる問題が発見できる。
Javaの言語仕様と同じなので、理解しやすくて助かる。
TSの型の表現力
数ある静的型付け言語の中でも、TSの型システムはほかに類を見ない高い表現力を持っている
表現力とは、型でいろいろなロジックをあらわすことができるということを指している。
オブジェクト型・関数型をはじめ、リテラル型・ユニオン型・keyof型などの高度な型があり、TS独特の設計パターンはこれらの型の存在によるところが大きく、高い表現力の源になっている。
同じ静的型付けであるJavaと比較しても表現力が高いと読めるので、今後紹介される表現方法にわくわくしながら読み進めていきたいと思う。
静的型付けのメリット(1)型安全性
型安全性とは、間違ったプログラムをコンパイラの型チェックが検出してくれることを指す。
型に矛盾が発生した時にコンパイルエラーになる。
例えば以下のような場合。
// 受け取った数値のぶん"hello"を結合した文字列を返す関数
function repeatHello(count: number): string {
return "hello".repeat(count);
}
// 数値ではなく、文字列を渡している
console.log(repeatHello("wow"))
// -> 型エラーが発生
// 数値を渡せばOK!
console.log(repeatHello(3))
// -> hellohellohello
コンパイルエラーが発生するので、実際にプログラムを実行しなくてもコーディングの間違いに気づくことができる。
コンパイルエラーはコーディングの強い味方。ミスは当たり前に発生するものなので、それをすぐ発見・修正できるので成果物のクオリティが高まる。
動的型付けの場合、引数に何を渡しても実行するまでエラーに気づけないの怖すぎないか、、
Java技術者としては、今まであまり意識せずに恩恵を受けていた部分なので、JSメインの人がTSに移行する時には感動するんじゃないかと思った。
IDEだと、ここの引数間違ってますよ。という警告がコーディング中に出てくるので、かなりスマートに間違いを正せるのも良い点。
静的型付けのメリット(2)ドキュメント化と入力補完
ソースコード中に型の情報が書かれるので、プログラムを読解する助けになる。
関数名や型情報、コメントなどを組み合わせることで、関数の中身まで詳細に読み込むことなく関数を理解できるようになる。
大人数でのチーム開発の場合、他人のプログラムを読む機会はかなり多く、型の補助による効果は絶大。
また、IDEによる入力補完にも大きな影響を与え、型情報からプログラマが何を入力しようとしているかを判断して補助してくれる。
使いこなすことで、コーディング時間の大幅な短縮につながる。
これまでの経験上、不具合修正でデータの流れを追って調査するときは
変数名より中身の実際の値と型に着目する(バグっている時点で、変数名は信用できないことがある)ので、型がないとかなり不便そうだと感じた。
普段当たり前に使っていた、型やJavadocに感謝…
TSとJSとの関係
TSのコンパイラの機能解説を通じて、TSとJSの関係を理解する。
コンパイラの役割は大きく2つで、型チェックとトランスパイルになる。
型チェック
先に解説した型安全性を実現するための機能。
実際にコンパイルエラーを発生させるのはこの機能。
また、TSはランタイムの挙動が型情報に依存しないという特徴がある。
プログラム実行する際には静的な型情報は失われており、ピュアなJSと変わりない。
あくまでTSはJSの開発支援の後付けのツールであることに徹している。
そのため、関数オーバロード機能はTSにはない。
// こういうオーバーロードはできない!
function double(value: number){
console.log(value * 2);
}
function double(value: string){
console.log(value.repeat(2));
}
もし、オーバーロードが使いたい場合は以下のようにすることで同じようなことができる
// 文字列、または数値型を受け取ることができる(ユニオン型という記述方法)
function double(value: string | number){
if(typeof value === "number"){
// 数値型の場合
console.log(value * 2);
}else{
//それ以外(文字列型)の場合
console.log(value.repeat(2));
}
}
同じ静的型付けでもJavaとは全然異なる特徴だった。
TSはその成り立ちから、TSはJSから離れた独自の機能を実装しないようになっているので、そこから違いが生まれているよう。
オーバーロードが使えないとしても、ユニオン型という高い表現力を持つ型を使って乗り越えられるようになっているのは流石だなと思った。
あとがき
これ以降もトランスパイルの仕組みだったり、開発環境の構築方法なども紹介されていますが
Javaと比較して、という文脈で語れるものは少ないので割愛します。
また、第2章編も投稿しますのでそちらもぜひご一読お願いします。
参考文献