如何在TypeScript方法装饰器中获取函数返回类型作为描述对象
实现方案
TypeScript 的类型仅存在于编译阶段,运行时原生不会保留静态类型信息,因此无法直接在运行时的装饰器逻辑中直接获取纯静态类型的完整结构,可通过以下三种方案实现需求:
- 方案1:使用TypeScript反射元数据(适合简单场景)
首先安装reflect-metadata依赖,然后修改tsconfig.json开启以下配置:
{ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true } }
在装饰器对应位置获取返回类型:
import 'reflect-metadata'; // 你标注注释的位置添加如下代码 const returnType = Reflect.getMetadata('design:returntype', target, propertyKey);
该方案的局限性:仅能返回基础类型、自定义类的构造函数,接口、类型别名、联合类型、泛型等复杂类型会统一返回Object,无法拿到具体结构,不适合复杂接口场景。
- 方案2:运行时Schema反向推导(生产级复杂场景)
该方案是目前Node.js生态中Swagger自动生成的主流实现思路,通过运行时校验Schema反向推导TS类型,保证类型和实际返回结构完全对齐:
- 选用运行时Schema定义库定义返回结构,同时推导对应的TS类型
- 改造你的路由装饰器,增加接收返回Schema的入参
- 在装饰器对应位置将Schema转换为Swagger所需的结构即可
示例改造逻辑:
// 装饰器定义新增返回Schema参数 function Get(path: string, responseSchema?: any) { return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { // 原有逻辑省略 // 标注注释的位置直接处理Schema if (responseSchema) { // 将Schema转换为Swagger兼容的JSON结构即可 const swaggerSchema = convertSchemaToSwagger(responseSchema); __swaggerRoute.get.responses = { 200: { description: "成功响应", schema: swaggerSchema } } } // 原有逻辑省略 } } // 路由使用示例 const UserResponseSchema = /* 定义运行时返回结构 */; type UserResponse = /* 从Schema推导的TS类型 */; @Get('/user', UserResponseSchema) getUser(): UserResponse { // 业务逻辑 }
该方案支持所有复杂类型,且能避免类型声明和实际返回结构不一致的问题,适合生产环境使用。
- 方案3:自定义TypeScript转换器(全类型自动支持)
如果你需要完全自动提取类型不需要手动定义Schema,可以开发自定义TypeScript Transformer,在编译阶段通过TypeScript Compiler API扫描所有被装饰器修饰的方法,解析函数返回类型的结构,转换为JSON Schema后注入到代码元数据中,运行时直接读取即可。该方案无需额外编写业务代码,但开发成本较高,需要熟悉TypeScript编译API的使用。
内容的提问来源于stack exchange,提问作者Yohan Le Quéré
相关产品推荐
相关产品推荐

