Assert函数无法更新类型:自制类Zod NPM包类型推断异常
问题原因与解决方案
为什么变量类型没更新?
核心问题是断言函数的作用域限制:
isString断言函数仅在它被直接调用的parse方法内部生效,它修改的是parse函数里局部变量arg的类型,不会影响外部的变量a。- 直接调用
isString(a)时,是在当前作用域对变量a做断言,TypeScript能直接更新a的类型。 - 而
x.string().parse(a)本质是返回一个string类型的值,但你没有把返回值重新赋值给a,同时parse方法本身没声明会修改传入参数的类型,所以TypeScript不会自动推断a的类型发生变化。
如何让变量类型更新?
有两种可行方案:
方案1:将parse返回值赋值给变量
把校验后的结果重新赋值给a,TypeScript会自动推导a的类型为string:
let a: unknown = 'asd' a = x.string().parse(a) // a: string
方案2:让parse方法成为断言函数
复刻Zod直接断言变量类型的效果,把parse的签名改成断言函数,声明它会断言传入参数是string类型:
function isString(val: unknown): asserts val is string { if (typeof val !== 'string') throw new Error() } const x = { string: () => ({ // 修改parse为断言函数签名 parse(arg: unknown): asserts arg is string { isString(arg) } }) } let a: unknown = 'asd' x.string().parse(a) // 调用后,a的类型自动更新为string
这种方式下,parse不再返回值,而是直接对传入参数做类型断言,效果和直接调用isString(a)完全一致。
内容的提问来源于stack exchange,提问作者Sercrac 07
相关产品推荐
相关产品推荐

