Rのつく財団入り口

ITエンジニア関連の様々な話題を書いているはずのブログです。

【感想】『プロを目指す人のためのTypeScript入門 安全なコードの書き方から高度な型の使い方まで』:ブルーベリー本でTSを深堀りしよう

Ruby界隈にチェリー本あらばTS界隈にはブルーベリー本誕生!

 2022/4/22に発売された新刊です。物理本はなんと965ページのボリューム、TypeScriptを基本からみっちり解説した本となっています。

 インパクトのある表紙も時々ある技術書関連では、Ruby界隈ではご高名な伊藤 淳一さん【give IT a try】の『プロを目指す人のためのRuby入門』が「チェリー本」という愛称がついているのは割と有名な話。
瑞々しいブルーベリーがどどんと載っている本書『プロを目指す人のためのTypeScript入門』は、習って「ブルーベリー本」もしくは「ベリー本」という愛称がついたそうです。TypeScriptが学べてさらに目もよくなりそうでおトクです。
 著者はLINEでフロントエンドエンジニアとしてご活躍中のuhyoこと鈴木僚太さん。「OSS活動にも積極的だが自作のライブラリはあまり流行っていない。」というプロフィールの締めがじわりときます。

 自分はTypeScriptは本を読んだりUdemyの講座と一緒に実際に書いてみたりで基本はわかっている(はずw)レベルです。業務で大規模なバックエンドをTypeScriptで作りこむような機会はなさそうですが、ReactかVue+TypeScriptは新規プロジェクトの機会には導入したいと思っています。
 これを機にがっちりした本で深堀りしようと思って拝読しました。

プロを目指すためのTypeScript入門 / ブルーベリー本でTS入門!

アイキャッチ画像右側のフォントは、TS公式ロゴに使われているっぽいSegoe UIに似たNoto Sansです

第1章 イントロダクション

TypeScriptとはなんぞやというところをしっかりやっていく章。

  • Cのコンパイラの格言を引き出したりしながら、静的型付けのメリットを説明していきます。
  • TypeScript年表があるのがありがたいですね。別の所のコラムにも出てきますが、初期はJavaScriptとは独自の構文や機能を持って別の言語を目指していたが(今も別言語ですが)、その後は完全にJavaScriptの拡張の方向に向いているという話は面白い。
  • enumModuleなど独自の構文には触れず、今は気にしてなくて良いとバッサリ切り捨てています。以前にJavaScriptの本を読んだときによくわからなかったSymbol形も、本書では出てこなかったりします。
  • 後半ではNode.jsを入れて開発環境構築をしていく段取りもしっかりあります。コマンドはnpxを使っています。
  • TypeScriptの言語仕様に出てくるワードは、全体を通してできる限りすべて英語表記をカッコで添えています。こういうところはとてもありがたいです。

第2章 基本的な文法・基本的な型

  • プログラムは「文」からなり、 const 変数名= 式 のようにその中に「式」があり、結果があるのが式でないのが文。
  • 式の後にセミコロンを書く文が「式文」。このあたりもしっかり定義しています。式文ってまったく知らんかった!
  • コラムでできる限りconstを使ってletを避けようという話があり、だいたい9割はconstで済むという話があります。イミュータブルな変数をメインに使う言語もありますし、プロフェッショナルとして使うならconstなんだなあと。
  • プリミティブ型の説明に整数と小数を分けられる任意精度整数のBigInt形も説明あり。コード中で型を書く場合は全部小文字で bignum: bigint なんですね。
  • JS特有の話としてはデータがないことを表現するnullundefined、TSの言語仕様上はサポートが手厚いことを理由にundefinedを推奨しています。なんとなく他言語から来るとnullを優先してしまいそうなので注意が必要ですね。
  • 等価演算子===推奨で、==はもう使うなとはっきり明言。使ってもいいのは == null の場合のみで、「nullかundefinedである」を判定できるから。TSだと型があるからほぼ===になるんですね。
  • 最新の本なのでES2020で追加された二項演算子 ?? も解説に入っています。デフォルト値に使う時に使うもの。
  • コラムでES2021で追加された論理代入演算子 &&= ||= ??= もあり。一見タイプミスに見えそうな構文ですが、JSはどんどん進化しますね...
  • 制御構文の話ではforループのところでfor-of文も言及されていますが、for-inは利用機会が低いのでほぼ要らないとあります。
  • 各章にある力試しは約束のFizzBuzzでした。

