函数
本篇笔记我们介绍TypeScript中函数的定义、可选参数、默认参数、剩余参数、函数重载等相关内容。
函数的基本类型标注
TypeScript中,我们可以为函数的参数和返回值添加类型标注。下面是一个例子。
function add(a: number, b: number): number {
return a + b;
}
const result = add(1, 2); // result的类型为number
代码中,我们定义了一个add函数,它接收两个number类型的参数,并返回number类型的结果。TypeScript会在编译时检查参数和返回值的类型是否匹配,如果类型不匹配则会报错。
对于箭头函数,类型标注的方式类似。
const multiply = (a: number, b: number): number => {
return a * b;
};
当函数没有返回值时,我们使用void类型。
function logMessage(message: string): void {
console.log(message);
}
函数类型表达式
除了在函数定义时标注类型,我们还可以使用函数类型表达式来描述函数的类型,这在将函数作为参数传递或定义回调函数类型时非常有用。
type AddFn = (a: number, b: number) => number;
const add: AddFn = (a, b) => {
return a + b;
};
代码中,我们使用type关键字定义了一个函数类型AddFn,它描述了接收两个number参数并返回number的函数。随后我们用这个类型来标注add变量,此时函数实现中的参数类型也可以省略,TypeScript会自动推断。
函数类型表达式可以直接在参数中使用,下面是一个例子。
function executeOperation(a: number, b: number, operation: (x: number, y: number) => number): number {
return operation(a, b);
}
const result = executeOperation(10, 5, (x, y) => x - y);
可选参数和默认参数
TypeScript支持可选参数,使用?标记,注意可选参数必须放在必选参数之后。
function greet(name: string, greeting?: string): string {
if (greeting) {
return `${greeting}, ${name}!`;
}
return `Hello, ${name}!`;
}
greet("Tom"); // "Hello, Tom!"
greet("Tom", "Hi"); // "Hi, Tom!"
代码中,greeting是可选参数,调用时可以不传递该参数。需要注意的是,可选参数的类型实际上是string | undefined的联合类型。
默认参数则是在参数后使用=赋予默认值。
function greet(name: string, greeting: string = "Hello"): string {
return `${greeting}, ${name}!`;
}
greet("Tom"); // "Hello, Tom!"
greet("Tom", "Hi"); // "Hi, Tom!"
与可选参数不同,默认参数的类型不可能包含undefined,因为当传入undefined时会使用默认值。
剩余参数(不定数量参数)
当函数需要接收不定数量的参数时,可以使用剩余参数(Rest Parameters)。剩余参数使用...语法,其类型本质是一个数组。
function sum(...numbers: number[]): number {
return numbers.reduce((acc, cur) => acc + cur, 0);
}
sum(1, 2); // 3
sum(1, 2, 3, 4, 5); // 15
注意剩余参数必须是函数中的最后一个参数。
函数重载
JavaScript本身不支持函数重载,但TypeScript提供了函数重载的类型声明能力。函数重载允许我们为同一个函数定义多个类型签名,以处理不同的参数类型组合。
function parseValue(value: string): string[];
function parseValue(value: number): number;
function parseValue(value: string | number): string[] | number {
if (typeof value === "string") {
return value.split("");
}
return value * 2;
}
const strResult = parseValue("hello"); // 类型为string[]
const numResult = parseValue(10); // 类型为number
代码中,前两行是重载签名,它们声明了函数可以接受的不同参数类型及对应的返回类型。最后一个是实现签名,它必须兼容所有的重载签名。调用函数时,TypeScript会根据传入的参数类型选择匹配的重载签名,从而获得正确的返回类型。
注意:实现签名对外部调用者是不可见的,调用时只能使用重载签名中定义的参数类型。
this类型
在TypeScript中,我们可以显式声明函数中this的类型,this参数是一个特殊的伪参数,它必须放在参数列表的第一位。
interface User {
name: string;
greet(this: User): void;
}
const user: User = {
name: "Tom",
greet() {
console.log(`Hello, I'm ${this.name}`);
},
};
user.greet(); // "Hello, I'm Tom"
代码中,我们在greet方法中声明了this的类型为User,这样在方法内部访问this时就能获得正确的类型提示,同时TypeScript也会检查方法的调用方式是否正确。不过这个this参数仅用于类型检查,不会出现在实际运行时的参数列表中,也就是说,调用user.greet()时仍然不需要传任何参数。