Ts.ED框架入门指南:从零开始构建TypeScript服务端应用

Ts.ED框架入门指南:从零开始构建TypeScript服务端应用

【免费下载链接】tsed :triangular_ruler: Ts.ED is a Node.js and TypeScript framework on top of Express to write your application with TypeScript (or ES6). It provides a lot of decorators and guideline to make your code more readable and less error-prone. ⭐️ Star to support our work! 【免费下载链接】tsed 项目地址: https://gitcode.com/gh_mirrors/ts/tsed

引言:为什么选择Ts.ED?

还在为Node.js服务端开发的配置繁琐、类型安全问题而烦恼吗?Ts.ED(TypeScript Express Decorators)框架为你提供了一站式解决方案!作为基于TypeScript和Express构建的现代化Node.js框架,Ts.ED通过装饰器(Decorators)和依赖注入(Dependency Injection)等高级特性,让服务端开发变得简单、优雅且类型安全。

通过本文,你将掌握:

  • ✅ Ts.ED框架的核心概念和架构设计
  • ✅ 从零搭建完整的RESTful API服务
  • ✅ 使用装饰器简化路由和参数处理
  • ✅ 依赖注入实现松耦合的业务逻辑
  • ✅ 自动生成OpenAPI文档的最佳实践
  • ✅ 项目结构和配置的规范化管理

环境准备与项目初始化

系统要求

在开始之前,请确保你的开发环境满足以下要求:

组件最低版本推荐版本
Node.js20.11.022.x
TypeScript5.0.05.5.0
npm8.0.010.x

使用CLI快速创建项目

Ts.ED提供了强大的命令行工具,可以快速初始化项目结构:

# 使用npx创建新项目
npx -p @tsed/cli tsed init my-tsed-app

# 或者使用yarn
yarn dlx -p @tsed/cli tsed init my-tsed-app

# 进入项目目录
cd my-tsed-app

CLI工具会引导你完成项目配置:

mermaid

项目结构解析

初始化完成后,你会看到以下标准的项目结构:

my-tsed-app/
├── src/
│   ├── controllers/     # 控制器层
│   ├── services/       # 服务层
│   ├── models/         # 数据模型
│   ├── middlewares/    # 中间件
│   ├── config/         # 配置文件
│   └── Server.ts       # 服务器入口
├── tests/              # 测试文件
├── package.json
└── tsconfig.json

核心概念深度解析

装饰器:框架的灵魂

Ts.ED大量使用TypeScript装饰器来简化代码编写。以下是核心装饰器的功能对比:

装饰器类别常用装饰器功能描述使用场景
控制器装饰器@Controller定义控制器类组织路由端点
路由装饰器@Get, @Post定义HTTP方法处理特定请求
参数装饰器@BodyParams, @QueryParams提取请求参数参数自动绑定
服务装饰器@Injectable, @Inject依赖注入管理业务逻辑解耦
模型装饰器@Property, @Required数据模型定义数据验证和序列化

依赖注入:松耦合的基石

Ts.ED内置了强大的依赖注入容器,基于@tsed/di包实现:

import { Injectable, Inject } from "@tsed/di";

@Injectable()
export class UserService {
  async findById(id: string) {
    // 业务逻辑实现
    return { id, name: "示例用户" };
  }
}

@Controller("/users")
export class UsersController {
  @Inject()
  private userService: UserService;

  @Get("/:id")
  async getUser(@PathParams("id") id: string) {
    return this.userService.findById(id);
  }
}

实战:构建完整的RESTful API

步骤1:定义数据模型

首先创建用户数据模型,包含验证规则:

import { Property, Required, MinLength, MaxLength, Groups } from "@tsed/schema";

export class UserModel {
  @Property()
  id: string;

  @Required()
  @MinLength(3)
  @MaxLength(50)
  @Property()
  name: string;

  @Required()
  @Email()
  @Property()
  email: string;

  @Property()
  @Format("date-time")
  createdAt: Date;

  @Groups("!creation") // 创建时排除此字段
  @Property()
  updatedAt: Date;
}

步骤2:创建业务服务

实现用户服务的核心业务逻辑:

import { Injectable } from "@tsed/di";
import { UserModel } from "../models/UserModel";

@Injectable()
export class UserService {
  private users: Map<string, UserModel> = new Map();

  async create(userData: Partial<UserModel>): Promise<UserModel> {
    const user = new UserModel();
    user.id = this.generateId();
    user.name = userData.name!;
    user.email = userData.email!;
    user.createdAt = new Date();
    user.updatedAt = new Date();

    this.users.set(user.id, user);
    return user;
  }

  async findById(id: string): Promise<UserModel | null> {
    return this.users.get(id) || null;
  }

  async findAll(): Promise<UserModel[]> {
    return Array.from(this.users.values());
  }

  async update(id: string, updates: Partial<UserModel>): Promise<UserModel | null> {
    const user = await this.findById(id);
    if (!user) return null;

    Object.assign(user, updates, { updatedAt: new Date() });
    return user;
  }