第3章 オブジェクトの基本とオブジェクトの型

オブジェクト=連想配列である というところから始まり、オブジェクトを論じていく章。

  • TSでもあまりクラスは使われずただのオブジェクトで済むケースが多いとあり、なるほどと思います。
  • 明示的にコピーでなく変数同士で代入していくとオブジェクト同士氏は参照になり、同じであることになることもきっちり解説してあります。
  • 型名を新規作成するときはtype文とinterface宣言がありややこしいですが、本書ではほとんどの場合でtype文で済むとあります。確かにネット上の古い情報だとinterfaceの時もあるので注意ですね。
  • type T = typeof num; のように型のtypeoftypeof演算子は全く別であることも解説されています。忘れていました...型のほうのtypeofは乱用すべきでないこともしっかりコラムで解説してあります。
  • 型引数の話でScala言語とHaskell言語の「高カインド型がない」という凄そうなパワーワードが出てきてまったく分かりませんでした(笑) 言語仕様の世界も奥が深い...
  • 素数が固定された配列型のタプル型については、本書のカバー範囲ではオブジェクト型推奨、もっと高度なことをするときに出てくるよと範囲が明快。
  • コラムで配列へのarr[10]のように位置にアクセスするときの危険性で、インデックスアクセスは極力使わないという回避方法が解説。このへん言語によって対処法は様々ですが、なるほどこういう時にfor-of文なのだなあと。
  • 最後の力試しはuhyoさんやジョンスミス氏のデータ処理をするものでした。自分的には最初の解答例のコードの方ががわかりやすく、filter関数などを駆使した別解は分かりにくく感じてしまいました。確かに別解はすっきりするけどどっちらがいいのでしょう...

第4章 TypeScriptの関数

従来の関数宣言でやるところから、関数の話をきっちりと論じています。

  • アロー関数で書くのが「アロー関数式」で、それとは別に関数式がある。オブジェクトの宣言の中で関数を描く「メソッド記法」もある。JSは奥が深い...
  • 部分型についてもかなりみっちりと解説しています。
  • <T>ジェネリクスについても型引数がどう推論されるのかコラムで深く追及。
  • 力試しは3章のFizzBuzzの続きでコールバック関数を練習するもの。確かにすっきりした簡潔なコードにするにはジェネリクスがいるなと分かる問題になっています。
  • どうでもいいのですが、サンプルによく出てくるuhyoさんオブジェクトのheightプロパティを見ると180cmを超えていて背高い!と思ってしまいました。(笑)

第5章 TypeScriptのクラス

 クラスは必須ではないが、ミュータブルな使い方をするオブジェクトやメソッドを持つオブジェクトをたくさん作っていくときにはよく使われる...ということで、クラスを深堀りしていきます。

  • いきなりコラムでクラスも変数である事が判明。なるほど!
  • staticで宣言するクラス内の静的プロパティはあまり使うシーンはないとのこと。
  • const User = class { }; で書く「クラス式」というやり方は初めて知りました。
  • もうひとつ、プロパティをprivateで宣言する以外に#で書くやり方もあるんですね。こちらはES2015の機能なのでより厳格、どちらかいうとこの#を推奨とのこと。こうした背景も書いてあるのはありがたいです。あとの方で継承を使うときに実はこの2つに差があるという話も出てきます。
  • 静的初期化ブロックというのも知らなかった...これは使い所はどうなのでしょう。
  • コラムで変数名と型名は名前空間が実は違うという話もあり、この辺も奥が深いです。
  • クラスの継承についてもがっつり語りつつ、比較的複雑な機能なので注意して使うようにとあります。
  • 出た~JS/TSの複雑怪奇といわれる鬼門this! という感じですが本書は例を元にしっかり解説。結局はアロー関数が優位であり、applycall関数にも軽く触れて終了となっています。
  • 例外の話も例を上げてしっかり解説してあるのですが、thrownullなど何でも投げられるというのは知りませんでした。
  • 最期の力試しが面白くて、まずはUserの処理をUserクラスを用いた書き方に置き換え、次に関数のみを使ったやり方で書き直しています。この流れで関数の中にデータが内包されているものを「クロージャ」と呼ぶ...と解説があると理解しやすいです。
  • 確かにクラスに2つ以上のメソッドがある場合はクラス形式が便利ですが、メソッドがひとつだけだったらこちらの関数を使うやり方でもカプセル化できるのですね。TypeScriptといえど近年ではクラス使用は必須ではないのだなと思いました。

