在 NestJS 中,helper 和 service 都是 provider(@Injectable() 类),但它们在职责、语义、使用场景和设计意图上有明显区别。

官方文档只说“services, repositories, factories, and helpers 等都可以作为 provider”,但没有严格定义 helper 是什么——这其实是社区的惯用叫法。

下面用表格对比一下目前(2025-2026)社区最常见的理解和实践差异:

方面 Service Helper (或 Helper Service) 纯静态工具类 / util 函数
主要职责 承载业务逻辑、领域逻辑、用例协调 提供技术性、格式化、转换、工具性质的辅助功能 非常通用的、无状态的纯函数式工具
是否有状态 经常有(依赖 repository、其他 service、缓存等) 通常无状态(stateless),方法独立 完全无状态
业务相关性 ,跟当前领域/模块高度相关 ,偏技术实现细节 极弱,几乎与业务无关
典型例子 UserService、OrderProcessingService StringFormatterHelper、DateTimeHelper、ExcelHelper string.utils.ts、date.utils.ts 中的纯函数
是否需要依赖其他 provider 经常需要(注入 repo、其他 service、config 等) 偶尔需要(比如要注入 ConfigService 读配置) 基本不需要
注入方式 几乎总是注入到 controller / 其他 service 通常注入到 controller / service 中使用 直接 import 使用,不需要注入
测试难度 较高(要 mock 很多依赖) 较低(依赖少或无依赖) 最低(纯函数,容易单元测试)
文件命名习惯 xxx.service.ts xxx.helper.ts 或 xxx-transform.service.ts xxx.util.ts / xxx.helper.ts(不加 @Injectable)
是否加 @Injectable() 必须 推荐(尤其是要注入依赖时) 不需要
放在哪里 通常跟模块同级:users/user.service.ts 常放在 helpers/ 子目录,或直接跟 service 同级 src/common/utils/ 或模块内 utils/ 子目录
社区共识命名 业务名 + Service 功能名 + Helper / Transformer / Formatter / UtilService 功能名 + util / helper(小写文件)

快速判断题:这段逻辑应该写成 service 还是 helper?

  • “根据用户角色返回不同的权限列表” → Service(业务规则)
  • “把手机号统一转成 +86 开头的国际格式” → Helper
  • “从数据库取用户 + 校验密码 + 生成 token + 记录登录日志” → Service
  • “把实体对象转成 DTO,处理字段隐藏、日期格式化” → Helper(常见叫 ResponseMapperHelper 或 DtoTransformer)
  • “判断两个日期是否在同一天(忽略时间)” → 可以是 Helper,也可以直接写成 util 函数

实际项目中最常见的几种叫法和折中方案

  1. 全 helper 化(很多中小项目这样写)

    • 凡是 controller 里不适合放的独立逻辑 → xxx.helper.ts + @Injectable()
    • 优点:统一,容易搜索,测试友好
  2. 分层更清晰(中大型项目常见)

    • 真正的业务逻辑 → xxx.service.ts
    • 数据映射/格式化/转换 → xxx.mapper.ts 或 xxx.transformer.service.ts
    • 纯技术工具 → xxx.helper.ts 或直接 utils/ 目录下的纯函数
  3. 最偷懒但也最常见
    直接都叫 xxx.service.ts,但起名时体现区别:

    • UserService
    • UserPasswordService
    • UserDtoMapperService
    • StringUtilsService(很多人会这么写……)

总结一句话建议(2026 年社区主流折中做法)

  • 如果这段逻辑跟业务规则、领域事件、数据一致性有关 → 写成 service
  • 如果只是格式化、转换、计算、字符串处理、文件路径拼接、响应包装 → 写成 helper(加 @Injectable(),方便以后加依赖)
  • 如果非常通用、无任何依赖、项目中多处使用 → 优先写成纯函数放到 common/utils/ 下
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