ts-rest 快速入门指南:构建类型安全的 REST API 系统

ts-rest 快速入门指南:构建类型安全的 REST API 系统

ts-rest RPC-like client, contract, and server implementation for a pure REST API ts-rest 项目地址: https://gitcode.com/gh_mirrors/ts/ts-rest

前言

在现代 Web 开发中,前后端分离架构已成为主流。然而,随着项目规模扩大,前后端接口的维护和同步往往成为痛点。ts-rest 项目应运而生,它提供了一种类型安全的方式来定义和实现 REST API,确保前后端在接口层面始终保持一致。

核心概念

ts-rest 的核心思想是通过 TypeScript 类型系统来定义 API 契约(Contract),这个契约可以在前后端共享,从而获得以下优势:

  1. 类型安全:编译时就能捕获接口不匹配的问题
  2. 自动补全:IDE 能提供准确的参数提示
  3. 减少文档:代码即文档,减少维护文档的工作量
  4. 统一验证:前后端使用相同的验证逻辑

环境准备

安装核心包

首先需要安装 ts-rest 的核心包:

npm install @ts-rest/core

配置 TypeScript

确保你的 tsconfig.json 中启用了严格模式:

{
  "compilerOptions": {
    "strict": true
  }
}

严格模式是 ts-rest 正常工作的重要前提,它能提供更完善的类型检查。

定义 API 契约

API 契约是 ts-rest 的核心,它定义了接口的路径、方法、请求参数和响应格式。建议将契约定义在共享的位置,前后端都能访问。

使用 Zod 定义契约(推荐)

import { initContract } from '@ts-rest/core';
import { z } from 'zod';

const c = initContract();

const Pokemon = z.object({
  name: z.string(),
});

export const pokemonContract = c.router({
  getPokemon: {
    method: 'GET',
    path: '/pokemon/:id',
    responses: {
      200: Pokemon,
    },
    summary: '根据ID获取宝可梦信息',
  },
});

使用 Zod 等验证库的好处是:

  • 提供运行时验证
  • 自动生成类型定义
  • 支持复杂的验证规则

其他验证库选项

ts-rest 也支持 Valibot、Arktype 等验证库,或者不使用任何验证库(仅类型)。选择哪种方式取决于项目需求和技术栈。

服务端实现

ts-rest 支持多种 Node.js 框架,下面以 Express 为例:

Express 实现

import express from 'express';
import { initServer } from '@ts-rest/express';
import { pokemonContract } from './contract';

const app = express();
const s = initServer();

const router = s.router(pokemonContract, {
  getPokemon: async ({ params: { id } }) => {
    const pokemon = { name: '皮卡丘' };

    if (id !== '1') {
      return {
        status: 404,
        body: null,
      };
    }

    return {
      status: 200,
      body: pokemon,
    };
  },
});

app.use(express.json());
app.use('/api', router);

app.listen(3000, () => {
  console.log('服务器已启动: http://localhost:3000');
});

其他框架支持

  • NestJS:提供装饰器风格的实现
  • Fastify:高性能框架实现
  • Next.js:适合全栈应用

每种实现都保持了相同的类型安全特性,开发者可以根据项目需求选择合适的框架。

客户端实现

基础 Fetch 客户端

import { initClient } from '@ts-rest/core';
import { pokemonContract } from './contract';

const client = initClient(pokemonContract, {
  baseUrl: 'http://localhost:3000',
});

const { status, body } = await client.getPokemon({
  params: { id: '1' },
});

if (status === 200) {
  console.log(`宝可梦名称: ${body.name}`);
} else {
  console.log('未找到宝可梦');
}

React Query 集成

对于前端应用,特别是 React 项目,推荐使用 React Query 集成:

import { initQueryClient } from '@ts-rest/react-query';

const client = initQueryClient(pokemonContract, {
  baseUrl: 'http://localhost:3000',
});

function PokemonComponent() {
  const { data, isLoading } = client.getPokemon.useQuery(
    ['pokemon', '1'],
    { params: { id: '1' } }
  );

  if (isLoading) return <div>加载中...</div>;
  if (data?.status !== 200) return <div>获取数据失败</div>;

  return <div>{data.body.name}</div>;
}

React Query 集成提供了:

  • 自动缓存
  • 请求状态管理
  • 自动重试
  • 乐观更新等高级功能

最佳实践

  1. 共享契约:将契约定义在前后端都能访问的共享位置
  2. 验证库:优先使用 Zod 等验证库,确保运行时安全
  3. 错误处理:统一前后端的错误响应格式
  4. 文档生成:考虑从契约自动生成 API 文档
  5. 版本控制:为契约添加版本信息,便于后续演进

总结

ts-rest 为 TypeScript 项目提供了一套完整的类型安全 REST API 解决方案。通过定义共享契约,开发者可以:

  • 减少前后端沟通成本
  • 提高开发效率(自动补全、类型检查)
  • 降低运行时错误
  • 简化测试和维护

无论是小型项目还是大型企业应用,ts-rest 都能显著提升 API 开发的体验和质量。

ts-rest RPC-like client, contract, and server implementation for a pure REST API ts-rest 项目地址: https://gitcode.com/gh_mirrors/ts/ts-rest

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吕岚伊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

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

抵扣说明:

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

余额充值