TypeScript の型定義は「仕様」ではなく「実装」

TypeScript が他の静的型付き言語と決定的に違うのは、実体は JavaScript であり、TypeScript のコンパイラをどうやって黙らせたところで実行時の型は JavaScript の型にしかすぎない、TypeScript で書いた型は実行時にはなんら影響をもたらさない、という点である。

つまり TypeScript で「このオブジェクトはこういうパラメータを持っていてここに書いていないパラメータは持っていない」というような意図で interface なり type なりを定義したところで、実行時の JavaScript は「持っていてほしいパラメータを持っていない」ことも「持っていてほしくないパラメータを持っている」こともありえるし、そもそもまったく別の型、たとえば文字列や数値や真偽値型であることさえありえる。TypeScript コンパイラは静的解析を行ってあらかじめありえないものを検知してエラーを通知してくれるから、実行時にそのようなことが起きることを避けられているだけで、型定義それ自体が JavaScript の実行時の型を決定するものでは決してない。

しかし世の TypeScript の型定義を見ていると、ちょくちょく「外部インタフェース定義」を期待したものに出くわしたりする。たとえばあるクラスについて、内部変数が型定義に書いてないということがあるが、そのクラスを拡張したクラスを作るときにはその内部変数は本当は型情報として見えてほしいはずである。

TypeScript の型定義は実装を反映した型を書くべきで、こうあるべきという仕様を書くものではない。これを忘れないようにしたいし、TypeScript で型定義を書く世の人にも忘れないでいてほしい。

こちらからは以上です。