webアプリ作成中、コンポーネントに{...カスタムフック(Url)}
と記述されているのを見て展開しているのかわからなかったので、「レスト構文」と「スプレッド構文」の違いについて調べました。
レスト構文(残余引数)
スプレット演算子の ...
を使用します。
オブジェクトや配列など、 残りの要素をまとめて変数に格納します。
function sum(...numbers: number[]) {
return numbers.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
const [first, ...rest] = [1, 2, 3, 4];
console.log(first); // 1
console.log(rest); // [2, 3, 4]
文法的位置
関数定義、配列やオブジェクトの分割代入で使用され、パラメータリストや分割代入の最後に配置されます。 複数の要素を1つの構造にまとめるものです(多 → 1)
スプレッド構文
既存の配列やオブジェクトの中身を展開します。
function sum(x: number, y: number, z: number) {
return x + y + z;
}
// タプル型
const arr1: [number, number, number] = [1, 2, 3];
console.log(sum(...arr1)); // 6
// または、as constアサーションを使用
const arr2 = [1, 2, 3] as const;
console.log(sum(...arr2)); // 6
文法的位置
通常、式の中で記述され、関数呼び出し、配列リテラル、オブジェクトリテラルで使用されます。1つの構造を複数の要素に展開するものです (1 → 多)
余談
スプレッド構文の例で タプル型
as const
を使用しているのは、sum関数は正確に3つの number型引数
を期待しているからです。
通常の配列型 (number[])
は長さが可変であるため、関数が期待する引数の数と一致する保証がないのです。以下だとエラーが出ます。
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]
function sum(x: number, y: number, z: number) {
return x + y + z;
}
console.log(sum(...arr1)); // error
長くなるので省きますが、他にもパターンがあり、詳しくは以下がわかりやすかったです。
まとめ
スプレッド構文は「展開」、レスト構文は「集約」と覚えておけば、文脈から見分けることができそうです。