TypeScriptを掌握する極限の知見:Arity(引数の数)を型レベルで強制するコンパイラ駆動設計
チーフシステムアーキテクトの視点から言えば、現代のTypeScript開発において最も見落とされている脆弱性、あるいは設計上の負債は「関数の過剰な引数受容(Arity mismatch)」にある。
例えば、`Array.prototype.map(callback)` に無防備に任意の関数を渡したとき、ランタイムは何を考えているか。JavaScriptのエンジン(V8など)は、呼び出されたコールバックに対し、インデックスや配列本体といった余計な引数を暗黙的に流し込む。`.map(parseInt)` が奇妙な挙動を示すのは周知の通りだ。
今回は、このランタイムの「お節介」をコンパイルタイムの型システムで完全にハックし、高階関数に渡すコールバックの引数の数(Arity)を厳密に制限・強制するテクニックを解説する。これは単なる型パズルではない。巨大なコードベースにおける意図しない副作用の伝播を防ぎ、V8のインラインキャッシュ(IC)を汚染させないための防壁構築なのだ。
—
1. 型システムにおける「引数リスト」の解体と評価
TypeScriptの関数型は、単なるシグネチャではない。コンパイラ内部(`checker.ts`)において、関数型は `FunctionType` という構造を持ち、そのパラメータリストは `Parameters
私たちが目指すべきは、渡された関数 `F` のパラメータタプルの長さを `extends` キーワードを用いて静的に評価し、許容される上限(あるいは正確な数)を超えている場合に `never` やコンパイルエラーを誘発することだ。
しかし、単純に `Parameters
—
2. 実装:厳密なArity制限を持つ高階関数の型定義
以下のコードを見てほしい。ここでは、引数を最大2つまでしか受け取らない関数のみを安全に受け入れる高階関数 `secureMap` の実装と、その型定義の全貌である。
type