跳到主要内容

Node 服务里类型与运行时校验的分界线

· 阅读需 2 分钟
一介布衣
全栈开发者 / 技术写作者

2021 年很多 Node.js 项目开始接入 TypeScript,代码补全和重构体验都会好很多。但这时也特别容易出现一个错觉:既然参数已经有类型了,接口是不是就安全了?

答案通常是否定的。TypeScript 保护的是“你写代码时看到的世界”,而真正从网络进来的请求体,依旧可能是任何形状。

运行时边界最好放在入口层

对 HTTP 接口来说,最适合做校验的位置通常是 controller、route handler 或者 service 的最外层。这个位置离外部输入最近,也最容易统一返回错误信息。

如果把校验拖到业务深处才做,异常路径就会越来越分散。

类型定义解决的是团队协作问题

比如 CreatePostDtoUpdateUserDto 这类类型,价值在于让团队成员知道内部代码期望拿到什么结构。它能减少沟通成本,也方便 IDE 提示。

但它并不能阻止一个缺字段、字段类型错误、甚至多传一堆脏数据的请求进来。

内外两套约束最好分开看

我比较推荐把“外部输入校验”和“内部对象类型”拆成两层:

  • 外部输入先做运行时校验与清洗
  • 清洗后的结果再进入内部 TypeScript 类型世界

这样一来,业务代码就可以默认自己面对的是收口后的对象,而不是到处补 typeof 判断。

校验规则也要避免和 ORM 模型绑死

很多项目会偷懒,直接拿数据库模型字段去反推接口校验规则。这样短期省事,但接口契约会被存储层牵着走,后面一旦有字段兼容或重命名需求,就很被动。

更稳妥的是把接口 DTO 当成单独边界维护。

小结

TypeScript 很重要,但它不是运行时防线。对 2021 年正在升级中的 Node.js 服务来说,最可靠的做法仍然是:把外部输入校验放在入口,把内部类型稳定在边界之内,两层各做各的事。