Skip to content
第 4 章 前端 ⏱ 12 分钟阅读

第 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 注解,箭头函数继承外层

动手练习 ​

  1. 可选参数:createUser(name, age?, email?),age 和 email 可选
  2. 函数重载:reverse(x: string): string 和 reverse(x: number[]): number[]
  3. 箭头函数 vs 普通函数:写一个 Counter 类,用两种方式实现 inc(),观察 this 行为

下一章:第 5 章:接口 →

本站基于 VitePress 构建 · 由 StackHub 团队维护