- Abstraction
- AI Pair Programming
- Algorithm
- API
- Array
- Array methods
- Booleans
- Callback
- Class
- Class Members
- Closure
- Closure
- Code refactoring
- Comment
- Computer programming
- Conditional statements
- Constant
- Constructor
- Coupling and Cohesion
- Data types
- Debugging
- Decorator
- Dependency
- Destructuring
- Dictionary
- Enum
- Event
- Exception / Error handling
- Function
- Generic / Template
- Higher-order function
- IDE
- Immutability
- Inheritance
- Input validation
- Integer
- Interface
- Iteration patterns
- Legacy code
- Loop
- Machine learning
- Memoization
- Memory and references
- Method
- Module
- Null / Undefined / None
- Null safety / Optional values
- Object
- Object-Oriented Programming (OOP)
- Operator
- Parameter
- Parsing
- Promise and Async/Await
- Prompt Engineering
- Recursion
- Regular expression
- Return statement
- Rollback
- Runtime
- Scope
- Script
- Sequence
- Set
- Spaghetti code
- Spread and Rest operators
- State management
- String
- Switch statement
- Synchronous vs Asynchronous execution
- Syntax
- Technical debt
- Ternary operator
- Testing
- This / Self
- Tuple
- Type casting
- Type conversion
- Variable
- Vibe coding
- Webhook
PROGRAMMING-CONCEPTS
Spread and Rest Operators: Definition, Purpose, and Examples
The spread and rest operators give developers flexible ways to expand or gather values from arrays, objects, and function arguments. Although they look identical (...) in JavaScript and TypeScript, their roles differ:
- Spread expands a collection into individual elements
- Rest collects multiple values into a single collection
Python offers similar behavior through unpacking with * and **, and Swift supports rest-like variadic parameters.
These features simplify data merging, configuration building, function signatures, and component logic across modern codebases.
What the Spread Operator Does
Spread expands an array, object, or iterable into separate elements. It helps create new collections without mutating existing ones.
Example: Expanding an array once
const numbers = [1, 2, 3];
const extended = [...numbers, 4, 5];
Spread makes the new array easier to read and avoids modifying numbers.
Example: Passing dynamic arguments
const nums = [4, 12, 8];
const max = Math.max(...nums);
Here, spread unpacks array values into function arguments.
Conditional spreading (real-world example)
This is common in configuration files:
const config = {
mode: "production",
...(process.env.DEBUG && { debug: true })
};
If the condition is false, nothing is added.
What the Rest Operator Does
Rest collects multiple values into a single variable. You see it in function parameters and destructuring.
Collecting arguments in a function
function tag(label, ...items) {
return `${label}: ${items.join(", ")}`;
}
tag("Fruits", "apple", "banana", "cherry");
items becomes an array containing all remaining arguments.
Array destructuring with rest
const [head, ...tail] = [10, 20, 30, 40];
// head = 10
// tail = [20, 30, 40]
Object rest
const user = { id: 7, name: "Luka", verified: true };
const { id, ...profile } = user;
// profile = { name: "Luka", verified: true }
Rest helps when you need part of an object but want to pass the remainder somewhere else.
Spread and Rest in TypeScript
TypeScript adds strong typing on top of JavaScript’s behavior.
Generic rest/spread merge utility
function mergeObjects<T extends object>(...objects: T[]): T {
return Object.assign({}, ...objects);
}
const settings = mergeObjects(
{ theme: "dark" },
{ language: "en" },
{ notifications: true }
);
TypeScript ensures that all merged values match the expected object type.
Python’s Version: * and **
Python uses * for sequences and ** for dictionaries.
Expanding a list
Python
a = [1, 2]
b = [*a, 3, 4]
Collecting arguments
Python
def summarize(*values):
return sum(values)
summarize(1, 5, 10)
Merging dictionaries
Python
base = {"theme": "dark"}
overrides = {"language": "en"}
merged = {**base, **overrides}
The intent mirrors JavaScript spread/rest even though the symbols differ.
Swift’s Equivalent Features
Swift doesn’t use ... for collections, but supports rest-like parameters.
Variadic function example
func average(_ nums: Double...) -> Double {
let total = nums.reduce(0, +)
return total / Double(nums.count)
}
average(2.0, 4.0, 6.0)
For simple cases, tuple destructuring mimics unpacking behavior.
When Spread and Rest Are Most Useful
Spread/rest patterns shine when organizing code around flexible, composable data.
1. Updating or extending data immutably
Especially common in React state updates:
setSettings(prev => ({
...prev,
theme: "light"
}));
Only the changed field is updated.
2. Merging configurations
Great for building API query parameters, command options, or UI settings.
const baseParams = { page: 1 };
const filters = { category: "books" };
const finalParams = { ...baseParams, ...filters };
3. Creating expressive function signatures
Rest parameters make your function handle unlimited arguments cleanly.
function combine(...sections) {
return sections.join(" / ");
}
4. Transforming collections
Combined with destructuring, spread helps reorganize arrays:
const list = ["start", "middle", "end"];
const [, ...rest] = list; // ["middle", "end"]
Examples of Spread/Rest in Real Applications
Example 1: Building API query strings
const base = { limit: 20 };
const filters = { search: "python" };
const params = { ...base, ...filters };
This is standard in dashboards, admin panels, and data-driven apps.
Example 2: Immutable list insertion
const items = ["a", "b", "c"];
const updated = [...items.slice(0, 1), "x", ...items.slice(1)];
This pattern avoids mutating the original array.
Example 3: Normalizing event data
function logEvent(type, ...details) {
console.log({ type, details });
}
logEvent("CLICK", "button", "header");
Rest makes the signature flexible.
Spread vs Rest: The Practical Rule
A simple way to remember the difference:
- Spread “opens” a collection
- Rest “gathers” values into a collection
Despite using the same symbol, they behave in opposite directions.
Common Mistakes and How to Avoid Them
Mistake: Confusing spread with deep clones
Spread only clones the first level:
const copy = { ...obj }; // nested objects still reference originals
Mistake: Order mismatch during object merging
Later spreads override earlier ones:
{ ...a, ...b } // b wins
Mistake: Using spread on non-iterables
Works only on arrays, iterables, and plain objects.
Mistake: Overusing nested spread
Deep or complicated spreads can reduce clarity.
Better to break it into steps for readability.
Summary
Spread expands values.
Rest collects values.
JavaScript and TypeScript use ..., Python uses * and **, and Swift supports rest-like variadic arguments. These operators simplify array manipulation, configuration merging, function design, React component patterns, and many real-world workflows. When used thoughtfully, spread and rest reduce duplication, improve readability, and make data structures far easier to work with.
Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.