  async delete(id: string): Promise<boolean> {
    return this.users.delete(id);
  }

  private generateId(): string {
    return Math.random().toString(36).substring(2) + Date.now().toString(36);
  }
}

步骤3:实现控制器

创建用户控制器,处理HTTP请求:

import { 
  Controller, Get, Post, Put, Delete, 
  BodyParams, PathParams, QueryParams, 
  Returns, Summary, Status 
} from "@tsed/schema";
import { Inject } from "@tsed/di";
import { UserService } from "../services/UserService";
import { UserModel } from "../models/UserModel";

@Controller("/users")
@Summary("用户管理API")
export class UsersController {
  @Inject()
  private userService: UserService;

  @Get("/")
  @Summary("获取所有用户")
  @Returns(200, Array).Of(UserModel)
  async getAllUsers() {
    return this.userService.findAll();
  }

  @Get("/:id")
  @Summary("根据ID获取用户")
  @Returns(200, UserModel)
  @Returns(404).Description("用户不存在")
  async getUserById(@PathParams("id") id: string) {
    const user = await this.userService.findById(id);
    if (!user) {
      throw new NotFound("用户不存在");
    }
    return user;
  }

  @Post("/")
  @Status(201)
  @Summary("创建新用户")
  @Returns(201, UserModel)
  async createUser(@BodyParams() @Groups("creation") userData: UserModel) {
    return this.userService.create(userData);
  }

  @Put("/:id")
  @Summary("更新用户信息")
  @Returns(200, UserModel)
  @Returns(404).Description("用户不存在")
  async updateUser(
    @PathParams("id") id: string,
    @BodyParams() updates: Partial<UserModel>
  ) {
    const user = await this.userService.update(id, updates);
    if (!user) {
      throw new NotFound("用户不存在");
    }
    return user;
  }

  @Delete("/:id")
  @Status(204)
  @Summary("删除用户")
  @Returns(204)
  @Returns(404).Description("用户不存在")
  async deleteUser(@PathParams("id") id: string) {
    const deleted = await this.userService.delete(id);
    if (!deleted) {
      throw new NotFound("用户不存在");
    }
  }
}

步骤4:配置服务器

配置主服务器文件,挂载控制器和中间件:

import { Configuration } from "@tsed/di";
import "@tsed/platform-express";
import "@tsed/swagger";
import "@tsed/ajv";
import { config } from "./config/index";
import * as rest from "./controllers/rest/index";

@Configuration({
  ...config,
  port: process.env.PORT || 3000,
  mount: {
    "/api": [
      ...Object.values(rest)
    ]
  },
  swagger: [
    {
      path: "/docs",
      specVersion: "3.0.1"
    }
  ],
  middlewares: [
    "cookie-parser",
    "compression", 
    "method-override",
    "json-parser",
    "urlencoded-parser"
  ],
  ajv: {
    returnsCoercion: true
  }
})
export class Server {}

步骤5:启动应用

创建应用启动入口文件:

import { $log } from "@tsed/logger";
import { PlatformExpress } from "@tsed/platform-express";
import { Server } from "./Server";

async function bootstrap() {
  try {
    $log.info("启动服务器...");
    const platform = await PlatformExpress.bootstrap(Server);
    
    await platform.listen();
    $log.info("服务器初始化完成");
    $log.info(`API文档地址: http://localhost:3000/docs`);
    $log.info(`健康检查地址: http://localhost:3000/rest/health`);
  } catch (error) {
    $log.error("服务器启动失败:", error);
    process.exit(1);
  }
}

bootstrap();

高级特性探索

自动生成OpenAPI文档

Ts.ED自动从你的装饰器和模型生成OpenAPI 3.0文档:

import { Returns, Summary, Description } from "@tsed/schema";

@Get("/statistics")
@Summary("获取用户统计信息")
@Description("返回系统的用户统计数据和指标")
@Returns(200, UserStatistics)
@Returns(500).Description("服务器内部错误")
async getStatistics() {
  // 实现统计逻辑
}

访问 http://localhost:3000/docs 即可查看完整的API文档。

中间件和拦截器

创建自定义中间件进行请求处理:

import { Middleware, MiddlewareMethods } from "@tsed/platform-middlewares";
import { Context } from "@tsed/platform-params";

@Middleware()
export class LoggingMiddleware implements MiddlewareMethods {
  use(@Context() ctx: Context) {
    const { request } = ctx;
    console.log(`${new Date().toISOString()} - ${request.method} ${request.url}`);
    
    // 继续处理请求
    return ctx.next();
  }
}

// 在控制器中使用
@Controller("/users")
@UseBefore(LoggingMiddleware)
export class UsersController {
  // ...
}

数据验证和转换

利用Ajv进行强大的数据验证:

import { Property, Format, Email, Minimum, Maximum } from "@tsed/schema";

export class CreateUserDto {
  @Property()
  @Required()
  @MinLength(3)
  name: string;

