首页 / TypeScript 入门教程 / 函数类型基础

TypeScript 入门教程

函数类型基础

本教程共 80 篇 · 第 17 篇 · 更新于 2026-08-10 · 约 8 分钟阅读

TypeScriptTypeScript 入门教程函数类型类型标注void

本节目标:学会给函数参数和返回值加类型注解,理解 void 的用法,以及匿名函数如何自动推断类型。

TypeScript 对函数的类型检查主要集中在两个地方:参数的类型和返回值的类型。这两处写好之后,大多数由函数调用引发的 bug 就能在编译期被拦下。

参数类型注解

给参数加类型很简单,直接在参数名后面写 : 类型

function greet(name: string) {
  console.log("Hello, " + name);
}

greet("TypeScript"); // ✅
greet(42);           // ❌ 类型 "number" 的参数不能赋给类型 "string" 的参数

在 TypeScript 7.0 中,strict: true 是默认值。这意味着如果你不给参数加类型,编译器会报错——因为 strict 开启了 noImplicitAny,不允许隐式的 any 类型。

// strict: true(7.0 默认)
function greet(name) {
  //          ~~~~ 参数 "name" 隐式具有 "any" 类型
  console.log("Hello, " + name);
}

所以参数类型在 7.0 下基本上是必写的。这不是麻烦,是安全保障——相当于逼你把”这个参数是什么”想清楚。

返回值类型注解

返回值类型写在参数列表的圆括号后面:

function add(x: number, y: number): number {
  return x + y;
}

const result = add(3, 5); // result 的类型是 number

实际上 TypeScript 很擅长推断返回值类型,你就算不写 : number,它也能自己推断出来。那为什么还要写呢?两个原因:

  1. 文档作用——一眼就知道这个函数返回什么。
  2. 防止无意篡改——如果你不小心改了函数逻辑导致返回值类型变了,编译器会立刻提醒你。
// 不写返回值类型,TS 推断为 number
function multiply(a: number, b: number) {
  return a * b;
}

// 明确写出返回值类型
function divide(a: number, b: number): number {
  return a / b;
}
Tip

建议始终显式标注返回值类型,尤其是公开的 API 函数。这算是一种防御性编程——万一你后续改代码时不小心删掉了 return,编译器会替你发现。

void 返回

void 表示”这个函数不返回任何有意义的值”。

function logMessage(msg: string): void {
  console.log(msg);
  // 没有 return 语句
}

在 JavaScript 里,没有 return 的函数实际上会返回 undefined。但在 TypeScript 中,voidundefined 不是一回事。如果你显式写了 return 返回一个值,而函数签名标注了 void,编译器会报错:

function sayHello(): void {
  return "hello"; // ❌ 类型 "string" 不能赋给类型 "void"
}

不过有个特殊规则需要知道:当你把一个有返回值的函数赋值给 void 类型的回调位置时,TypeScript 不会报错。这是有意为之的——否则 Array.forEach 就没法用了,因为 push 之类的方法会返回 number

const src = [1, 2, 3];
const dst: number[] = [];

// forEach 要求回调返回 void,但 push 返回 number
// TypeScript 允许这样做
src.forEach((el) => dst.push(el));

这种设计让 TypeScript 保持了实用性——你不会因为一个 void 类型被卡住。

匿名函数与上下文类型推断

TypeScript 最聪明的一点是:当你把一个匿名函数传给一个已知类型的参数时,它会根据上下文自动推断匿名函数的参数类型。

const names = ["Alice", "Bob", "Charlie"];

// 你不需要给 name 加类型注解
names.forEach((name) => {
  console.log(name.toUpperCase());
  //          ~~~~ name 被推断为 string
});

forEach 的回调类型是 (value: string, index: number, array: string[]) => void。TypeScript 知道 namesstring[],所以自动推断 namestring。这就是”上下文类型推断”——参数的类型由函数所在的上下文决定,不需要你自己写。

再比如 map

const lengths = names.map((name) => name.length);
//                          ~~~~ name: string
// lengths 的类型被推断为 number[]

你连返回值类型都没写,TypeScript 全帮你推出来了。这种推断在回调嵌套时特别省事——不用每层都写一遍类型。

Note

上下文类型推断只对匿名函数有效。如果你把函数单独定义再传进去,参数类型就不会自动推断,需要你自己写注解。

// 单独定义的函数,参数需要显式标注类型
function getNameLength(name: string): number {
  return name.length;
}

const lengths = names.map(getNameLength); // 没问题,因为 getNameLength 已经有类型

// 但如果定义时不写类型
function getNameLength2(name) {
  //                     ~~~~ 隐式 any,strict 下报错
  return name.length;
}

这个规则的核心是:匿名函数可以靠上下文推断,命名函数需要自己负责类型。两种方式各有用处——简单回调用匿名省事,复杂逻辑用命名函数更清晰。

小结

这一节涵盖了函数类型最基础的三个概念:参数类型、返回值类型、void。再加上上下文类型推断,你已经可以写出类型安全的函数了。下一节会深入函数参数的各种花样——可选参数、默认值、剩余参数和解构。