函数参数 #
一、参数概述 #
Deno/TypeScript支持多种参数传递方式,包括位置参数、默认参数、可选参数、剩余参数和解构参数。
二、基本参数 #
2.1 位置参数 #
typescript
function greet(name: string, greeting: string): string {
return `${greeting}, ${name}!`;
}
console.log(greet("Alice", "Hello")); // Hello, Alice!
2.2 参数类型 #
typescript
function process(
text: string,
count: number,
flag: boolean,
callback: (result: string) => void
): void {
let result = "";
for (let i = 0; i < count; i++) {
result += text;
}
if (flag) {
callback(result);
}
}
process("Hi", 3, true, console.log); // HiHiHi
三、可选参数 #
3.1 基本语法 #
使用 ? 标记可选参数:
typescript
function greet(name: string, greeting?: string): string {
return `${greeting ?? "Hello"}, ${name}!`;
}
console.log(greet("Alice")); // Hello, Alice!
console.log(greet("Bob", "Hi")); // Hi, Bob!
3.2 可选参数必须在必选参数后面 #
typescript
// 正确
function correct(name: string, greeting?: string): string {
return `${greeting ?? "Hello"}, ${name}!`;
}
// 错误:可选参数不能在必选参数前面
// function wrong(greeting?: string, name: string): string { }
3.3 检查可选参数 #
typescript
function formatName(first: string, last?: string, middle?: string): string {
let result = first;
if (middle) {
result += ` ${middle}`;
}
if (last) {
result += ` ${last}`;
}
return result;
}
console.log(formatName("John")); // John
console.log(formatName("John", "Doe")); // John Doe
console.log(formatName("John", "Doe", "William")); // John William Doe
四、默认参数 #
4.1 基本语法 #
typescript
function greet(name: string, greeting: string = "Hello"): string {
return `${greeting}, ${name}!`;
}
console.log(greet("Alice")); // Hello, Alice!
console.log(greet("Bob", "Hi")); // Hi, Bob!
4.2 默认值表达式 #
typescript
function createTimestamp(date: Date = new Date()): string {
return date.toISOString();
}
console.log(createTimestamp()); // 当前时间
console.log(createTimestamp(new Date("2024-01-01"))); // 2024-01-01T00:00:00.000Z
4.3 使用前面参数的值 #
typescript
function createProfile(
name: string,
id: string = name.toLowerCase().replace(/\s+/g, "-")
): { name: string; id: string } {
return { name, id };
}
console.log(createProfile("Alice Smith"));
// { name: "Alice Smith", id: "alice-smith" }
4.4 默认参数与undefined #
typescript
function greet(name: string, greeting: string = "Hello"): string {
return `${greeting}, ${name}!`;
}
console.log(greet("Alice", undefined)); // Hello, Alice!(使用默认值)
console.log(greet("Alice", "")); // , Alice!(空字符串,不使用默认值)
五、剩余参数 #
5.1 基本语法 #
使用 ... 收集剩余参数:
typescript
function sum(...numbers: number[]): number {
return numbers.reduce((acc, n) => acc + n, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
console.log(sum(10, 20)); // 30
5.2 与普通参数组合 #
typescript
function greetAll(greeting: string, ...names: string[]): string {
return names.map(name => `${greeting}, ${name}!`).join(" ");
}
console.log(greetAll("Hello", "Alice", "Bob", "Charlie"));
// Hello, Alice! Hello, Bob! Hello, Charlie!
5.3 元组类型剩余参数 #
typescript
function process(...args: [string, number, boolean]): void {
const [str, num, bool] = args;
console.log(str, num, bool);
}
process("hello", 42, true); // hello 42 true
5.4 数组展开 #
typescript
function sum(...numbers: number[]): number {
return numbers.reduce((acc, n) => acc + n, 0);
}
const values = [1, 2, 3, 4, 5];
console.log(sum(...values)); // 15
六、解构参数 #
6.1 对象解构 #
typescript
interface User {
name: string;
age: number;
email?: string;
}
function greet({ name, age, email }: User): string {
let result = `Hello, ${name}! You are ${age} years old.`;
if (email) {
result += ` Email: ${email}`;
}
return result;
}
console.log(greet({ name: "Alice", age: 25 }));
// Hello, Alice! You are 25 years old.
6.2 带默认值的解构 #
typescript
interface Options {
host?: string;
port?: number;
secure?: boolean;
}
function connect({
host = "localhost",
port = 3000,
secure = false
}: Options = {}): string {
return `${secure ? "https" : "http"}://${host}:${port}`;
}
console.log(connect()); // http://localhost:3000
console.log(connect({ port: 8080 })); // http://localhost:8080
console.log(connect({ host: "api.example.com", secure: true }));
// https://api.example.com:3000
6.3 数组解构 #
typescript
function process([first, second, ...rest]: number[]): void {
console.log(`First: ${first}`);
console.log(`Second: ${second}`);
console.log(`Rest: ${rest}`);
}
process([1, 2, 3, 4, 5]);
// First: 1
// Second: 2
// Rest: 3,4,5
6.4 嵌套解构 #
typescript
interface Config {
server: {
host: string;
port: number;
};
database: {
name: string;
user: string;
};
}
function init({
server: { host, port },
database: { name, user }
}: Config): void {
console.log(`Server: ${host}:${port}`);
console.log(`Database: ${name} (${user})`);
}
七、参数类型 #
7.1 联合类型参数 #
typescript
function process(value: string | number): string {
if (typeof value === "string") {
return value.toUpperCase();
}
return value.toFixed(2);
}
console.log(process("hello")); // HELLO
console.log(process(3.14159)); // 3.14
7.2 字面量类型参数 #
typescript
type Direction = "up" | "down" | "left" | "right";
function move(direction: Direction, distance: number): string {
return `Moving ${direction} by ${distance}`;
}
console.log(move("up", 10)); // Moving up by 10
// move("forward", 10); // 错误:类型不匹配
7.3 函数类型参数 #
typescript
function execute(
value: number,
transform: (v: number) => number
): number {
return transform(value);
}
console.log(execute(5, n => n * 2)); // 10
console.log(execute(5, n => n * n)); // 25
7.4 泛型参数 #
typescript
function identity<T>(value: T): T {
return value;
}
console.log(identity<string>("hello")); // hello
console.log(identity(42)); // 42
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { name: "Alice", age: 25 };
console.log(getProperty(user, "name")); // Alice
八、参数校验 #
8.1 运行时校验 #
typescript
function divide(a: number, b: number): number {
if (b === 0) {
throw new Error("除数不能为零");
}
return a / b;
}
console.log(divide(10, 2)); // 5
// divide(10, 0); // Error: 除数不能为零
8.2 类型守卫 #
typescript
function process(value: unknown): string {
if (typeof value === "string") {
return value.toUpperCase();
}
if (typeof value === "number") {
return value.toFixed(2);
}
throw new Error("不支持的类型");
}
8.3 参数对象模式 #
typescript
interface FetchOptions {
url: string;
method?: "GET" | "POST" | "PUT" | "DELETE";
headers?: Record<string, string>;
body?: unknown;
timeout?: number;
}
async function fetchData(options: FetchOptions): Promise<Response> {
const {
url,
method = "GET",
headers = {},
body,
timeout = 5000
} = options;
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, {
method,
headers,
body: body ? JSON.stringify(body) : undefined,
signal: controller.signal
});
return response;
} finally {
clearTimeout(timeoutId);
}
}
九、实际应用 #
9.1 配置合并 #
typescript
interface Config {
host?: string;
port?: number;
debug?: boolean;
logLevel?: "debug" | "info" | "warn" | "error";
}
const defaultConfig: Required<Config> = {
host: "localhost",
port: 3000,
debug: false,
logLevel: "info"
};
function createConfig(userConfig: Config = {}): Required<Config> {
return {
...defaultConfig,
...userConfig
};
}
console.log(createConfig({ port: 8080, debug: true }));
// { host: "localhost", port: 8080, debug: true, logLevel: "info" }
9.2 事件处理器 #
typescript
interface Event {
type: string;
payload?: unknown;
timestamp?: Date;
}
function handleEvent(
{ type, payload, timestamp = new Date() }: Event,
handlers: Record<string, (payload: unknown) => void>
): void {
console.log(`[${timestamp.toISOString()}] Event: ${type}`);
const handler = handlers[type];
if (handler) {
handler(payload);
}
}
handleEvent(
{ type: "user.created", payload: { name: "Alice" } },
{
"user.created": (payload) => console.log("New user:", payload)
}
);
9.3 构建器模式 #
typescript
interface QueryBuilder {
table: string;
fields: string[];
where?: string;
orderBy?: string;
limit?: number;
}
function buildQuery({
table,
fields,
where,
orderBy,
limit
}: QueryBuilder): string {
let query = `SELECT ${fields.join(", ")} FROM ${table}`;
if (where) {
query += ` WHERE ${where}`;
}
if (orderBy) {
query += ` ORDER BY ${orderBy}`;
}
if (limit) {
query += ` LIMIT ${limit}`;
}
return query;
}
console.log(buildQuery({
table: "users",
fields: ["id", "name", "email"],
where: "active = true",
orderBy: "created_at DESC",
limit: 10
}));
// SELECT id, name, email FROM users WHERE active = true ORDER BY created_at DESC LIMIT 10
十、最佳实践 #
10.1 参数数量控制 #
typescript
// 不推荐:参数太多
function createUser(
name: string,
email: string,
age: number,
city: string,
country: string,
phone: string
) { }
// 推荐:使用参数对象
interface UserData {
name: string;
email: string;
age?: number;
address?: {
city: string;
country: string;
};
phone?: string;
}
function createUser(data: UserData) { }
10.2 合理使用默认值 #
typescript
// 推荐:为可选参数提供合理的默认值
function fetchData(
url: string,
options: {
method?: string;
headers?: Record<string, string>;
timeout?: number;
} = {}
) {
const { method = "GET", headers = {}, timeout = 5000 } = options;
// ...
}
10.3 类型安全 #
typescript
// 推荐:使用严格类型
function process(value: string | number): string {
if (typeof value === "string") {
return value.toUpperCase();
}
return value.toFixed(2);
}
// 不推荐:使用any
function processUnsafe(value: any): any {
return value;
}
十一、总结 #
本章学习了:
- 基本参数和类型
- 可选参数
- 默认参数
- 剩余参数
- 解构参数
- 参数类型(联合、字面量、函数、泛型)
- 参数校验
- 最佳实践
下一章,我们将学习闭包。
最后更新:2026-03-28