この投稿では、TypeScriptのビルトイン型定義のArray.isArray
を読み取り専用配列(readonly array)に対応する方法を紹介します。
Array.isArray
の問題点
TypeScriptのArray.isArray
メソッドの型宣言は次のようになっています。
interface ArrayConstructor {
/* 中略 */
isArray(arg: any): arg is any[];
/* 中略 */
}
// from: https://github.com/microsoft/TypeScript/blob/9a75d2acc8f7175d1ada327a0e457f7ea1ea1c46/src/lib/es5.d.ts#L1440
このメソッドは型ガード関数で、戻り値はtype predicateになっています。これにより、if文などでArray.isAarray
を使った場合、変数が配列型に絞り込みがなされます。
ところが、読み取り専用配列に対して、Array.isArray
を使って型の絞り込みを行うと、any[]
型になってしまいます。
読み取り専用配列に対応してほしいという声はあるようで、issueに上がっていますが解決されていません。
Array.isArray
を読み取り専用配列に対応する方法
この問題を解決するには、isArray
の型定義を上書きします。型の上書きには、宣言マージ(declaration merging)を応用します。具体的には、次のArrayConstructor
インターフェースを定義します。
declare global {
interface ArrayConstructor {
isArray(arg: readonly any[] | any): arg is readonly any[];
}
}
これを書いておくと、読み取り専用配列に対しても型の絞り込みがうまくいくようになります。
ちなみに、読み取り専用タプル(readonly tuple)に対してもちゃんと効くようになります。