TypeScriptの勉強をしていた時に出てきた謎の...について調べたのでまとめる。
MDNドキュメントには
下記のように書かれていた。
スプレッド (...) 構文を使うと、配列式や文字列などの反復可能オブジェクトを、0 個以上の引数(関数呼び出しの場合)や要素(配列リテラルの場合)を目的の場所に展開することができます。オブジェクトリテラルでは、スプレッド構文によりオブジェクトのプロパティを列挙し、作成するオブジェクトにキーと値の組を追加します。
簡単に言うと
... は「配列やオブジェクトの中身を展開する」特殊な構文。
実際に使ってみた
配列
配列の場合は下記のように使える。
const a = [1, 2, 3];
const b = [...a, 4]; // → [1, 2, 3, 4]
...a で [1, 2, 3] の中身を展開して新しい配列にする
b は [1, 2, 3, 4] になる。
オブジェクト
オブジェクトだと下記。
const user = { name: "たろう", age: 20 };
const updated = { ...user, age: 21 };
...user でオブジェクトの中身を丸々コピー。
age: 21 で上書き。
updated → { name: "たろう", age: 21 }
まとめ
書き方 | 意味 |
---|---|
[...array] | 配列のコピーを作る |
[newItem, ...array] | 配列の先頭に要素追加 |
[...array, newItem] | 配列の末尾に要素追加 |
{...object} | オブジェクトのコピー |
{...obj, key: val} | 一部を上書きした新オブジェクト |
よくある用途
ChatGPTによくある用途を聞いたところ下記が出てきた。
- useState での状態更新
- props のコピーや合体
- オブジェクトのマージ
- イミュータブルな変更(元を直接変えない)
使用上の注意点
スプレッド構文は「浅いコピー」なので、ネストが深いと仲間ではコピーされない。
「浅いコピー」とは オブジェクトの一番上の階層だけ をコピーすること。
実際にソースコードで書いてみたところ、下記のように意図しない状態になった。
const original = {
name: "Taro",
info: {
age: 20,
city: "Tokyo"
}
};
const copy = { ...original };
copy.info.city = "Osaka";
console.log(original.info.city); // → "Osaka" に変わった...