首页 / TypeScript 入门教程 / 类型注解入门

TypeScript 入门教程

类型注解入门

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

TypeScriptTypeScript 入门教程类型注解类型推断基础类型

本节目标:学会给变量和函数加上类型标注,理解 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

letconst 处理推断的方式不一样:

// 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 的类型推断非常强大,大部分变量和返回值都可以省略注解。把精力放在函数参数和那些推断不了的边界上。下一章我们开始逐个学习基础类型,先从最常见的 booleannumberstring 开始。