こういう一連の記事を書きました.
susisu.hatenablog.com susisu.hatenablog.com susisu.hatenablog.com
TypeScript の型安全性
TypeScript の型システムは健全ではありません. TypeScript Design Goals にある通り, そもそも言語設計の段階で完璧な型安全性は目標になっておらず, 既存の JavaScript の言語仕様や資産を活用しやすいように, 生産性や利便性とのバランスをとることを目標としています.
では TypeScript の型システムではどの程度の安全性が保証されるのでしょうか?
型安全性を第一の目標に置いていないとはいえ, TypeScript がまったく見当違いな型検査をしているというわけではありません. したがって, ある制限された範囲内であれば, 安全性を担保するのに十分な効果を発揮します.
TypeScript で書かれたプログラムがどの程度安全になるのかは, このような安全性の確保された範囲をいかに見極めて逸脱しないかという部分に大きく依存することになるでしょう.
型システムの落とし穴
TypeScript によって安全性が保証される範囲を知っているというのは, 裏を返せばどういった箇所に危険な落とし穴があるのかを知っているということでもあります. 落とし穴をすべて避けて歩くことができれば, 自然と安全なプログラムが完成しているはずです.
一方で落とし穴を個別に把握していくというのは大変な作業です. というのも, TypeScript の落とし穴は他言語と比較しても数が多く, また JavaScript の構文やライブラリを再利用している都合上, 必ずしも危険なものが危険には見えないといったこともあるためです. 実際に中〜上級者レベルであっても把握していない落とし穴があることは珍しくなく, このことはしばしば TypeScript が難しい言語だと評価される原因にもなっているように思います.
落とし穴の多い機能のカテゴリ
ここで重要になってくるのが, 落とし穴は TypeScript の言語機能にまばらに存在しているのではなく, 基本的には特定のカテゴリに集中して存在しているということです. したがって, すべての落とし穴を個別に把握していなくても, 落とし穴の多い機能のカテゴリのことを知っていれば, それらを避けることでプログラムの安全性を高めることができるはずです.
落とし穴の多いカテゴリは, 目に見えて危険な any
や as
といった脱出ハッチを除けば, あまり認識されていないように個人的には感じています.
そこでこれまでの記事では, 私個人が比較的よく見かける (注意せず入っていく人をよく見る) 3 つのカテゴリを紹介してきました.
- オブジェクトの mutable な操作
- オブジェクトを mutable に操作するよりも immutable に操作することの方が多いため, immutable な場合の利便性を重視して mutable な場合の安全性は妥協している
- オブジェクトの具体的な形へのアクセス (静的な型情報に基づかないプロパティの参照)
- そもそも静的に安全性を保証するのは無理筋だが, 利便性を考慮してそれらしい型をつけている
- オブジェクトの index signature とオプショナルなプロパティ
- 利便性のために存在しているが, 他の機能との食い合わせが悪く安全ではない
もちろんこれらが全てではなく, マイナーな安全でない例などを挙げればキリがないのですが, プログラムの安全性を高めていく上で any
や as
を避ける次の段階として, これらのカテゴリに注意するというのは悪い選択ではないと思います.
というわけで
JavaScript が The Good Parts を選んで使わなければいけない言語であるのと同様に, TypeScript もまた The Good Parts を選んで使っていかなければその力を最大限活かすことができません. やっていきましょう.
おまけ (追記)
こちらもあわせてどうぞ.