TypeScript 提供了多种方式来处理复杂的参数传递。以下是一些常见的复杂参数传递的实例和技巧:
- 对象解构(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);- 默认参数和可选参数
你可以为函数参数设置默认值,或者将参数标记为可选的。
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");- 剩余参数(Rest Parameters)
剩余参数允许你将不定数量的参数作为数组传递。
function sum(...numbers: number[]): number {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 输出: 15- 函数重载
函数重载允许你为同一个函数定义多个类型签名。
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- 泛型
泛型允许你创建可重用的组件,这些组件可以与多种类型一起工作。
function identity<T>(arg: T): T {
return arg;
}
let output1 = identity<string>("myString");
let output2 = identity<number>(100);- 联合类型和类型守卫
联合类型允许一个值是多种类型之一,而类型守卫帮助你缩小类型范围。
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- 交叉类型
交叉类型允许你组合多个类型。
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());
}- 条件类型
条件类型允许你基于类型关系表达非均匀类型映射。
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"- 映射类型
映射类型允许你从现有类型创建新类型。
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" ,因为它是只读属性。- 索引类型和索引访问类型
索引类型查询和索引访问类型允许你使用动态属性名。
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 强大的类型系统和它处理复杂场景的能力。通过使用这些特性,你可以创建更加类型安全、可读性更强、更易于维护的代码。在实际开发中,你可能会根据具体需求组合使用这些特性,以达到最佳的代码组织和类型检查效果。