第 4 章:函数
学习目标
- 定义有类型的函数(参数、返回值)
- 学会可选参数、默认参数、剩余参数
- 掌握函数重载
- 理解 this 类型与箭头函数
一、函数声明与表达式
typescript
// 函数声明(具名)
function add(a: number, b: number): number {
return a + b;
}
// 函数表达式(匿名,需要类型注解)
const subtract: (a: number, b: number) => number = (a, b) => a - b;
// 类型别名(更清晰)
type MathFn = (a: number, b: number) => number;
const multiply: MathFn = (a, b) => a * b;⚠️ 坑 1:函数表达式的类型必须写在变量上,不能写
(a: number, b: number) => number在函数本身,否则 TS 会推导出函数表达式返回的"具体值"。
二、参数类型
必选参数
typescript
function greet(name: string): string {
return `Hello, ${name}`;
}
greet(); // ❌ Expected 1 argument, but got 0可选参数(用 ?)
typescript
function greet(name: string, prefix?: string): string {
return `${prefix ?? 'Hi'}, ${name}`;
}
greet('Tom', 'Hello'); // 'Hello, Tom'
greet('Tom'); // 'Hi, Tom'(prefix 是 undefined)⚠️ 坑 2:可选参数必须在必选参数后面,不能
prefix?: string, name: string这样写。
默认参数
typescript
function greet(name: string, prefix: string = 'Hi'): string {
return `${prefix}, ${name}`;
}
greet('Tom'); // 'Hi, Tom'
greet('Tom', 'Hello'); // 'Hello, Tom'剩余参数(Rest)
typescript
function sum(...nums: number[]): number {
return nums.reduce((acc, n) => acc + n, 0);
}
sum(1, 2, 3, 4); // 10三、返回值类型
typescript
// 显式声明
function add(a: number, b: number): number {
return a + b;
}
// void:无返回值
function log(msg: string): void {
console.log(msg);
}
// never:永不返回
function throwErr(): never {
throw new Error('崩了');
}⚠️ 坑 3:TS 会根据
return自动推断返回值,但建议显式写,便于阅读和维护。
四、函数类型作为参数
typescript
type Callback = (result: number) => void;
function calc(a: number, b: number, cb: Callback): void {
const result = a + b;
cb(result);
}
calc(1, 2, (r) => console.log(r)); // 3五、函数重载(Overload)
typescript
// 重载签名
function padLeft(input: string, padding: string | number): string;
function padLeft(input: string, ...padding: string[]): string;
// 实现签名(必须兼容所有重载,参数最宽松)
function padLeft(input: string, padding: string | number | string[]): string {
if (typeof padding === 'number') {
return ' '.repeat(padding) + input;
}
if (Array.isArray(padding)) {
return padding.join('') + input;
}
return padding + input;
}
padLeft('Tom', 4); // ' Tom'
padLeft('Tom', '>>'); // '>>Tom'
padLeft('Tom', 'a', 'b'); // 'abTom'六、箭头函数与 this
typescript
interface User {
name: string;
greet: () => void;
}
const user: User = {
name: 'Tom',
greet: function (this: User) { // 显式 this 类型
console.log(this.name); // ✅ 类型安全
},
};
// 箭头函数的 this 来自外层
class Counter {
count = 0;
inc = (): void => {
this.count++; // ✅ 箭头函数捕获外层 this
};
}⚠️ 坑 4:箭头函数没有自己的 this,不能用作构造函数(没有
new),也不能用this参数语法。
七、构造函数签名
typescript
interface Constructable {
new (name: string): { name: string };
}
class Person {
constructor(public name: string) {}
}
function create(Ctor: Constructable, name: string): { name: string } {
return new Ctor(name);
}八、泛型函数(预告)
typescript
function identity<T>(arg: T): T {
return arg;
}
const num = identity(42); // 推断 T = number
const str = identity('Tom'); // 推断 T = string九、本章小结
| 要点 | 关键 |
|---|---|
| 参数类型 | 必选、可选(?)、默认、剩余(...) |
| 返回类型 | 显式声明,可推断;void 无返回值,never 永不返回 |
| 函数类型 | (a: T) => R 或 type Fn = ... |
| 重载 | 多个签名 + 一个实现,实现要兼容所有重载 |
| this | 普通函数可用 this: Type 注解,箭头函数继承外层 |
动手练习
- 可选参数:
createUser(name, age?, email?),age 和 email 可选 - 函数重载:
reverse(x: string): string和reverse(x: number[]): number[] - 箭头函数 vs 普通函数:写一个
Counter类,用两种方式实现inc(),观察this行为
下一章:第 5 章:接口 →