readonly配列にpushしようとするとdoes not exist on typeになる理由
readonly number[]のように宣言した配列型には、push・pop・splice等の破壊的(要素を変更する)メソッドがそもそも型として存在しません。呼び出そうとした時点で「そのメソッドは無い」というエラーになります。
エラーメッセージの読み方
main.ts(2,9): error TS2339: Property 'push' does not exist on type 'readonly number[]'.
main.ts- ファイル名
2- 行番号
9- 列番号 — この位置でtscが検査に失敗しました
TS2339- エラーコード — 検索するとTypeScriptの解説が見つかります
Property 'push' does not exist on type 'readonly number[]'.- 内容 — 期待していたもの、または受け付けられなかったもの
このエラーが出る典型パターン
パターン1
1 function printAll(items: readonly number[]): void { 2 items.push (4); ^ 3 console.log(items); 4 } 5 printAll([1, 2, 3]);
main.ts(2,9): error TS2339: Property 'push' does not exist on type 'readonly number[]'.
readonly number[]にはpushのような破壊的メソッドは型として存在しません。concatのような非破壊的メソッドを使います。
直し方: push を concat にします。
広告
広告スロット(未設定)
パターン2
1 function clearAll(items: readonly string[]): void { 2 items.splice(0, items.length); ^ 3 console.log(items); 4 } 5 clearAll(["a", "b"]);
main.ts(2,9): error TS2551: Property 'splice' does not exist on type 'readonly string[]'. Did you mean 'slice'?
spliceは配列を直接書き換える破壊的メソッドです。readonly配列の型には含まれていません。
直し方: splice を slice にします。
パターン3
1 function reverseAll(items: readonly number[]): void { 2 items.reverse(); ^ 3 console.log(items); 4 } 5 reverseAll([1, 2, 3]);
main.ts(2,9): error TS2339: Property 'reverse' does not exist on type 'readonly number[]'.
reverseも元の配列を書き換える破壊的メソッドのため、readonly配列の型からは除外されています。
直し方: reverse を slice にします。
よくある誤解
「readonlyは実行時に書き換えを禁止する機能」だと誤解されがちですが、実際にはコンパイル時の型チェックだけの仕組みです。破壊的メソッド自体が型定義から除外されているため、呼び出しコードの時点でエラーになります。
まとめ
readonly配列にpushしようとするとdoes not exist on typeになる理由は中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。