天の月

ソフトウェア開発をしていく上での悩み, 考えたこと, 学びを書いてきます(たまに関係ない雑記も)

プロを目指す人のためのTypeScript入門 - Forkwell Library #35に参加してきた

forkwell.connpass.com

こちらのイベントに参加してきたので、会の様子と感想を書いていこうと思います。

会の概要

以下、イベントページから引用です。

今回の第35回目では、昨年4月に発売された『プロを目指す人のためのTypeScript入門 安全なコードの書き方から高度な型の使い方まで』著者のうひょ氏をお招きし、お話を伺います。

根幹となるJavaScriptの仕様・機能とともに、TypeScript独自の仕様・機能を解説している本書について、うひょ氏に書籍の内容を振り返りつつ、TypeScriptの面白いところをピックアップしてご紹介いただきます。

事例講演では、FastLabel株式会社 VPoEの植野 晃司氏に、FastLabel社の事例についてご発表いただきます。

会の様子

基調講演「TypeScriptってどんな言語? 言語そのものを知る面白さ」

本のコンセプト

応用に踏み込まずTypeScriptそのものを教科書的に学ぶようにしているそうですが、現場でプロフェッショナルとして振る舞えるような本にはなっているそうです。

また、JavaScriptの経験がなくてもTypeScriptが学べるようなスタイルも特徴的だということでした。

他にも、初心者向けに誤魔化したような説明は書かず、厳密な用語の使い方, 厳密な定義を記載するように心がけたそうです。

2章のおさらい

基本的な構文の学習に加え、文と式の違いや式文に関して正確な説明をしているということでした。(なんとなく動くことよりも体系だった説明を意識)

3章のおさらい

オブジェクトの概念やオブジェクトに関連した構文を学び、===の判定や部分型関係など込み入った話も曖昧な表現なく正確に説明するようにしたということでした。

4章のおさらい

関数に関して学ぶとともに、ブロックスコープの概念も説明しているそうです。
ジェネリック関数の型引数が省略された場合にどのようなメカニズムで推論されるのか?という部分を詳しく説明して深い理解を促しているということでした。

5章のおさらい

クラスやエラー処理に関して解説しているそうです。thisの解説もここに突っ込んだということでした。

6章のおさらい

TypeScriptの醍醐味である高度な型に関して解説しているそうで、一番分量を割いたということでした。タグ付きユニオンや型の絞り込みに関してもこの章で解説しているということです。

7章のおさらい

モジュールシステムに関して解説しているということでした。

8章のおさらい

非同期処理をPromiseなど含め裏側の仕組みから丁寧に解説しているということでした。

TypeScriptの面白いところ

ユニオン型と型の絞り込みが一番面白いところだと考えているそうで、6章で丁寧に解説しているということでした。

タグ付きユニオンが使えるようになることを本書でも目標としているそうで、論理和論理積で表現しないようにアンチパターンとともに説明しているということでした。(静的解析を受けるためにも、正確に可能性を表現することが重要)

基礎固めをなぜするのか?

読者次第で幅広い応用ができて技術進化に立ち向かえることや、読者が自ら考える助けをすることを補助するために、基礎固めをしているそうです。

何より、仕組みから実装を理解することで楽しめることも基礎固めをするメリットだと考えているということでした。

発売当初からのTypeScriptの進化

Node.jsのCJS/ESM両対応機能にTypeScriptも対応したことや、.cts/.mtsの導入、空オブジェクトやunknownの相互運用性向上、satisfies構文の追加、デコレータのサポートによるクラスの表現力向上、using宣言のサポートなどが本書からバージョンアップしているということです。

事例講演「スタートアップにおけるTypeScript運用の変遷」

TypeScriptを使ってよかったこと

TypeScriptで言語を統一することで、言語のキャッチアップコストを抑えられていることと、ライブラリが提供している型に従うことができている(CDKの型定義に従うとソース的に正しいものがすぐ書ける)ことがよかったそうです。

anyとasは使わない

TypeScriptで言語を統一した上にスピード優先の開発をしていた結果、anyが乱立する事象が発生したそうです。(自分たちが定義した以外の型を一旦anyとした)

結果、型定義の恩恵を受けることができなくなり、最終的にはすべてのanyを消すためにコストをかける羽目になったということでした。

同様のことがasに関しても起きたそうで、この2つは運用ルールなりでカバーする重要性を実践の中で実感したということです。

tsconfig/basesを使おう

元々はCompilerOptions等を自前で設定していたそうですが、必要な部分だけ現場に合わせて変えないといけない部分だけ変更しておくと、初学者がTypeScriptを変な形で使うことがなくなるし、ベストプラクティスに従えている確信が得られるため、是非使ってみてほしいという事でした。

Q&A

講演の後はQ&Aがありました。以下、質問と回答を常体かつ一問一答形式で記載していきます。

jest.fn()などはそのままでは引数も戻り値もanyになってしまう。テストコードのみはanyを使うというのは例えばありなのか?
  • テストコードではありかなと思う。ただ、一旦本番をanyで書いてしまうとテストを回すまではコンパイルエラーに気が付けないとかの可能性もあるので、
  • めちゃくちゃ無理はしなくてもいいが可能ならanyを使ったほうがいいとは思う。なお、jest.fn()はanyを使わずとも意外と楽に書けるので、そこはanyを使わないチャレンジをしてみてもよいと思う
TypeScriptで書いたコードをテストするときのベストプラクティスを知りたい
  • TypeScript特有のテストはないと思うが、なるべく型に寄せて、コンパイラがチェックできることはなるべくテストでチェックしないようにするのは重要だと思う
  • カバレッジ100%は現実的ではないので、自分たちが書いたソースコードが意図した通りに動いているかをテストするのがいいと思う
エラー処理についてRustのResult型のようなものを定義して使うか?

人によって言うことがぜんぜん違うのではと思う。uhyoさんとしては、両方使うことが多い。RustでResultで書けるならResultで書けるし、Rustで言うpanicに相当するものはThrowで書く。

アップデートで追加された機能はすぐ使うのか?周りのメンバーのキャッチアップを待つか?

基本的にはどんどん使っていくスタイル。人のスキルレベルに依存しないものは特に積極的に使う。

TypeScriptのデメリットや選択しないケースは?

正直思いつかない。

anyではなくunknownならどうしていいのか?
  • unknownなら不要に使いづらいのでまだマシと言うだけで、unknownを使っていいというわけではない
  • これなんだっけ?というのが本当に分からない場面もあるので、その際にはunknownを使ってもいい
エラーハンドリングに関してもっと詳しく知りたい
  • TypeScriptは言語仕様上何が投げられるのかわからないので、エラーをキャッチするときはunknownにすると良いと思っている。
  • instanceofのエラーならこう処理する、みたいなのを決めておくとかは現場でやる
DenoやBunといった環境も出ているが、Node.jsがやはり多いか?
  • 今はメジャーなのでNode.jsを使っているという感じ
  • 現状はNode.jsだと思うし、将来的にもNode.jsがデファクトスタンダード的な立ち位置を守り続けるような気がする(Node.jsも健全な進化をしているので)

会全体を通した感想

初心者向けの本というと、とりあえず動くアプリケーションを作ると言った構成のものが多い中で、プロフェッショナルになるために教科書的な基礎を盛り込んだという部分には特に共感できました。