来自全韩国最好的程序员的 Nest.js 中 TypeSafe 方案

Nest.js 中的 TypeSafe 方案

在现代 Web 开发中,类型安全(TypeSafe)是提升代码质量和减少运行时错误的关键因素。

Nest.js 作为一个渐进式的 Node.js 框架,结合了 TypeScript 的强大功能,提供了构建高效、可扩展服务器端应用的理想平台。

笔者在使用 Nest.js 构建全栈应用时最大的痛点是写了这么多类型检查,好像没有办法和前端通用啊~。相信许多人也有这个问题,所以也冒出了在 Nest.js 中集成 tRPC 的教程。

而本文介绍的 Nestia,一个专为 Nest.js 设计的类型安全解决方案,帮助开发者在构建应用时实现更高的类型安全性和开发效率。

韩国最好的程序员

Jeongho Nam ,GitHub用户名为 samchon他在 README 中自称为 韩国最好的程序员。他自1998年开始编程,拥有25年的丰富经验。在这段时间里,他开发了许多程序,并不断提升自己的技能。他不仅在工作中开发程序,还在业余时间开发开源项目,以满足自身需求或改进现有功能。这些开源项目逐渐形成了新的开源库,其中最著名的就是 typianestia

什么是Nestia?

Nestia 是一个专为 Nest.js 开发的库,旨在通过利用 TypeScript 的类型系统,提供更高效和类型安全的开发体验。Nestia 的核心目标是简化数据传输对象(DTOs)的定义和验证,减少类型错误,并提升代码的可维护性。

Nestia的主要功能

  1. 类型安全的 DTO 定义和验证

    Nestia 利用 TypeScript 的类型系统,允许开发者定义类型安全的 DTOs。通过自动生成的类型定义,Nestia 确保了数据在传输和处理过程中的一致性,避免了常见的类型错误。

    NestJS需要三个重复的 DTO 模式定义。第一个是定义 TypeScript 类型,第二个和第三个是调用 class-validator@nestjs/swagger 的装饰器函数。这不仅繁琐,而且容易出错。如果你在第 2 或第 3 处写错了的话,TypeScript 编译器是无法检测到的。只有在运行时才能检测到。换句话说,它并不是类型安全的。

  2. 自动生成API客户端

    Nestia 可以根据服务器端的 API 定义,自动生成类型安全的 API 客户端。这种方式不仅减少了手动编写客户端代码的工作量,还确保了前后端的一致性

    这一功能与著名的 tRPC 库有相似之处。tRPC 是一个端到端类型安全的 RPC 框架,它允许你轻松构建和使用完全类型安全的 API,无需模式或代码生成。tRPC 的主要作用是在全栈 TypeScript 项目中提供类型安全的 API 调用,大大提高了开发效率和代码质量。但 tRPC 的问题是通常要求前后端代码位于同一个 monorepo 中 ,以便共享类型定义。这种紧耦合的架构可能不适合所有项目,特别是那些前后端分离开发或需要为第三方提供 API 的场景。相比之下,Nestia 通过自动生成独立的 API 客户端解决了这个问题。它允许你在保持类型安全的同时,将生成的 SDK 作为独立的包分发给客户端开发者。这种方式既保留了类型安全的优势,又提供了更大的灵活性,使得 Nestia 在更广泛的项目结构和开发场景中都能发挥作用。

  3. 高效的JSON序列化和反序列化

    Nestia 提供了高效的 JSON 序列化和反序列化功能,利用 TypeScript 的类型信息,显著提升了性能和类型安全性。

如何使用Nestia

安装Nestia

你可以运行以下命令通过模版代码来快速上手 Nestia。 模板将自动构建在<directory>中。作为参考,这是一个最小的模板项目,只集中于从 NestJS 服务器生成 SDK。它不包含数据库连接。

bash 复制代码
npx nestia start <directory>

你也可以运行下面的命令来将 Nestia 集成至现有的项目中。设置向导将自动安装并配置所有内容。

bash 复制代码
npx nestia setup

定义类型安全的DTO

你不需要掌握特殊的语法只使用 TypeScript 就可以编写一个带有类型检查的 DTO。当然,Nestia 也通过 Typia 提供了编写复杂类型检查的可能,例如,我们可以定义一个论坛完整的 DTO:

typescript 复制代码
import { tags } from "typia";

export interface IBbsArticle {
  /* Primary Key. */
  id: string & tags.Format<"uuid">;

