跳到主要内容

TypeScript 函数

函数是 JavaScript 的核心构建块,TypeScript 为函数添加了类型支持。

函数类型

基本类型注解

// 函数声明
function add(a: number, b: number): number {
return a + b;
}

// 函数表达式
const multiply = function(a: number, b: number): number {
return a * b;
};

// 箭头函数
const divide = (a: number, b: number): number => {
return a / b;
};

// 简写箭头函数
const square = (n: number): number => n * n;

解释:参数列表中的每个参数都需要类型注解,返回值类型可以省略(TypeScript 会自动推断)。

函数类型表达式

// 定义函数类型
type MathOperation = (a: number, b: number) => number;

// 使用函数类型
const subtract: MathOperation = (a, b) => a - b;
const power: MathOperation = (a, b) => a ** b;

// 作为参数类型
function calculate(a: number, b: number, operation: MathOperation): number {
return operation(a, b);
}

calculate(10, 5, subtract); // 5
calculate(2, 3, power); // 8

参数类型

可选参数

function greet(name: string, greeting?: string): string {
if (greeting) {
return `${greeting}, ${name}!`;
}
return `Hello, ${name}!`;
}

greet("张三"); // "Hello, 张三!"
greet("张三", "你好"); // "你好, 张三!"

解释:可选参数使用 ? 标记,必须放在必需参数之后。

默认参数

function greet(name: string, greeting: string = "Hello"): string {
return `${greeting}, ${name}!`;
}

greet("张三"); // "Hello, 张三!"
greet("张三", "你好"); // "你好, 张三!"

// 默认参数不需要放在最后
function createPoint(x: number, y = 0, z = 0): [number, number, number] {
return [x, y, z];
}

解释:默认参数在调用时可以省略,默认参数会自动推断类型,无需显式注解。

剩余参数

function sum(...numbers: number[]): number {
return numbers.reduce((total, n) => total + n, 0);
}

sum(1, 2, 3); // 6
sum(1, 2, 3, 4, 5); // 15

// 结合其他参数
function log(level: string, ...messages: string[]): void {
console.log(`[${level}]`, ...messages);
}

log("INFO", "服务器启动", "端口 3000");
// [INFO] 服务器启动 端口 3000

解构参数

interface Point {
x: number;
y: number;
}

// 解构对象参数
function printPoint({ x, y }: Point): void {
console.log(`(${x}, ${y})`);
}

printPoint({ x: 10, y: 20 }); // "(10, 20)"

// 解构数组参数
function printCoordinates([x, y]: [number, number]): void {
console.log(`X: ${x}, Y: ${y}`);
}

printCoordinates([10, 20]); // "X: 10, Y: 20"

函数重载

函数重载允许同一个函数接受不同类型或数量的参数。

基本重载

// 重载签名
function convert(value: number): string;
function convert(value: string): number;
function convert(value: boolean): string;

// 实现签名
function convert(value: number | string | boolean): string | number {
if (typeof value === "number") {
return value.toString();
} else if (typeof value === "string") {
return parseInt(value, 10);
} else {
return value ? "true" : "false";
}
}

// 使用
const numStr: string = convert(123); // "123"
const strNum: number = convert("456"); // 456
const boolStr: string = convert(true); // "true"

解释:重载签名定义函数的不同调用方式,实现签名必须兼容所有重载签名。

实际应用示例

// 创建元素
function createElement(tag: "a"): HTMLAnchorElement;
function createElement(tag: "canvas"): HTMLCanvasElement;
function createElement(tag: "table"): HTMLTableElement;
function createElement(tag: string): HTMLElement;
function createElement(tag: string): HTMLElement {
return document.createElement(tag);
}

// 事件处理
function on(element: HTMLElement, event: "click", handler: (e: MouseEvent) => void): void;
function on(element: HTMLElement, event: "input", handler: (e: Event) => void): void;
function on(element: HTMLElement, event: string, handler: (e: Event) => void): void {
element.addEventListener(event, handler);
}

