首页/2

2章:给博客加上类型:基础类型实战

为博客文章定义类型

45分钟
4个学习目标

学习目标

  • 1掌握TypeScript的基础类型
  • 2学会为变量和函数添加类型注解
  • 3理解类型推断的工作原理
  • 4为博客项目定义完整的类型系统

上一章我们做了什么

在上一章中,我们创建了博客项目,并用一个简单的Post接口定义了文章的结构。

但你可能注意到了一个问题:我们的类型太简单了。一个真正的博客系统需要:

  • 不同状态的文章(草稿、已发布、已归档)
  • 多种标签
  • 浏览次数统计
  • 作者信息

这一章,我们会学习TypeScript的基础类型,然后用它们来完善博客的类型系统。

问题:为什么需要类型?

想象一下这个场景:你在写一个函数来显示文章的发布日期。

JavaScript版本:

function showDate(date) {
  return date.toLocaleDateString();
}

showDate("2024-01-01"); // 可能正常工作
showDate(1234567890);   // 返回一个奇怪的日期
showDate(null);          // 报错!

JavaScript不会告诉你传入的参数类型不对,直到运行时才会出错。

TypeScript版本:

function showDate(date: Date): string {
  return date.toLocaleDateString();
}

showDate("2024-01-01"); // 编译时报错!类型"string"不能赋值给"Date"

TypeScript在你写代码时就能发现问题,而不是等到用户使用时才出错。这就是类型安全的价值。

基础类型一览

TypeScript提供了几种基础类型,就像积木一样,我们可以用它们来构建复杂的类型。

原始类型(最基础的积木):

| 类型 | 说明 | 示例 | |------|------|------| | string | 字符串 | "hello" | | number | 数字 | 42, 3.14 | | boolean | 布尔值 | true, false | | null | 空值 | null | | undefined | 未定义 | undefined |

特殊类型:

| 类型 | 说明 | 何时使用 | |------|------|----------| | any | 任意类型 | 尽量避免使用 | | void | 无返回值 | 函数不返回东西时 | | never | 永不返回 | 函数总是抛出错误时 | | unknown | 未知类型 | 比any更安全的替代品 |

复合类型(用积木搭建的复杂结构):

| 类型 | 说明 | 示例 | |------|------|------| | 数组 | 同类型集合 | number[], Array<string> | | 元组 | 固定长度和类型 | [string, number] | | 枚举 | 命名常量 | enum Status { Active } |

在博客中使用基础类型

typescript
加载中...

类型注解 vs 类型推断

TypeScript有两种方式确定变量的类型:

1. 类型注解(手动指定)

const title: string = "我的博客";

你明确告诉TypeScript:这个变量是string类型。

2. 类型推断(自动推断)

const title = "我的博客"; // TypeScript自动推断为string

TypeScript根据赋的值自动推断类型。

什么时候用哪种?

| 场景 | 建议 | |------|------| | 变量初始化时就有值 | 可以省略,让TS推断 | | 函数参数 | 必须手动指定 | | 函数返回值 | 建议手动指定 | | 类型不明显时 | 手动指定 |

一个原则: 当类型明显时,可以省略注解;当类型不明显或需要明确时,添加注解。

类型推断的实际应用

typescript
加载中...

枚举:定义文章状态

在博客系统中,文章有不同的状态:草稿、已发布、已归档。我们可以用枚举来定义这些状态。

枚举是什么?

枚举就像一个菜单,列出了所有可能的选项。比如餐厅的菜单上有"红烧肉"、"宫保鸡丁"、"鱼香肉丝"——你只能从这些选项中选择。

为什么用枚举?

  1. 避免拼写错误:"published" 容易拼错,Status.Published 不会
  2. 代码提示:IDE会自动显示所有选项
  3. 集中管理:修改状态值只需要改一处

用枚举定义文章状态

typescript
加载中...

完善博客的类型系统

现在我们有了足够的知识来完善博客的类型系统。

我们需要定义:

  1. 文章状态(枚举)
  2. 文章接口(包含所有属性)
  3. 创建/更新文章的输入类型

设计原则:

  • 只读属性用 readonly 标记
  • 可选属性用 ? 标记
  • 自动生成的字段(如id、createdAt)不放在输入类型中

完整的博客类型定义

typescript
加载中...

常见错误

学习类型系统时,初学者常犯以下错误:

错误1:过度使用any

// 不推荐
let data: any = "hello";
data = 42; // 不会报错,但可能不是你想要的

// 推荐
let data: string | number = "hello";
data = 42; // 明确允许string或number

错误2:忘记数组类型

// 不推荐
const tags = []; // 类型是 any[]

// 推荐
const tags: string[] = [];

错误3:混淆null和undefined

// null:明确表示"没有值"
const title: string | null = null;

// undefined:表示"未定义"
const title: string | undefined = undefined;

动手实践

现在轮到你了!让我们为博客添加更多的类型定义。

练习1:定义用户类型 为博客系统定义一个User接口,包含:

  • id: string
  • name: string
  • email: string
  • avatar?: string(可选)
  • bio?: string(可选)

练习2:定义评论类型 为博客系统定义一个Comment接口,包含:

  • id: string
  • postId: string(关联的文章ID)
  • content: string
  • authorName: string
  • createdAt: Date

练习3:使用枚举 定义一个CommentStatus枚举,包含:

  • Pending(待审核)
  • Approved(已批准)
  • Rejected(已拒绝)

练习参考答案

typescript
加载中...

本章小结

这一章我们学习了:

1. 基础类型

  • string、number、boolean:最常用的原始类型
  • null、undefined:表示空值
  • any、unknown:特殊类型,尽量避免any

2. 类型注解 vs 类型推断

  • 类型注解:手动指定类型
  • 类型推断:TypeScript自动推断
  • 函数参数必须手动指定类型

3. 枚举

  • 用于定义一组命名常量
  • 避免拼写错误,提供代码提示

4. 完善的类型系统

  • Post接口:文章的完整结构
  • CreatePostInput:创建文章时的输入
  • UpdatePostInput:更新文章时的输入

下一章预告:

在下一章中,我们会学习接口的更多特性:

  • 接口继承
  • 可选属性和只读属性
  • 函数类型接口

这些特性会让我们博客的类型系统更加强大!

交互式练习

1 / 1

类型注解练习

为变量添加正确的类型注解

typescript
Loading...

章节测验

问题 1 / 4得分: 0 / 4

以下哪个是TypeScript的基础类型?

A
int
B
float
C
number
D
double