Effective TypeScript 読んだ / 郷に入っては郷に従う

Effective TypeScript (第2版) を読んだ

なんらか他の人に読んでおくと良いよと紹介できる本があると良いなと思って読みました. 2020 年以降に TypeScript を書く上での常識が概ね網羅されていると思うので, そういった前提知識に自信をつけたいならおすすめです.

www.oreilly.co.jp

ただ「項目18 推論可能な型でコードを乱雑にしない」で, 関数の戻り値の型アノテーションをデフォルトで省略するよう推奨していることについては明確に反対したい. より正確には, コールバックなど再利用を想定しない関数についてはデフォルトで省略してもよいが, 通常関数は再利用を目的として定義されがちなことを考えると, デフォルトで省略するというのはあまり実態に則していないと思う. 実際にこの本の後の章には戻り値の型アノテーションを書いておけばよかったのにという状況がしばしば出てきますし, 実体験としてもそうです.

またこの一冊を読んでおけばもう教えることは何もないかというと全然そんなことはないので, 更に上を目指すなら type-challenges を解いてみるとか, 型システムに入門してみるとか, 他の言語のイディオムの輸入を試みるなどして TypeScript の限界を探ってみたりすると良いと思います.

このブログにもより効果的に TypeScript を書く方法の記事がいくつかあるので, 暇な人は読んでください.

郷に入っては郷に従う

ところで TypeScript が広まるにつれて自分の意思に反して「書かされる」人が増えたからなのか, しばしば TypeScript への文句 (や怨嗟) を目にします. 例えば,

  • 型システムに健全性がないからダメ
  • 名前的型付けがないからダメ
  • ADT やパターンマッチがないからダメ
  • class のアクセス制御が貧弱だからダメ

などなど.

これは自分が他の言語に入門するときのために自戒を込めて書いておきますが, こういった態度はコードベースに対してゲストとして関わるならともかく, そうでないなら全く歓迎されません. 自分の考えた理想のコードが TypeScript で書けないからといって文句を言っていても何も解決しません. TypeScript というシステムの中で理想的なコードが何かを考えた方が生産的です.

もちろん TypeScript が完璧な言語というわけではありません (たぶん欠点の方が見つけやすい) し, 上に挙げたような機能があると便利なことは言われるまでもなく理解しています*1. 一方で私がなぜ TypeScript を使い続けられているかというと, 大抵の場合は代替手段があってなんとかなっているからです.

  • 健全性の罠は, どういった種類の罠があるかさえ知っておけばかなりシステマチックに回避できます.
  • 名前的型付けについてはブランド (branded types)というテクニックがあって, 完璧ではなくともいくつかの場面では有用です.
  • ADT やパターンマッチについては, 代替手段として判別可能ユニオン (discriminated unions) と制御フロー解析による型の絞り込みがあります. 他の言語の ADT やパターンマッチと比較すると脱糖後のような記述なので多少冗長ではありますが, 概念としては同じものを表現できます.
  • class のアクセス制御については, 私はそもそも class をほとんど使わないのでそこまで気にしていないです. メソッドの記述やプログラムのモジュール化については関数型言語的なテクニックでなんとかしています.

郷に入っては郷に従って, その言語でのベストプラクティスを学んで取り入れた方が良いです. TypeScript でのベストプラクティスは JavaScript とも他の言語とも違います. 自分の知っている他の言語の知識だけで戦おうとするのは Java で static メソッドばかり書くのと同じくらい効果的でないです.

ってマックで私が言ってた.

*1:ところで相手が理解していないと勝手に決めつけて突っかかっている人を時折見かけますが, 普通にコミュニケーションの方法として最悪なのでやめようね