NSwag生成TypeScript客户端时如何提取公共DTO避免类型重复
NSwag生成TypeScript客户端公共DTO重复问题解决方案
方案1:后端自定义SchemaProcessor标记公共类型(你提到的思路落地)
这是最可控的方案,实现逻辑如下:
- 先统一公共DTO的存放规则,将所有跨服务共享的DTO放到单独的类库中,统一使用固定命名空间,比如
YourCompany.Contracts.Common - 自定义实现
ISchemaProcessor接口,在Schema生成阶段识别公共类型,固定公共类型的Schema ID为类型全限定名,同时添加自定义扩展标记标识公共类型,示例代码如下:
public class CommonTypeSchemaProcessor : ISchemaProcessor { private const string CommonTypeNsPrefix = "YourCompany.Contracts.Common"; public void Process(SchemaProcessorContext context) { var currentType = context.Type; if (currentType.Namespace?.StartsWith(CommonTypeNsPrefix) == true) { // 固定Schema ID,避免不同微服务生成同类型的ID不一致 context.Schema.Id = currentType.FullName; // 添加自定义扩展标记,后续生成客户端时可识别 context.Schema.ExtensionData ??= new Dictionary<string, object>(); context.Schema.ExtensionData["x-is-common-type"] = true; } } }
- 在NSwag服务注册逻辑中注入该处理器:
services.AddSwaggerDocument(config => { config.SchemaProcessors.Add(new CommonTypeSchemaProcessor()); });
- 生成TS客户端时,自定义NSwag的生成模板,识别带有
x-is-common-type标记的类型,将其定义统一输出到公共目录,其余服务生成的代码直接从公共目录导入即可。
方案2:生成端配置全局类型映射
无需修改后端逻辑,仅调整NSwag生成配置即可实现:
- 首先将所有公共DTO单独生成一份TS类型定义,存放到客户端公共目录,比如
@/types/common-dto - 每个微服务生成TS客户端时,在NSwag配置的
typeScriptGeneratorSettings中添加typeMappings配置,将公共类型的全限定名映射为公共目录的导入声明,nswag.json配置示例如下:
{ "typeScriptGeneratorSettings": { "typeMappings": { "YourCompany.Contracts.Common.UserDto": "import { UserDto } from '@/types/common-dto'", "YourCompany.Contracts.Common.PageResult": "import { PageResult } from '@/types/common-dto'" } } }
- 生成时NSwag会自动跳过这些映射类型的本地定义,直接使用导入的公共类型,不会生成冗余代码。
方案3:生成后脚本自动去重
适合不方便修改后端和NSwag配置的场景:
- 使用
ts-morph等TS语法解析库,扫描所有微服务生成的TS类型定义 - 基于类型结构哈希(属性名、属性类型完全一致则判定为同一类型)筛选出重复的公共类型
- 将公共类型提取到统一公共目录,把所有生成文件中的对应类型定义替换为公共目录的导入语句,可配置到CI/CD流程中自动执行。
注意:所有方案的前提是公共类型在不同微服务中的定义完全一致,建议公共DTO统一维护在独立的类库包中,所有服务引用统一版本的包,避免出现类型定义不一致的问题。
内容的提问来源于stack exchange,提问作者Oyvind
相关产品推荐
相关产品推荐

