π Rest parameters let you represent an indefinite number of arguments as an array.
function func(...args: type[]) {}β Basic Example
function sum(...numbers: number[]): number {
return numbers.reduce((total, num) => total + num, 0);
}
sum(1, 2, 3); // 6
sum(10, 20, 30, 40); // 100π§ numbers: number[] β TypeScript infers the rest parameter is an array of numbers.
βοΈ Mixed Parameters + Rest
function greet(greeting: string, ...names: string[]) {
return `${greeting}, ${names.join(" & ")}`;
}
greet("Hello", "Alice", "Bob"); // "Hello, Alice & Bob"π₯ Important:
β Rest parameter must come last in the parameter list.
function invalid(...nums: number[], prefix: string) {} // β Error<div class="infographic-ts" id="infographic-ts">
<style>
.infographic-ts {
--body-font: system-ui, -apple-system, sans-serif;
--mono-font: ui-monospace, SFMono-Regular, Consolas, "Courier New", monospace;
--ed-bg: #1e1e1e;
--ed-bar: #2a2a2a;
--ed-out: #d4d4d4;
--ed-muted: #8a8a8a;
--ed-ok: #4ec9b0;
--run-bg: #2e7d46;
--run-bg-hover: #35924f;
--tok-kw: #c586c0;
--tok-type: #4ec9b0;
--tok-str: #ce9178;
--tok-num: #b5cea8;
--tok-cmt: #808080;
--tok-var: #ffffff;
max-width: 680px;
margin: 0 auto;
box-sizing: border-box;
background: transparent;
font-family: var(--body-font);
}
.infographic-ts * { box-sizing: border-box; }
.ts-header { font-family: 'Georgia', 'Fraunces', serif; font-weight: 700;
font-size: 1.9rem; letter-spacing: 0.01em; color: inherit; text-align: center;
margin: 0 0 1.4rem; }
.code-window { background: var(--ed-bg); border: 1px solid #2f2f2f; border-radius: 8px;
overflow: hidden; margin-bottom: 1rem; }
.code-window:last-child { margin-bottom: 0; }
.code-topbar { display: flex; align-items: center; justify-content: space-between;
padding: 0.5rem 0.75rem; background: var(--ed-bar); }
.code-dots { display: flex; gap: 6px; }
.code-dot { width: 9px; height: 9px; border-radius: 50%; }
.code-dot.r { background: #ff5f57; }
.code-dot.y { background: #febc2e; }
.code-dot.g { background: #28c840; }
.code-filename { font-family: var(--mono-font); font-size: 0.74rem; color: var(--ed-muted); }
.run-btn { display: inline-flex; align-items: center; gap: 0.35rem; background: var(--run-bg);
color: #fff; border: none; border-radius: 4px; padding: 0.32rem 0.7rem; font-size: 0.74rem;
font-family: var(--body-font); font-weight: 500; cursor: pointer; }
.run-btn:hover { background: var(--run-bg-hover); }
.run-btn svg { width: 10px; height: 10px; }
.code-body { padding: 0.85rem 1.1rem; font-family: var(--mono-font); font-size: 0.8rem;
line-height: 1.65; color: var(--ed-out); white-space: pre; overflow-x: auto; }
.tok-kw { color: var(--tok-kw); }
.tok-type { color: var(--tok-type); }
.tok-str { color: var(--tok-str); }
.tok-num { color: var(--tok-num); }
.tok-punc { color: var(--tok-var); }
.tok-cmt { color: var(--tok-cmt); }
.tok-var { color: var(--tok-var); }
.console { padding: 0 1.1rem; max-height: 0; overflow: hidden; font-family: var(--mono-font);
font-size: 0.78rem; line-height: 1.65; transition: max-height 0.35s ease, padding 0.35s ease; }
.console.show { max-height: 260px; padding: 0 1.1rem 0.85rem; }
.console-line { color: var(--ed-out); }
.console-line.ok { color: var(--ed-ok); }
.note-line { font-family: var(--body-font); font-size: 0.8rem; color: var(--ed-muted);
padding: 0 0.2rem; margin: 0 0 1rem; }
</style>
<h2 class="ts-header">Examples</h2>
<div class="code-window">
<div class="code-topbar">
<div class="code-dots"><span class="code-dot r"></span><span class="code-dot y"></span><span class="code-dot g"></span></div>
<span class="code-filename">sum.ts</span>
<button class="run-btn" id="sumBtn" type="button">
<svg viewBox="0 0 24 24" fill="currentColor"><polygon points="6 3 20 12 6 21 6 3"/></svg>
run
</button>
</div>
<div class="code-body"><span class="tok-cmt">// gathers any number of arguments into one typed array</span>
<span class="tok-kw">function</span> <span class="tok-var">sum</span><span class="tok-punc">(</span><span class="tok-punc">...</span><span class="tok-var">nums</span><span class="tok-punc">:</span> <span class="tok-type">number</span><span class="tok-punc">[])</span><span class="tok-punc">:</span> <span class="tok-type">number</span> <span class="tok-punc">{</span>
<span class="tok-kw">return</span> <span class="tok-var">nums</span><span class="tok-punc">.</span><span class="tok-var">reduce</span><span class="tok-punc">((</span><span class="tok-var">total</span><span class="tok-punc">,</span> <span class="tok-var">n</span><span class="tok-punc">)</span> <span class="tok-punc">=></span> <span class="tok-var">total</span> <span class="tok-punc">+</span> <span class="tok-var">n</span><span class="tok-punc">,</span> <span class="tok-num">0</span><span class="tok-punc">);</span>
<span class="tok-punc">}</span>
<span class="tok-var">sum</span><span class="tok-punc">(</span><span class="tok-num">1</span><span class="tok-punc">,</span> <span class="tok-num">2</span><span class="tok-punc">,</span> <span class="tok-num">3</span><span class="tok-punc">);</span>
<span class="tok-var">sum</span><span class="tok-punc">(</span><span class="tok-num">10</span><span class="tok-punc">,</span> <span class="tok-num">20</span><span class="tok-punc">,</span> <span class="tok-num">30</span><span class="tok-punc">,</span> <span class="tok-num">40</span><span class="tok-punc">);</span></div>
<div class="console" id="sumConsole"></div>
</div>
<p class="note-line">Any number of arguments collapse into one array parameter — here typed as number[].</p>
<div class="code-window">
<div class="code-topbar">
<div class="code-dots"><span class="code-dot r"></span><span class="code-dot y"></span><span class="code-dot g"></span></div>
<span class="code-filename">introduce.ts</span>
<button class="run-btn" id="introBtn" type="button">
<svg viewBox="0 0 24 24" fill="currentColor"><polygon points="6 3 20 12 6 21 6 3"/></svg>
run
</button>
</div>
<div class="code-body"><span class="tok-cmt">// a fixed parameter can come before the rest parameter</span>
<span class="tok-kw">function</span> <span class="tok-var">introduce</span><span class="tok-punc">(</span><span class="tok-var">greeting</span><span class="tok-punc">:</span> <span class="tok-type">string</span><span class="tok-punc">,</span> <span class="tok-punc">...</span><span class="tok-var">names</span><span class="tok-punc">:</span> <span class="tok-type">string</span><span class="tok-punc">[])</span><span class="tok-punc">:</span> <span class="tok-type">string</span> <span class="tok-punc">{</span>
<span class="tok-kw">return</span> <span class="tok-str">`${</span><span class="tok-var">greeting</span><span class="tok-str">}, ${</span><span class="tok-var">names</span><span class="tok-punc">.</span><span class="tok-var">join</span><span class="tok-punc">(</span><span class="tok-str">" and "</span><span class="tok-punc">)</span><span class="tok-str">}!`</span><span class="tok-punc">;</span>
<span class="tok-punc">}</span>
<span class="tok-var">introduce</span><span class="tok-punc">(</span><span class="tok-str">"Hello"</span><span class="tok-punc">,</span> <span class="tok-str">"Alice"</span><span class="tok-punc">);</span>
<span class="tok-var">introduce</span><span class="tok-punc">(</span><span class="tok-str">"Hi"</span><span class="tok-punc">,</span> <span class="tok-str">"Alice"</span><span class="tok-punc">,</span> <span class="tok-str">"Bob"</span><span class="tok-punc">,</span> <span class="tok-str">"Charlie"</span><span class="tok-punc">);</span></div>
<div class="console" id="introConsole"></div>
</div>
<p class="note-line">The rest parameter must come last — everything after the fixed ones gets swept in.</p>
<div class="code-window">
<div class="code-topbar">
<div class="code-dots"><span class="code-dot r"></span><span class="code-dot y"></span><span class="code-dot g"></span></div>
<span class="code-filename">combine.ts</span>
<button class="run-btn" id="combineBtn" type="button">
<svg viewBox="0 0 24 24" fill="currentColor"><polygon points="6 3 20 12 6 21 6 3"/></svg>
run
</button>
</div>
<div class="code-body"><span class="tok-cmt">// the rest array can hold a union of types</span>
<span class="tok-kw">function</span> <span class="tok-var">combine</span><span class="tok-punc">(</span><span class="tok-var">separator</span><span class="tok-punc">:</span> <span class="tok-type">string</span><span class="tok-punc">,</span> <span class="tok-punc">...</span><span class="tok-var">items</span><span class="tok-punc">:</span> <span class="tok-punc">(</span><span class="tok-type">string</span> <span class="tok-punc">|</span> <span class="tok-type">number</span><span class="tok-punc">)[])</span><span class="tok-punc">:</span> <span class="tok-type">string</span> <span class="tok-punc">{</span>
<span class="tok-kw">return</span> <span class="tok-var">items</span><span class="tok-punc">.</span><span class="tok-var">join</span><span class="tok-punc">(</span><span class="tok-var">separator</span><span class="tok-punc">);</span>
<span class="tok-punc">}</span>
<span class="tok-var">combine</span><span class="tok-punc">(</span><span class="tok-str">"-"</span><span class="tok-punc">,</span> <span class="tok-num">1</span><span class="tok-punc">,</span> <span class="tok-num">2</span><span class="tok-punc">,</span> <span class="tok-num">3</span><span class="tok-punc">);</span>
<span class="tok-var">combine</span><span class="tok-punc">(</span><span class="tok-str">", "</span><span class="tok-punc">,</span> <span class="tok-str">"a"</span><span class="tok-punc">,</span> <span class="tok-str">"b"</span><span class="tok-punc">,</span> <span class="tok-str">"c"</span><span class="tok-punc">);</span></div>
<div class="console" id="combineConsole"></div>
</div>
<p class="note-line">Each item's type is still checked — only string | number values are allowed through.</p>
<script>
(function () {
var wrapper = document.currentScript.closest('.infographic-ts')
|| document.querySelector('.infographic-ts');
var root = wrapper;
function line(consoleEl, cls, text) {
var el = document.createElement('div');
el.className = 'console-line ' + (cls || '');
el.textContent = text;
consoleEl.appendChild(el);
}
function bind(id, consoleId, cb) {
var btn = root.querySelector('#' + id);
var c = root.querySelector('#' + consoleId);
btn.addEventListener('click', function () {
c.innerHTML = '';
c.classList.add('show');
cb(c);
});
}
bind('sumBtn', 'sumConsole', function (c) {
line(c, 'ok', 'sum(1, 2, 3) \u2192 6');
line(c, 'ok', 'sum(10, 20, 30, 40) \u2192 100');
});
bind('introBtn', 'introConsole', function (c) {
line(c, 'ok', 'introduce("Hello", "Alice") \u2192 "Hello, Alice!"');
line(c, 'ok', 'introduce("Hi", "Alice", "Bob", "Charlie") \u2192 "Hi, Alice and Bob and Charlie!"');
});
bind('combineBtn', 'combineConsole', function (c) {
line(c, 'ok', 'combine("-", 1, 2, 3) \u2192 "1-2-3"');
line(c, 'ok', 'combine(", ", "a", "b", "c") \u2192 "a, b, c"');
});
})();
</script>
</div>β Parameter Ordering Rules in TypeScript
π Correct order:
required β default β optional β restBut since optional and default parameters can technically swap, the main rule is:
Rest parameter must always come last β that's non-negotiable!
π₯ So the safe and clean order is:
function example(
required: string,
defaultParam: number = 10,
optionalParam?: boolean,
...rest: string[]
) {
// function body
}β This works perfectly:
example("req"); // defaultParam = 10, optionalParam = undefined, rest = []
example("req", 20); // optionalParam = undefined
example("req", 20, true, "a", "b"); // rest = ["a", "b"]β¨ Summary
Feature | Purpose | Example |
|---|---|---|
| Handle multiple args as an array |
|
Type | Must be an array type |
|
Must be last | Only one rest param allowed |
|
β Real-World Use Cases
Summing or combining many values
Forwarding arguments to other functions
Building custom utility functions