You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何结合TypeBox与Inversify路由在swagger-express-ts中复用模型?

解决方案

1. 核心思路:TypeBox Schema 转 Swagger 兼容结构

swagger-express-ts 的装饰器(如@ApiRequestBody、@ApiResponse)接受的是符合 Swagger 规范的 JSON Schema,而 TypeBox 自带了将自身 Schema 转换为标准 JSON Schema 的方法,利用这一点就能实现复用。

2. 具体实现步骤

第一步:定义复用的 TypeBox Schema

先写出通用的 TypeBox 校验 Schema,后续在校验和 Swagger 装饰器中都用这个:

import { Type } from '@sinclair/typebox';

// 可复用的用户创建参数Schema
const CreateUserSchema = Type.Object({
  username: Type.String({ minLength: 3, maxLength: 20 }),
  email: Type.String({ format: 'email' }),
  password: Type.String({ minLength: 6 })
});

// 可复用的用户返回结果Schema
const UserResponseSchema = Type.Object({
  id: Type.String(),
  username: Type.String(),
  email: Type.String()
});

第二步:转换 Schema 并在 Swagger 装饰器中使用

使用 TypeBox 的SchemaToJsonSchema方法转换后,直接传入 swagger-express-ts 的装饰器参数:

import { ApiOperationPost, ApiRequestBody, ApiResponse } from 'swagger-express-ts';
import { SchemaToJsonSchema } from '@sinclair/typebox';
import { Post, Req } from 'inversify-express-utils';

@ApiOperationPost({
  path: '/users',
  description: '创建新用户',
  summary: '用户注册接口'
})
@ApiRequestBody({
  description: '用户注册参数',
  required: true,
  // 转换TypeBox Schema为Swagger兼容结构
  schema: SchemaToJsonSchema(CreateUserSchema)
})
@ApiResponse({
  statusCode: 201,
  description: '创建成功',
  schema: SchemaToJsonSchema(UserResponseSchema)
})
@Post('/users')
async createUser(@Req() req: Request) {
  // 这里用TypeBox做参数校验
  const isValid = Type.Check(CreateUserSchema, req.body);
  if (!isValid) {
    throw new Error('参数格式错误');
  }
  // 业务逻辑处理
  return this.userService.create(req.body);
}

第三步:封装校验中间件复用 Schema

如果想把校验逻辑抽离到中间件,直接传入 TypeBox Schema 即可:

import { Request, Response, NextFunction } from 'express';
import { Type, Errors } from '@sinclair/typebox';

// 通用校验中间件
export function validateSchema(schema: any) {
  return (req: Request, res: Response, next: NextFunction) => {
    const validationErrors = Errors(schema, req.body);
    if (validationErrors.length > 0) {
      return res.status(400).json({
        message: '参数校验失败',
        errors: validationErrors.map(e => e.message)
      });
    }
    next();
  };
}

然后在路由中同时使用中间件和 Swagger 装饰器:

@ApiOperationPost({
  path: '/users',
  description: '创建新用户',
  summary: '用户注册接口'
})
@ApiRequestBody({
  description: '用户注册参数',
  required: true,
  schema: SchemaToJsonSchema(CreateUserSchema)
})
// 传入TypeBox Schema到校验中间件
@Post('/users', validateSchema(CreateUserSchema))
async createUser(@Req() req: Request) {
  // 业务逻辑处理
  return this.userService.create(req.body);
}

第四步:优化转换逻辑(可选)

封装一个工具函数,自动处理转换后的冗余属性,让代码更简洁:

import { TSchema, SchemaToJsonSchema } from '@sinclair/typebox';

export function toSwaggerSchema(schema: TSchema) {
  const jsonSchema = SchemaToJsonSchema(schema);
  // 移除TypeBox生成的$schema属性,兼容Swagger
  delete jsonSchema.$schema;
  return jsonSchema;
}

使用时直接调用:

@ApiRequestBody({
  description: '用户注册参数',
  required: true,
  schema: toSwaggerSchema(CreateUserSchema)
})

注意事项

  • TypeBox 的复杂类型(如Type.Union、Type.Intersect)转换为 JSON Schema 后,swagger-express-ts 基本都能兼容,若遇到特殊情况可手动调整转换后的 Schema。
  • 确保 TypeBox 和 swagger-express-ts 的版本匹配,避免因版本差异导致的解析问题。

内容的提问来源于stack exchange,提问作者Mr X

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 19:30:18