TypeScript の型定義に凝りすぎじゃね?

ここ数年で、Qiita や Zenn で TypeScript の話を見かける機会が多くなった。JavaScript には Java のような型定義がなく、初心者の混乱の元・ひいては障害の元になりうるのはよく分かる。

しかし、最近どうにもこうにも、TypeScript でむりくり型定義するような Tips を多く見かけて、疑問に思っている。たかが TypeScript に頑張り過ぎじゃね?と。

まず、TypeScript による型定義は単なる Linter でしかない。コードが実行される時は基本的に JavaScript に変換され、TypeScript の構文で記した型定義は消失する。コーディング中に静的解析し、警告を出してくれるモノでしかないのだ。

JS・TS を書くということは、得てしてどこぞの API と通信し、その結果を利用して処理することが多いだろう。レスポンスデータに型定義する方法もあるはあるが、大変だ。同じチームが作っているバックエンドサーバなら、中身をよく知っていて型定義を流用できるから簡単に実装できるかもしれないが、他システムの場合はなかなかそうもいかない。

勿論、頑張って型定義をこしらえることに意味がないワケではない。コーディング中に、Typo や勘違いに気が付けるようになるし、強制力が増す。それは良いことだ。

しかし、自分が気になっているのは、その効果に対して、かかるコストが見合っていないんじゃないかという点だ。

こういう API がある、こういうレスポンスが来る、じゃあコレを TypeScript が持つ構文でどうやって表現しようか、あぁ新しい TS じゃないとこういう型定義は難しいな、Interface を用意してー、クラスを用意してー、入れ子になっているからー…。

なんというか、そもそもそういう複雑な型の考慮が必要になっているシステム設計が悪いんじゃないか?それ。

一つのプロジェクトを小さく作っておき、外部通信が最小限で済めば、レスポンスを型定義したい場合も、簡単なクラスを何個か定義するだけで良い。使うプロパティのことだけ考えれば良いだろう。

オブジェクトや配列をこねこねする関数に関しても、一つの関数を小さく作れば、引数と戻り値はほとんどがプリミティブ型で扱えるレベルに落とし込めるはずだ。引数の表現に複雑な型定義が必要な関数は、その関数の設計自体が何らか誤っている。もっと小さく分割してやろう。

プロパティの存在チェックは TypeScript の型情報だけで済む話ではなく、事前条件・事後条件として検査し、異常時はエラーハンドリングすべき事項だろう。API コールが絡むと、型が保証される場面は少ないと考えている。あまり他システムというモノを信じていないのだろう。

JS 初心者がつまづくのは

くらいだろう。これら3つは簡単に覚えられる。これらの避け方を知っていれば、意図しない型変換による障害など防げるのだから、JS を普通に書ける自分個人は、ほとんど TS がなくても困らないと思っている。

自分はコレだけ意識しておいて、一つひとつのプロジェクトを小さく作るようにしている。仕事ではチーム開発ないしは引き継ぎが発生するので TypeScript を使うが、外部連携の部分では as any で逃げることも多々ある。ココを厳密に型定義できれば安全性が上がることは上がるのだが、外部システムを見ずにフロントだけ改修してバグを生むことにもなるので、そういう場面では any で逃げつつ、その外部システムのドキュメントへのリンクなどを、ドキュメンテーションコメントで細かく書いて残している。「any を使っている箇所は危なっかしい」というのは共通認識だろうから、それを利用して、「外部システムのことを考えて直してね」という気付きを与えるために使用している。

個人では TypeScript はほとんど使っていない。毎度 package.jsontypescript が登場したり、tsconfig.json.eslintrc.json での調整が必要だったりするのが、クソ面倒臭いのだ。上述のようにハマりやすいポイントは JS オンリーで簡単に避けられるので、サッサと直接 node コマンドで実行できる、ないしはブラウザで直接実行できるように、素の JS で書いてしまう。TypeScript は IDE (というか VSCode) での補助機能を当てにした連携も多く、既存の巨大なコードを直す場合はそうした恩恵に預かれるのは良いが、そもそもそんな巨大なコードを書くなということである。

JS のハマりポイントの代表例だけ知っておき、システムを小さく作っておけば、TypeScript なんて大仰に使う必要ないのだ。力を入れるべき場所がズレているように思う。


2021-02-10 追記 : 反応に対する反応書いた。