剩余参数允许函数接受不定数量的参数,将它们收集到一个数组中。使用
...语法,剩余参数必须是函数的最后一个参数。
在参数名前添加 ...,该参数会收集所有剩余的参数值。
function sum(...numbers: number[]): number {
return numbers.reduce((total, n) => total + n, 0)
}
console.log(sum(1, 2, 3))
console.log(sum(10, 20, 30, 40, 50))
console.log(sum())
numbers 是剩余参数,类型是 number[]。调用时可以传入任意数量的数字参数。
剩余参数必须放在所有固定参数之后。
function greet(greeting: string, ...names: string[]): string {
return `${greeting}, ${names.join("、")}!`
}
console.log(greet("你好", "张三"))
console.log(greet("早上好", "张三", "李四", "王五"))
第一个参数 greeting 是固定参数,后面的所有参数都被收集到 names 数组中。
剩余参数的类型必须是数组类型或元组类型。
function logAll(...messages: string[]): void {
messages.forEach(msg => console.log(msg))
}
logAll("消息1", "消息2", "消息3")
function printCoordinates(...coords: [number, number, number]): void {
const [x, y, z] = coords
console.log(`坐标: (${x}, ${y}, ${z})`)
}
printCoordinates(10, 20, 30)
数组类型接受任意数量的参数,元组类型限制参数的数量和类型。
剩余参数可以与泛型结合使用,实现类型安全的可变参数函数。
function combine<T>(...arrays: T[][]): T[] {
return arrays.flat()
}
console.log(combine([1, 2], [3, 4], [5, 6]))
console.log(combine(["a", "b"], ["c", "d"]))
function pickFirst<T>(...items: T[]): T | undefined {
return items[0]
}
console.log(pickFirst(1, 2, 3))
console.log(pickFirst("a", "b", "c"))
console.log(pickFirst())
泛型让剩余参数的类型更加灵活,同时保持类型安全。
箭头函数也可以使用剩余参数。
const multiply = (...factors: number[]): number => {
return factors.reduce((product, n) => product * n, 1)
}
console.log(multiply(2, 3, 4))
const format = (template: string, ...values: string[]): string => {
return template.replace(/{}/g, () => values.shift() || "")
}
console.log(format("你好,{},欢迎来到{}", "张三", "北京"))
箭头函数的剩余参数语法与普通函数相同。
剩余参数可以与解构语法结合使用。
function processInput(input: string, ...[first, second, ...rest]: string[]): void {
console.log(`输入: ${input}`)
console.log(`第一: ${first}`)
console.log(`第二: ${second}`)
console.log(`其余: ${rest}`)
}
processInput("测试", "a", "b", "c", "d")
解构语法在参数位置直接展开剩余参数,但这种方式可读性较差,通常不推荐使用。
在普通函数中,arguments 对象包含所有参数。但剩余参数是更好的选择。
function sumOld(): number {
let total = 0
for (let i = 0; i < arguments.length; i++) {
total += arguments[i]
}
return total
}
function sumNew(...numbers: number[]): number {
return numbers.reduce((total, n) => total + n, 0)
}
console.log(sumOld(1, 2, 3))
console.log(sumNew(1, 2, 3))
剩余参数的优势:
剩余参数在实际开发中有很多应用场景。
function formatMessage(template: string, ...args: any[]): string {
return template.replace(/{(\d+)}/g, (match, index) => {
return typeof args[index] !== "undefined" ? args[index] : match
})
}
console.log(formatMessage("你好,{0},你有{1}条新消息", "张三", 5))
function createLogger(prefix: string) {
return (...messages: string[]): void => {
const timestamp = new Date().toISOString()
messages.forEach(msg => {
console.log(`[${timestamp}] [${prefix}] ${msg}`)
})
}
}
const appLogger = createLogger("APP")
appLogger("应用启动", "加载配置", "初始化完成")
function mergeObjects<T extends object>(...objects: T[]): T {
return objects.reduce((result, obj) => ({ ...result, ...obj }), {} as T)
}
const merged = mergeObjects(
{ a: 1 },
{ b: 2 },
{ c: 3 }
)
console.log(merged)
剩余参数让函数可以处理不定数量的参数,非常适合日志、格式化、合并等操作。
剩余参数使用 ... 语法收集多个参数到数组中。它必须是函数的最后一个参数,类型必须是数组或元组。相比 arguments 对象,剩余参数有明确的类型,是真正的数组,在箭头函数中也能使用。剩余参数是实现可变参数函数的标准方式。