第6章 高度な型

 ここまで学んできた型システムは序の口である...!とハードルを上げつつ、TypeScriptの特徴である型の話を深堀していく章。どんどん難しくなってきます。

  • 論理和論理積のごときユニオン型、インターセクション型も、なぜそうなるのかみっちり解説しながらこの章で深く扱っています。
  • obj?.foo のようなオプショナルチェインもここで登場。
  • 文字列型でかつ"foo"という文字のみを許すような方が「リテラル型」。定数で持てばいいんじゃない?とつい思ってしまうのですが、ユニオン型と併用すると本書の例のように関数の引数が"plus"か"minus"の文字列のみを許したい時に補完がシュッと出てくれるわけですね。なるほど...
  • 型の絞り込みは文字列を === で比較するやり方、typeof演算子を使うやり方。ここでnull"object"と判定されるという挙動は確かに不自然に見えます。
  • tagというプロパティをそれぞれの型にもって絞り込んでいくやり方は初見でした。うーん高度だ。
  • 他の型の中のプロパティをHuman["age"]のように辿ってその型を使う「lookup型」。
  • ある型のプロパティ一覧を持ってきてそれを使える「keyof型」。これの使い方が難しい...!
  • 優秀にみえるTypeScriptの型推論も完璧ではないということでasも紹介されていますが、使いどころは限定的となっています。対してas const は使用を推奨。
  • any型はTSの中で最強の危険性を誇る最終兵器ということで、本書でも大いに警戒を発しています。存在理由もちゃんと論じているのがありがたい。
  • 対してunknown型は何が来るか分からない時には使用を推奨ということで、意外な気がしました。
  • 最後はさらに高度な型ということで、object型やnever型、ややこしい機能のmapped typeなども解説してあります。このあたりはやっぱり難しく感じますね~!

第7章 TypeScriptのモジュールシステム

JavaScript関連を語るとよく出てくるところではありますが、改めて本書で最近の状況を踏まえて解説してあります。

  • エクスポートの話でモジュールにincrement関数を定義、そのモジュール内で使うローカル変数も一緒にエクスポートする話が載っています。letで宣言した変数は外側から弄れてしまいそうに見えるんですが、TSだとコンパイルエラーで守られるんですね。こういうカプセル化の手法もあるんですね。
  • export default [関数や変数]; して import [好きな変数] from "./hogeAge.js" のようにするdefaultエクスポートとやインポート。モジュールの代表的な値をエクスポートするために用意されていて使用必須ではない、あまり使わない場合も多い...とあり納得しました。
  • 「インポート・スター」と読むらしい import * するやり方もあるんですね。
  • ファイルは「スクリプト」「モジュール」の2種類があり、今のTSでは自動で切り替わるのであまり意識する必要がなくなっているとのこと。
  • またNode.jsのモジュールシステム、npmの使い方も基本的な所が解説されています。昔あったCommonJSの話もあってありがたい。
  • 力試しはパスを指定してのファイル読み込みについての問題でした。

第8章 非同期処理

 基本的には非同期処理とは裏で行われる時間がかかる処理である...と定義して、本書最後の難関と記された非同期処理を論じていく章。

  • JS/TSがシングルスレッドモデルである話も最初にしてあります。
  • 最初は簡単なタイマー処理から始まってPromiseも出てきて、ログを出しながらどういう順番で実行されるのか、その中身をしっかり解説。
  • Promiseの話がけっこう長いのですが、その上で実際によく使うのはasync/awaitということで後半はこちらに。
  • コラムにあるのですが最近はtop-level awaitという機能もあるのですね。
  • 力試しは前章のファイル読み込み処理をPromise版にし、さらにタイムアウトの機能を追加するものとなっていました。
  • JavaScript Primer』あたりを読んだ時も思ったのですがやはり非同期処理周りは特に難しく感じました...。復習が必要ですね~。TypeScriptペースの本でかつ非同期処理をがっつり解説しているのは貴重な気がします。