  /* Title of the article. */
  title: null | (string & tags.MinLength<5> & tags.MaxLength<100>);

  /*  Main content body of the article. */
  body: string;

  /* Creation time of article. */
  created_at: string & tags.Format<"date-time">;
}

Controller 中调用 Nestia 的装饰器

NestJS 原生的装饰器(如 @Get(), @Post() 等)虽然使用方便,但在性能和类型安全方面存在一些局限:

  • 使用 class-validator 和 class-transformer 进行验证和转换,性能相对较低
  • 需要定义额外的 DTO 类和装饰器,增加了代码量
  • 类型安全性不够强,运行时可能出现类型错误

Nestia 的装饰器(如 @TypedRoute.Get(), @TypedBody() 等)则解决了这些问题:

  • 利用 typia 库进行高性能的运行时类型验证,比 class-validator 快 20,000 倍
  • 支持使用纯 TypeScript 接口定义 DTO,无需额外的类定义
  • 在编译时进行类型检查,提供更强的类型安全性
  • JSON 序列化速度比 class-transformer 快 200 倍
typescript 复制代码
import { TypedRoute } from "@nestia/core";
import { Controller } from "@nestjs/common";
 
import { IBbsArticle } from "./IBbsArticle";
 
@Controller("bbs/articles")
export class BbsArticlesController {

  @TypedRoute.Get("random")
  public async random(): Promise<IBbsArticle> {
    return {
      id: "2b5e21d8-0e44-4482-bd3e-4540dee7f3d6",
      title: "Hello nestia users",
      body: "Just use `TypedRoute.Get()` function like this",
      created_at: "2023-04-23T12:04:54.168Z",
      files: [],
    };
  }
  
  @TypedRoute.Post()
  public async store(
    @TypedBody() input: IBbsArticle.IStore,
  ): Promise<IBbsArticle> {
    return {
      ...input,
      id: "2b5e21d8-0e44-4482-bd3e-4540dee7f3d6",
      created_at: "2023-04-23T12:04:54.168Z",
    };
  }
}

自动生成API客户端

Nestia可以根据服务器端的API定义,自动生成类型安全的API客户端。在根目录配置 nestia.config.ts 文件

typescript 复制代码
import { INestiaConfig } from '@nestia/sdk';
import { NestFactory } from '@nestjs/core';
import { FastifyAdapter } from '@nestjs/platform-fastify';

import { AppModule } from './src/app.module';

const NESTIA_CONFIG: INestiaConfig = {
  input: async () => {
    const app = await NestFactory.create(AppModule, new FastifyAdapter());
    app.setGlobalPrefix('api');
    return app;
  },
  output: 'src/api',
  clone: true,
  distribute: 'sdk',
};
export default NESTIA_CONFIG;

运行命令 npx nestia sdk 即可生成 SDK package,你可以直接在 Monorepo 中使用它,也可以将其分发到 npm.

尝试使用生成的 SDK 看到类型提示的那一刻,整个人都通畅了~

结论

Nestia 作为一个专为 Nest.js 设计的类型安全解决方案,通过简化 DTO 定义和验证、自动生成 API 客户端以及高效的 JSON 序列化和反序列化功能,帮助开发者在构建应用时实现更高的类型安全性和开发效率。无论是大型企业级应用还是个人项目,Nestia 都是提升代码质量和开发效率的理想选择。

通过本文的介绍,希望您对 Nestia 有了更深入的了解,并能在您的 Nest.js 项目中尝试使用这一强大的工具,享受类型安全带来的诸多好处。

相关推荐
Web阿成6 小时前
3.学习webpack配置 尝试打包ts文件
前端·学习·webpack·typescript
j喬乔16 小时前
Node导入不了命名函数?记一次Bug的探索
typescript·node.js
yg_小小程序员1 天前
vue3中使用vuedraggable实现拖拽
typescript·vue
高山我梦口香糖1 天前
[react 3种方法] 获取ant组件ref用ts如何定义?
typescript·react
prall1 天前
实战小技巧:下划线转驼峰篇
前端·typescript
一條狗3 天前
隨筆 20241224 ts寫入excel表
开发语言·前端·typescript
轻口味3 天前
配置TypeScript:tsconfig.json详解
ubuntu·typescript·json
小林rr4 天前
前端TypeScript学习day03-TS高级类型
前端·学习·typescript
web150850966415 天前
前端TypeScript学习day01-TS介绍与TS部分常用类型
前端·学习·typescript
前端熊猫5 天前
省略内容在句子中间
前端·javascript·typescript