方法重载

class Calculator {
// 重载:不同参数数量
add(a: number, b: number): number;
add(a: number, b: number, c: number): number;
add(a: number, b: number, c?: number): number {
if (c !== undefined) {
return a + b + c;
}
return a + b;
}
}

const calc = new Calculator();
calc.add(1, 2); // 3
calc.add(1, 2, 3); // 6

this 类型

指定 this 类型

interface User {
name: string;
greet(this: User): void;
}

const user: User = {
name: "张三",
greet() {
console.log(`Hello, I'm ${this.name}`);
}
};

user.greet(); // "Hello, I'm 张三"

// const greetFn = user.greet;
// greetFn(); // 错误:this 必须是 User 类型

解释:使用 this 参数可以确保方法在正确的上下文中调用。

箭头函数保留 this

class Person {
constructor(private name: string) {}

// 普通方法 - this 可能丢失
greetNormal() {
console.log(`Hello, I'm ${this.name}`);
}

// 箭头函数 - this 绑定到实例
greetArrow = () => {
console.log(`Hello, I'm ${this.name}`);
};
}

const person = new Person("张三");
const { greetNormal, greetArrow } = person;

// greetNormal(); // 错误:this 是 undefined
greetArrow(); // "Hello, I'm 张三"

返回类型

显式返回类型

// 显式声明返回类型
function createPoint(x: number, y: number): { x: number; y: number } {
return { x, y };
}

// 使用接口
interface Point {
x: number;
y: number;
}

function createPoint2(x: number, y: number): Point {
return { x, y };
}

返回类型推断

// TypeScript 自动推断返回类型
function add(a: number, b: number) {
return a + b; // 推断为 number
}

// 复杂类型推断
function getUser() {
return {
name: "张三",
age: 25
};
// 推断为 { name: string; age: number; }
}

void 返回类型

// 没有返回值的函数
function log(message: string): void {
console.log(message);
}

// 可以返回 undefined 或 null(非严格模式)
function doNothing(): void {
return undefined;
}

never 返回类型

// 永远不会正常返回
function fail(message: string): never {
throw new Error(message);
}

function infiniteLoop(): never {
while (true) {}
}

函数作为值

回调函数

// 定义回调类型
type Callback = (data: string) => void;

function fetchData(url: string, callback: Callback): void {
// 模拟异步获取数据
setTimeout(() => {
callback("获取的数据");
}, 1000);
}

fetchData("/api/data", (data) => {
console.log(data);
});

高阶函数

// 接受函数,返回函数
function debounce<T extends (...args: any[]) => any>(
func: T,
wait: number
): (...args: Parameters<T>) => void {
let timeout: ReturnType<typeof setTimeout>;
return function(...args: Parameters<T>) {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), wait);
};
}

// 使用
const debouncedLog = debounce((message: string) => {
console.log(message);
}, 300);

函数类型推断

参数类型推断

// 泛型函数 - 类型推断
function identity<T>(arg: T): T {
return arg;
}

const str = identity("hello"); // T 推断为 string
const num = identity(123); // T 推断为 number

// 显式指定类型
const explicit = identity<string>("hello");

条件返回类型

function getValue<T extends string | number>(
value: T
): T extends string ? string : number {
return value as any;
}

const strResult = getValue("hello"); // string
const numResult = getValue(123); // number

小结

本章我们学习了 TypeScript 函数:

  1. 函数类型注解
  2. 可选参数、默认参数、剩余参数
  3. 参数解构
  4. 函数重载
  5. this 类型
  6. 返回类型(void、never)
  7. 函数作为值传递

练习

  1. 定义一个函数,接受可选的问候语参数
  2. 实现一个函数重载,接受字符串或数组并返回其长度
  3. 创建一个高阶函数,实现节流功能
  4. 定义一个事件处理函数类型