如何在30分钟内用TypeScript编写REST API:实战指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么TypeScript和REST API是快速开发的理想组合

\n

现代Web开发需要速度和可靠性。如果你需要快速为移动应用、Web服务或微服务架构构建后端,TypeScript + Node.js + Express 组合是最有效的工具之一。TypeScript为JavaScript增加了严格的类型检查,让你能在编译阶段而非运行时捕获错误。这在构建REST API时尤其有价值,因为每个端点都需要清楚知道它接收和返回什么数据。

\n

在本文中,我们将在30分钟内创建一个用于管理任务列表(To-Do List)的完整REST API。你将学习如何配置项目、编写控制器、路由和中间件。所有内容都基于包含完整代码的实战示例。

\n\n

项目准备与配置(5分钟)

\n

首先,创建项目结构并安装依赖。

\n
mkdir todo-api\ncd todo-api\nnpm init -y\nnpm install express cors uuid\nnpm install -D typescript @types/express @types/cors @types/uuid ts-node nodemon
\n

在项目根目录创建 tsconfig.json 文件:

\n
{\n  "compilerOptions": {\n    "target": "ES2020",\n    "module": "commonjs",\n    "outDir": "./dist",\n    "rootDir": "./src",\n    "strict": true,\n    "esModuleInterop": true,\n    "skipLibCheck": true\n  },\n  "include": ["src/**/*"]\n}
\n

在 package.json 中添加脚本:

\n
"scripts": {\n  "dev": "nodemon --exec ts-node src/index.ts",\n  "build": "tsc",\n  "start": "node dist/index.js"\n}
\n

创建 src 文件夹和入口文件 index.ts。

\n\n

基本文件夹结构

\n
    \n
  • src/index.ts — 入口文件,启动服务器
  • \n
  • src/routes/tasks.ts — 任务路由
  • \n
  • src/controllers/taskController.ts — 请求处理逻辑
  • \n
  • src/models/task.ts — 接口和类型定义
  • \n
  • src/middleware/errorHandler.ts — 错误处理(可选)
  • \n
\n\n

创建数据模型和接口(5分钟)

\n

为任务定义数据类型。创建文件 src/models/task.ts:

\n
export interface Task {\n  id: string;\n  title: string;\n  completed: boolean;\n  createdAt: Date;\n}\n\nexport type CreateTaskDto = Pick<Task, 'title'>;\nexport type UpdateTaskDto = Partial<Pick<Task, 'title' | 'completed'>>;
\n

这里我们使用了 Pick 和 Partial —— TypeScript 内置的工具类型。CreateTaskDto 只接受标题,而 UpdateTaskDto 包含用于部分更新的可选字段。

\n\n

编写控制器和路由(15分钟)

\n

现在进入最有趣的部分——应用逻辑。我们将创建一个内存中的临时任务存储。生产环境中应替换为数据库。

\n\n

任务控制器

\n

文件 src/controllers/taskController.ts:

\n
import { Request, Response } from 'express';\nimport { v4 as uuidv4 } from 'uuid';\nimport { Task, CreateTaskDto, UpdateTaskDto } from '../models/task';\n\n// 临时存储\nlet tasks: Task[] = [];\n\n// GET /api/tasks\nexport const getAllTasks = (req: Request, res: Response) => {\n  res.json(tasks);\n};\n\n// GET /api/tasks/:id\nexport const getTaskById = (req: Request, res: Response) => {\n  const task = tasks.find(t => t.id === req.params.id);\n  if (!task) {\n    return res.status(404).json({ message: '任务未找到' });\n  }\n  res.json(task);\n};\n\n// POST /api/tasks\nexport const createTask = (req: Request, res: Response) => {\n  const { title } = req.body as CreateTaskDto;\n  if (!title || typeof title !== 'string') {\n    return res.status(400).json({ message: 'title 字段为必填项,且必须为字符串' });\n  }\n                

博客

书籍推荐