类型注解入门
本教程共 80 篇 · 第 8 篇 · 更新于 2026-08-10 · 约 8 分钟阅读
本节目标:学会给变量和函数加上类型标注,理解 TypeScript 的类型推断机制,知道什么时候该写类型、什么时候可以省略。
什么是类型注解?
类型注解,就是在声明变量、函数参数、函数返回值时,用 : 类型 的语法告诉 TypeScript:“这个东西应该是这种类型”。
let name: string = "小明";
let age: number = 18;
let isStudent: boolean = true;
name: string 读作”name 是 string 类型”。冒号后面跟着的就是类型注解。
你可能会注意到,这跟 Java 或 C# 的写法不一样。那些语言通常把类型写在前面(String name = "小明"),TypeScript 把类型注解放在变量名后面。这个设计不是随便决定的——这样写能让类型注解成为”可选的”,不写类型时代码跟纯 JavaScript 几乎没有区别。
let 和 const 的类型推断差异
TypeScript 最厉害的地方在于,你大部分时候不需要写类型注解。编译器会根据你赋的值自动推断类型。
let message = "Hello"; // 推断为 string
let count = 42; // 推断为 number
let done = false; // 推断为 boolean
但 let 和 const 处理推断的方式不一样:
// let 声明:变量可以重新赋值,所以推断为"宽泛类型"
let name = "小明"; // 类型: string(宽泛)
name = "小红"; // ✅ 可以
// const 声明:值不可变,所以推断为"字面量类型"
const name2 = "小明"; // 类型: "小明"(精确到具体值)
// name2 = "小红"; // ❌ 报错:不能重新赋值
这个区分很重要。const 声明的是常量,TypeScript 知道它永远不会变,就把类型收紧到那个具体值。let 声明的变量随时可能被赋新值,TypeScript 保留宽泛的类型。这个行为直接影响后面要讲的联合类型和字面量类型。
什么时候写注解?什么时候靠推断?
这是初学者最头疼的问题。其实原则很简单:
靠推断就够了的情况:
// 初始值已经明确给出了类型信息
let score = 95; // number,推断就够了
let hobbies = ["读书", "跑步"]; // string[],推断就够了
const user = { name: "小明", age: 18 }; // { name: string; age: number }
必须写注解的情况:
// 1. 没有初始值的变量
let result: number;
// 后面才赋值
result = calculate();
// 2. 函数参数——函数参数没有初始值,必须标注
function greet(name: string) {
console.log(`你好,${name}!`);
}
// 3. 想要更精确的类型
let direction: "left" | "right" = "left"; // 不是 string,而是这俩值之一
// 4. 从 JSON 或 API 获取的数据
const data: UserProfile = JSON.parse(response);
Tip一个实用的经验法则:写函数签名时必写参数类型,变量声明时优先靠推断。等你发现推断的类型不对,再加注解也不迟。
函数注解:参数和返回值
函数是类型注解最常用的地方。参数类型写在参数名后面,返回值类型写在参数括号后面:
// 参数类型必写,返回值类型可推断
function add(a: number, b: number): number {
return a + b;
}
// 没有返回值,用 void
function log(message: string): void {
console.log(message);
}
// 异步函数返回 Promise
async function fetchUser(id: number): Promise<User> {
const response = await fetch(`/api/users/${id}`);
return response.json();
}
返回值类型其实可以不写——TypeScript 会根据 return 语句推断。但建议给公开的函数(给别人用的 API)写上返回值类型,它能帮你防止意外的变更。
// ❌ 不写返回值,某天重构时可能改错
function getStatus() {
return "ok";
// 某天不小心加了一行:return 200;
// TypeScript 不会报错,但返回类型变了
}
// ✅ 写了返回值,重构出错能被发现
function getStatus(): string {
return "ok";
// 如果改成 return 200,TypeScript 会提示类型错误
}
回调函数和上下文推断
另一个不需要写注解的场景是回调函数。当你把一个函数作为参数传递时,TypeScript 会根据调用方的类型签名自动推断回调的参数类型:
const names = ["小明", "小红", "小刚"];
// s 不用写类型——TypeScript 知道 names 是 string[],
// forEach 的回调参数自然就是 string
names.forEach((s) => {
console.log(s.toUpperCase()); // 自动补全 string 的方法
});
// 同样的效果在 map、filter、reduce 上也适用
const lengths = names.map((name) => name.length); // name 推断为 string
这种机制叫上下文类型推断(contextual typing)。回调函数的参数类型是由它被使用的位置决定的,你不需要手动标注。
基础类型速览
在深入学习每种类型之前,先快速过一遍你会用到的基础类型:
| 类型 | 说明 | 示例 |
|---|---|---|
string | 字符串 | "hello" |
number | 数字(整数浮点一体) | 42, 3.14 |
boolean | 布尔值 | true, false |
string[] | 字符串数组 | ["a", "b"] |
number[] | 数字数组 | [1, 2, 3] |
null | 空值 | null |
undefined | 未定义 | undefined |
any | 任意类型(跳过检查) | 任何值 |
unknown | 未知类型(安全版 any) | 任何值 |
void | 函数无返回值 | — |
我们会在接下来的章节逐个深入。
一段完整的示例
下面这个函数把本节讲的概念串在一起,你可以跑一下试试:
// 类型注解完整示例
// 变量:靠推断,不需要注解
const userName = "小明";
let userAge = 25;
// 函数:参数必写注解,返回值写了更安全
function formatUser(name: string, age: number): string {
return `${name}今年 ${age} 岁`;
}
// 对象:TS 会推断出完整结构
const user = {
name: "小明",
age: 25,
isAdmin: false
};
// 回调:TS 根据数组类型自动推断 item 的类型
const students = [
{ name: "小明", score: 95 },
{ name: "小红", score: 88 },
{ name: "小刚", score: 76 }
];
const highScorers = students.filter((student) => student.score >= 90);
console.log(formatUser(userName, userAge));
console.log("高分学生:", highScorers.map((s) => s.name).join("、"));
输出:
小明今年 25 岁
高分学生: 小明
小结
类型注解是 TypeScript 的基础语法,但别把它当成”必须手写所有类型”。TS 的类型推断非常强大,大部分变量和返回值都可以省略注解。把精力放在函数参数和那些推断不了的边界上。下一章我们开始逐个学习基础类型,先从最常见的 boolean、number、string 开始。