编译期类型不是防弹衣

TypeScript 很强,但它无法保证运行时数据一定符合类型。只要数据来自网络、表单、消息队列,就需要校验。

一个常见坑

type User = { id: string; age: number }

function handleUser(u: User) {
  return u.age + 1
}

如果后端把 age 传成字符串,编译不会报错,运行才炸。

用 Zod 建立输入防线

import { z } from "zod"

const UserSchema = z.object({
  id: z.string().min(1),
  age: z.number().int().nonnegative(),
})

type User = z.infer<typeof UserSchema>

function parseUser(input: unknown): User {
  return UserSchema.parse(input)
}

好处是:

  • 校验规则集中管理
  • 报错信息可读
  • 类型与校验规则同步

在 API 层统一拦截

建议在 BFF 或网关层就完成 parse,业务层只接收已验证的数据。这样能显著减少线上脏数据导致的连锁异常。

小结

TS 负责编译期,Zod 负责运行时。两者结合,才能让类型安全真正落地。