iwasiman.hatenablog.com

第9章 TypeScriptのコンパイラオプション

 最後はTSの進化と共に微妙に変化がある設定ファイルtsconfig.jsonを深堀りした章となっています。

  • /src/**/*.ts*やは「globパターン」と呼ぶ名前があるんですね。
  • もっとも重要なオプションのstrict: true は強く推奨。
  • TypeScriptは2.0になるまではnull安全ではなかったんですね。strictNullChecksもtrueにしない理由がないと強く推奨。
  • そしてAny型はすべて弾いてnoImplicitAnyもtrueを強く推奨。
  • 新規プロジェクトでなく既存のJavaScriptプロジェクトからの移行時を想定した記述もあるのがありがたいです。
  • 新しいオプションとしては配列へのインデックスアクセスの挙動を強化するnoUnchecedIndexedAccessもtrueを推奨。
  • 新規プロジェクトではなるべく厳しい設定推奨とのことで、まあ正しくTypeScriptのパワーを正しく活用するにはこうなのだろうなあと。
  • 付録には演算子一覧と、さらなる学習用のキーワード集も載っています。

 なお巻末の著者プロフィールによると、TypeScriptを極めるにはインコの使い魔を従えるのが必須のようです。(うそ)

プロを目指すためのTypeScript入門 / ブルーベリー本でTS入門!

まとめ:ブルーベリーの奥に広がるTypeScriptの奥深さを学べる本

 まだTypeScriptが初めての人にも読める、プロを目指す人のための入門書...という位置づけでしたが内容はかなり深く、途中からどんどん難しくなり、みっちりと学ぶことができます。言語仕様としての用語はすべて英語のカッコ書き付き、脚注も豊富で、目の前の事象がなぜそうなるのか、なぜこうなっているかの背景もかなりきっちり解説してあります。TypeScriptという言語自体に造詣がかなり深い方なのだなあと思います。他の言語の話も時々出てきます。合計38個あるコラムもかなり深く、今まで知らなかったお役立ち情報を知ることができました。
 意外に思ったのですがJS/TSの様々なワードに関する歴史的経緯周りの話も逐一語られているのかと思いきや、「現在は気にしなくて大丈夫です」のような感じでけっこうスパッと切り捨てているんですね。変化の速い領域ではアンラーンも必要なのだなと思いました。
 けっこう分厚い本なのでJavaScriptに入門したばかりのような初学者には後半がハードルが高めですが、しっかり入門できるかと思います。

 なお本の特徴なので仕方ないですが表類は少なめ、長い文章でみっちり論じてあるスタイルなので、長い本を読むのが苦手な人にはやや抵抗があるかもしれません。個人的にはもうちょっと文章に改行が多いほうが読みやすいかな...とも思ったのですが、このボリュームでそうするとさらにページ数が増えてしまいそうですね。
またKindle版は機能で呼び出せるリンクが章だけでその下の節がないのがちょっと大変でした。(先頭の目次からは節にも飛べました。)
 またこれも本書の冒頭に書いてありますが、Node.jsの使い方やtsconfig.jsonの解説は登場しますが、TypeScriptの言語機能をフル活用したバックエンドのアプリ作成例の長いコードとか、ReactやVue.jsにTypeScriptを適用とかの話はありません。そのあたりは本書の知識をもって別の情報リソースをということでしょう。この調子で応用的な続編の本も出していただけたら凄いなあと思ったり。

 時々サンプルコードに出てくるuhyoさんなオブジェクトのage: 26(number型)が気になって、お若いのに凄いな...!と見るたびに思ってしまいました。フロントエンド界隈は年齢層が若めというのもありますが、いやはや、ソフトウェアエンジニアリングにはもう年齢は関係ないですね。

著者のuhyoさんのブログによる記事。

blog.uhy.ooo

技術評論社のページ。 gihyo.jp

uhyoさんへのインタビュー記事もあります。

engineering.linecorp.com