  @Property()
  @Required()
  @Email()
  email: string;

  @Property()
  @Minimum(18)
  @Maximum(100)
  age: number;

  @Property()
  @Format("date")
  birthDate: string;
}

测试策略

单元测试示例

使用Jest进行服务层测试:

import { TestContext } from "@tsed/testing";
import { UserService } from "./UserService";

describe("UserService", () => {
  let service: UserService;

  beforeEach(async () => {
    service = await TestContext.invoke(UserService);
  });

  afterEach(async () => {
    await TestContext.reset();
  });

  it("应该创建用户", async () => {
    const user = await service.create({
      name: "测试用户",
      email: "test@example.com"
    });

    expect(user.id).toBeDefined();
    expect(user.name).toBe("测试用户");
    expect(user.email).toBe("test@example.com");
  });
});

集成测试示例

测试完整的API端点:

import { PlatformTest } from "@tsed/testing";
import { PlatformExpress } from "@tsed/platform-express";
import { Server } from "../Server";

describe("Users API", () => {
  beforeAll(async () => {
    await PlatformTest.bootstrap(Server)();
  });

  afterAll(async () => {
    await PlatformTest.reset();
  });

  it("GET /api/users 应该返回用户列表", async () => {
    const response = await request.get("/api/users");
    
    expect(response.status).toBe(200);
    expect(Array.isArray(response.body)).toBe(true);
  });
});

部署和生产环境配置

环境变量配置

创建多环境配置文件:

// config/production.ts
export const config = {
  port: process.env.PORT || 3000,
  logger: {
    level: "info"
  },
  swagger: {
    path: "/docs",
    disabled: process.env.NODE_ENV === "production"
  }
};

// config/development.ts  
export const config = {
  port: 3000,
  logger: {
    level: "debug"
  },
  swagger: {
    path: "/docs"
  }
};

Docker容器化

创建Dockerfile用于容器化部署:

FROM node:20-alpine

WORKDIR /app

# 复制package文件
COPY package*.json ./
COPY yarn.lock ./

# 安装依赖
RUN yarn install --frozen-lockfile --production

# 复制源码
COPY dist/ ./dist/
COPY config/ ./config/

# 暴露端口
EXPOSE 3000

# 启动应用
CMD ["node", "dist/src/index.js"]

性能优化建议

1. 启用压缩中间件

@Configuration({
  middlewares: [
    compress({ threshold: 1024 }) // 启用响应压缩
  ]
})

2. 使用缓存策略

import { UseCache } from "@tsed/platform-cache";

@Get("/users")
@UseCache({ ttl: 300 }) // 缓存5分钟
async getUsers() {
  return this.userService.findAll();
}

3. 数据库连接池优化

@Configuration({
  typeorm: [
    {
      name: "default",
      type: "postgres",
      poolSize: 20, // 连接池大小
      synchronize: false
    }
  ]
})

常见问题解答

Q: Ts.ED与其他Node.js框架相比有什么优势?

A: Ts.ED结合了TypeScript的类型安全、Express的灵活性、装饰器的简洁性和依赖注入的可维护性,提供了开箱即用的企业级解决方案。

Q: 如何迁移现有的Express项目到Ts.ED?

A: 可以逐步迁移,先保持现有的Express中间件,逐步将路由改为Ts.ED的控制器形式。

Q: Ts.ED支持微服务架构吗?

A: 是的,Ts.ED支持多种传输协议,可以轻松构建微服务架构。

Q: 生产环境部署需要注意什么?

A: 确保启用适当的日志级别、禁用开发工具、配置环境变量和使用进程管理器如PM2。

总结

Ts.ED框架通过其强大的装饰器系统、依赖注入容器和开箱即用的功能,为TypeScript服务端开发提供了完整的解决方案。从简单的REST API到复杂的企业级应用,Ts.ED都能提供良好的开发体验和可维护的代码结构。

通过本文的指南,你应该已经掌握了:

  • 🚀 Ts.ED项目的创建和配置
  • 🔧 控制器、服务和模型的实现
  • 📚 自动API文档生成
  • 🧪 测试策略和最佳实践
  • 🚢 生产环境部署和优化

现在就开始你的Ts.ED之旅,享受类型安全的服务端开发体验吧!


下一步行动建议:

  1. 尝试本文中的示例代码,创建你的第一个Ts.ED应用
  2. 探索Ts.ED的插件生态系统,集成数据库和消息队列
  3. 加入Ts.ED社区,获取更多学习资源和帮助
  4. 在实际项目中应用所学知识,逐步掌握高级特性

记住,最好的学习方式就是动手实践!Happy coding! 🎉

【免费下载链接】tsed :triangular_ruler: Ts.ED is a Node.js and TypeScript framework on top of Express to write your application with TypeScript (or ES6). It provides a lot of decorators and guideline to make your code more readable and less error-prone. ⭐️ Star to support our work! 【免费下载链接】tsed 项目地址: https://gitcode.com/gh_mirrors/ts/tsed

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值