Spread/Rest: 展開と収集

... の二つの顔。配列/オブジェクト操作の必須構文。

Spread
... で配列/オブジェクトを展開。
Rest
... で残りをまとめる。
浅いコピー
ネストしたオブジェクトは参照のまま。

Spread/Rest とは?

トランプを広げる・集める (Spread Cards)

Spread(...)は「手に持ったトランプをテーブルに広げる」イメージです。束(配列)が個々のカード(要素)になります。逆に Rest(...)は「テーブルのカードをかき集めて束にする」イメージです。

同じ `...` という記号を使いますが、文脈によって意味が逆になります。関数呼び出しや配列リテラルの中では「展開(Spread)」、関数の引数定義や分割代入の左辺では「集約(Rest)」として機能します。

Spread & Rest
// 配列の展開
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]
// オブジェクトの展開
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 }; // { a: 1, b: 2, c: 3 }
// 関数呼び出しで展開
Math.max(...arr1); // 3
// Rest パラメータ
function sum(...nums: number[]) {
return nums.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3, 4); // 10
Bad
// ❌ Bad: apply で配列を渡す
Math.max.apply(null, [1, 2, 3]);
// ❌ concat で結合
var merged = arr1.concat(arr2);
Good
// ✅ Good: スプレッド構文
Math.max(...[1, 2, 3]);
// ✅ スプレッドで結合
const merged = [...arr1, ...arr2];

パターン

Common Patterns
// 浅いコピー
const copy = [...original];
const objCopy = { ...original };
// 配列の途中に挿入
const withInsert = [...arr.slice(0, 2), 'new', ...arr.slice(2)];
// デフォルト値とマージ
const config = { ...defaults, ...userConfig };
// 分割代入との組み合わせ
const [first, ...rest] = [1, 2, 3, 4];
// first = 1, rest = [2, 3, 4]
const { a, ...others } = { a: 1, b: 2, c: 3 };
// a = 1, others = { b: 2, c: 3 }
Tip: スプレッドは浅いコピー。ネストしたオブジェクトには注意。

合格ライン

Spread と Rest の違いを説明できる
オブジェクトのマージができる

演習課題

課題1: Spread
スプレッド構文で配列をマージしてください。
課題2: Rest
Rest パラメータで可変長引数を受け取ってください。