Skip to content

TypeScript 函数类型

函数是 TypeScript 中的重要组成部分,本章节将介绍如何为函数添加类型注解,包括参数类型、返回值类型、可选参数、默认参数、剩余参数、函数重载等。

函数参数类型

为函数参数添加类型注解:

示例:

typescript
// 为参数添加类型注解
function add(a: number, b: number): number {
  return a + b;
}

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

// 调用函数
const sum = add(1, 2); // 3
const message = greet("John"); // Hello, John!

// 错误:参数类型不匹配
// add("1", 2); // 错误:Argument of type 'string' is not assignable to parameter of type 'number'

函数返回值类型

为函数返回值添加类型注解:

示例:

typescript
// 为返回值添加类型注解
function add(a: number, b: number): number {
  return a + b; // 正确:返回 number 类型
}

function greet(name: string): string {
  return `Hello, ${name}!`; // 正确:返回 string 类型
}

function isEven(num: number): boolean {
  return num % 2 === 0; // 正确:返回 boolean 类型
}

// 无返回值函数
function logMessage(message: string): void {
  console.log(message); // 正确:无返回值
}

// 错误:返回值类型不匹配
// function getNumber(): number {
//   return "42"; // 错误:Type 'string' is not assignable to type 'number'
// }

可选参数

使用 ? 符号标记可选参数:

示例:

typescript
// 可选参数
function greet(name: string, greeting?: string): string {
  if (greeting) {
    return `${greeting}, ${name}!`;
  }
  return `Hello, ${name}!`;
}

// 调用函数
console.log(greet("John")); // Hello, John!
console.log(greet("John", "Hi")); // Hi, John!

// 可选参数必须放在必选参数之后
// function greetOptional(greeting?: string, name: string): string { // 错误:必选参数不能位于可选参数之后
//   return `${greeting || "Hello"}, ${name}!`;
// }

默认参数

为参数设置默认值:

示例:

typescript
// 默认参数
function calculateTotal(price: number, tax: number = 0.08): number {
  return price + price * tax;
}

// 调用函数
console.log(calculateTotal(100)); // 108
console.log(calculateTotal(100, 0.1)); // 110

// 默认参数可以是表达式
function getDate(date: Date = new Date()): string {
  return date.toISOString();
}

console.log(getDate()); // 当前日期
console.log(getDate(new Date(2024, 0, 1))); // 2024-01-01T00:00:00.000Z

剩余参数

使用 ... 语法定义剩余参数:

示例:

typescript
// 剩余参数
function sum(...numbers: number[]): number {
  return numbers.reduce((acc, curr) => acc + curr, 0);
}

// 调用函数
console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4, 5)); // 15

// 混合使用普通参数和剩余参数
function concatenate(separator: string, ...strings: string[]): string {
  return strings.join(separator);
}

console.log(concatenate(", ", "a", "b", "c")); // a, b, c

函数重载

函数重载允许你为同一个函数定义多个签名:

示例:

typescript
// 函数重载签名
function process(value: string): string;
function process(value: number): number;
function process(value: boolean): boolean;

// 函数实现
function process(value: string | number | boolean): string | number | boolean {
  if (typeof value === "string") {
    return value.toUpperCase();
  } else if (typeof value === "number") {
    return value * 2;
  } else {
    return !value;
  }
}

// 调用函数
console.log(process("hello")); // HELLO
console.log(process(42)); // 84
console.log(process(true)); // false

// 错误:没有匹配的重载签名
// process(null); // 错误:No overload matches this call

箭头函数类型

为箭头函数添加类型注解:

示例:

typescript
// 箭头函数类型注解
const add = (a: number, b: number): number => {
  return a + b;
};

const greet = (name: string): string => `Hello, ${name}!`;

const isEven = (num: number): boolean => num % 2 === 0;

// 调用函数
console.log(add(1, 2)); // 3
console.log(greet("John")); // Hello, John!
console.log(isEven(4)); // true

// 箭头函数类型别名
type AddFunction = (a: number, b: number) => number;

const addNumbers: AddFunction = (a, b) => a + b;
console.log(addNumbers(5, 10)); // 15

实战:给工具函数加类型

示例 1:数组工具函数

typescript
// 数组工具函数

// 过滤数组
function filter<T>(array: T[], predicate: (item: T) => boolean): T[] {
  return array.filter(predicate);
}

// 映射数组
function map<T, U>(array: T[], mapper: (item: T) => U): U[] {
  return array.map(mapper);
}

// 查找元素
function find<T>(array: T[], predicate: (item: T) => boolean): T | undefined {
  return array.find(predicate);
}

// 使用
const numbers = [1, 2, 3, 4, 5];

const evenNumbers = filter(numbers, (num) => num % 2 === 0);
console.log(evenNumbers); // [2, 4]

const doubled = map(numbers, (num) => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]

const found = find(numbers, (num) => num > 3);
console.log(found); // 4

// 字符串数组
const strings = ["a", "b", "c", "d"];

const longStrings = filter(strings, (str) => str.length > 1);
console.log(longStrings); // []

const uppercased = map(strings, (str) => str.toUpperCase());
console.log(uppercased); // ["A", "B", "C", "D"]

示例 2:对象工具函数

typescript
// 对象工具函数

// 深拷贝对象
function deepClone<T>(obj: T): T {
  if (obj === null || typeof obj !== "object") {
    return obj;
  }
  
  if (obj instanceof Date) {
    return new Date(obj.getTime()) as T;
  }
  
  if (obj instanceof Array) {
    return obj.map((item) => deepClone(item)) as T;
  }
  
  const clonedObj = {} as T;
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      clonedObj[key] = deepClone(obj[key]);
    }
  }
  
  return clonedObj;
}

// 合并对象
function merge<T extends object, U extends object>(obj1: T, obj2: U): T & U {
  return { ...obj1, ...obj2 };
}

// 使用
const person = {
  name: "John",
  age: 30
};

const address = {
  street: "123 Main St",
  city: "New York"
};

const merged = merge(person, address);
console.log(merged); // { name: "John", age: 30, street: "123 Main St", city: "New York" }

const original = {
  name: "John",
  address: {
    street: "123 Main St",
    city: "New York"
  }
};

const cloned = deepClone(original);
original.address.city = "Boston";
console.log(cloned.address.city); // New York (深拷贝,不受影响)

小结

本章节介绍了 TypeScript 函数类型的使用,包括:

  • 函数参数类型
  • 函数返回值类型
  • 可选参数
  • 默认参数
  • 剩余参数
  • 函数重载
  • 箭头函数类型
  • 实战:给工具函数加类型

为函数添加类型注解可以提高代码的类型安全性和可维护性,特别是在大型项目中。通过为函数参数和返回值添加类型注解,你可以在编译时捕获类型错误,避免在运行时出现问题。

在实际开发中,应该为所有函数添加适当的类型注解,特别是公共 API 和工具函数,以提高代码的可读性和可维护性。

© 2026 编程马·菜鸟教程 版权所有