TypeScript 提供了多种方式来处理复杂的参数传递。以下是一些常见的复杂参数传递的实例和技巧:

  1. 对象解构(Object Destructuring)

对象解构允许你从对象中提取多个属性,并将它们赋值给变量。

interface User {
    id: number;
    name: string;
    email: string;
}
 
function printUserInfo({ id, name, email }: User): void {
    console.log(`ID: ${id}, Name: ${name}, Email: ${email}`);
}
 
const user: User = { id: 1, name: "Alice", email: "alice@example.com" };
printUserInfo(user);
  1. 默认参数和可选参数

你可以为函数参数设置默认值,或者将参数标记为可选的。

function createUser(name: string, age: number = 18, email?: string): User {
    return {
        name,
        age,
        email: email || `${name.toLowerCase()}@example.com`
    };
}
 
const user1 = createUser("Bob");
const user2 = createUser("Alice", 25, "alice@example.com");
  1. 剩余参数(Rest Parameters)

剩余参数允许你将不定数量的参数作为数组传递。

function sum(...numbers: number[]): number {
    return numbers.reduce((total, num) => total + num, 0);
}
 
console.log(sum(1, 2, 3, 4, 5)); // 输出: 15
  1. 函数重载

函数重载允许你为同一个函数定义多个类型签名。

function processValue(value: number): number;
function processValue(value: string): string;
function processValue(value: number | string): number | string {
    if (typeof value === "number") {
        return value * 2;
    } else {
        return value.toUpperCase();
    }
}
 
console.log(processValue(5));      // 输出: 10
console.log(processValue("hello")); // 输出: HELLO
  1. 泛型

泛型允许你创建可重用的组件,这些组件可以与多种类型一起工作。

function identity<T>(arg: T): T {
    return arg;
}
 
let output1 = identity<string>("myString");
let output2 = identity<number>(100);
  1. 联合类型和类型守卫

联合类型允许一个值是多种类型之一,而类型守卫帮助你缩小类型范围。

type StringOrNumber = string | number;
 
function printLength(value: StringOrNumber): void {
    if (typeof value === "string") {
        console.log(value.length);
    } else {
        console.log(value.toString().length);
    }
}
 
printLength("hello");  // 输出: 5
printLength(12345);    // 输出: 5
  1. 交叉类型

交叉类型允许你组合多个类型。

interface Loggable {
    log(message: string): void;
}
 
interface Serializable {
    serialize(): string;
}
 
type LoggableAndSerializable = Loggable & Serializable;
 
function processObject(obj: LoggableAndSerializable): void {
    obj.log("Processing...");
    console.log(obj.serialize());
}
  1. 条件类型

条件类型允许你基于类型关系表达非均匀类型映射。

type TypeName<T> = 
    T extends string ? "string" :
    T extends number ? "number" :
    T extends boolean ? "boolean" :
    T extends undefined ? "undefined" :
    T extends Function ? "function" :
    "object";
 
type T0 = TypeName<string>;  // "string"
type T1 = TypeName<"a">;     // "string"
type T2 = TypeName<true>;    // "boolean"
type T3 = TypeName<() => void>;  // "function"
type T4 = TypeName<string[]>;    // "object"
  1. 映射类型

映射类型允许你从现有类型创建新类型。

type Readonly<T> = {
    readonly [P in keyof T]: T[P];
};
 
interface Point {
    x: number;
    y: number;
}
 
type ReadonlyPoint = Readonly<Point>;
 
const point: ReadonlyPoint = { x: 10, y: 20 };
// point.x = 5; // 错误:无法分配到 "x" ,因为它是只读属性。
  1. 索引类型和索引访问类型

索引类型查询和索引访问类型允许你使用动态属性名。

function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
    return obj[key];
}
 
const person = { name: "Alice", age: 25 };
const name: string = getProperty(person, "name");
const age: number = getProperty(person, "age");

这些复杂参数传递的实例展示了 TypeScript 强大的类型系统和它处理复杂场景的能力。通过使用这些特性,你可以创建更加类型安全、可读性更强、更易于维护的代码。在实际开发中,你可能会根据具体需求组合使用这些特性,以达到最佳的代码组织和类型检查效果。