写了个 isOrder(v): v is Order 的守卫,函数体里只判断了 v !== null,结果空对象也进了分支,取字段时报 undefined。日志里能看到传进来的是个字符串。第一次遇到会往复杂处想,其实漏掉的多是个小前提。
function isOrder(v: unknown): v is Order {
const o = v as Order;
return !!o && typeof o.id === 'number' && typeof o.amount === 'number';
}
console.log(isOrder('x')); // false
类型谓词只是声明返回布尔值,函数体不做真实字段检查,编译器就完全信任这个结论。写 return true 也能编译通过,收窄是假的,运行时该崩还是崩。这一点先确认清楚,后面就不用反复试。
碰到「类型守卫失效」这类问题,我习惯先把当前配置原样备份一份,改坏了立刻换回来,不用现场推。临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。
动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。
具体做法是,把守卫里的判断补成逐字段校验 类型和值都看;用 zod 这类校验器生成判断 少手写分支;给守卫补单测 传错误形状必须返回 false。
改完照着核一遍,传字符串和空对象时守卫都返回 false 分支只走正确数据 线上不再出现 undefined。
