JSの配列要素にアクセスするときは添字指定をやめてatメソッドを使おう
社内で「Arrayの要素を指定するときは [i]
やめて.at(i)
を使おう」という内容の雑談をしていました.
添字指定に感じていた課題
添字指定でもat
メソッドでもどちらもArrayの要素を取得できるメソッドであることに変わりはないのですが,TypeScript上で添字指定した場合はundefined
が返ってくる可能性が推論されないということに課題を感じていました.
const arr: string[] = [];
const str: string = arr[0]; // OK
console.log(str); // undefined
この例では,1行目で空のstring[]
を作成していますが,2行目で最初の要素を取得するとstring | undefined
ではなくstring
と推論されてしまいます.
ところが,実際に実行するとstr
の中身はundefined
であることがわかります.
一般的な習慣として,配列へアクセスする際はその値があるかどうかをチェックするコードを書きます.
const arr: string[] = [];
const str: string = arr[0]; // OK
if (str) console.log(str);
ただ,TypeScript上でStringと推論されているものに対してわざわざチェックコードを書くということに個人的に気持ち悪さを感じているという課題がありました.
正しい型情報を付与したい
添字指定の場合に正しい推論を行えるようにするにはどうしたら良いでしょうか?
方法の一つとして,明示的にT | undefined
にアサーションする方法があります.
const arr: string[] = [];
-const str: string = arr[0];
+const str = arr[0] as string | undefined;
if (str) console.log(str);
もしくは次のように書くこともできます.
const arr: string[] = [];
-const str: string = arr[0];
+const str: string | undefined = arr[0];
if (str) console.log(str);
添字指定をやめたい
型アサーションは現実(JavaScript)と理想(TypeScript)との不都合を良い感じにできる強力な方法ですが,添字指定を利用し続ける以上どうしてもミスが発生する可能性があります.
そこで,代わりに配列から要素を取り出してくれる補助関数を用意し,補助関数を経由して配列から要素を取り出すようにすることで,毎度型アサーションをする必要がなくなり,期待する推論結果を得ることができます.
const arr: string[] = [];
-const str: string = arr[0];
+const str = arrayAt(arr, 0);
if (str) console.log(str);
+function arrayAt<T>(arr: T[], i: number): T | undefined {
+ return arr[i];
+}
Array.prototype.at
を使おう
補助関数を利用する方法も紹介しましたが,atメソッドを使いましょう.
at
メソッドは2022年3月時点の主要ブラウザで広くサポートされているほか,TypeScript上でも推論結果がT | undefined
になってくれるまさに欲しかったメソッドです.
const arr: string[] = [];
-const str: string = arr[0];
+const str = arr.at(0); // string | undefined
if (str) console.log(str);
添字指定をやめてat
メソッドを使うだけで,string
型の変数に代入しようとした場合は期待する型エラーを取得することができます.
const arr: string[] = [];
const str: string = arr.at(0); // Type 'undefined' is not assignable to type 'string'.
配列の最後の要素を取得しやすい
また,at
メソッドは添字となる値にマイナス値を指定して行くことで最後の要素から順にアクセスできるようになっています.
そのため,次のようにコードの記述量を減らすこともできます.
-const str: string | undefined = arr[arr.length - 1];
+const str = arr.at(-1);
どのバージョンから使えるの?
2022年3月時点で広くブラウザでサポートされている記法なため,よほど古い実行環境でなければat
メソッドは普通に使うことができます.
TypeScriptも,4.6以上でes2022以上をターゲットにすることで型推論が行われます.
Discussion
noUncheckedIndexedAccessってオプションありますよpalyground
このオプション把握してなかったです。
ありがとうございます✨