老师好,感觉「只有当函数返回 true 时,形参被确定为 A 类型」这里的描述有点让人不好理解
来源:7-15 【 TS 自定义守卫理解+应用】 快速学透自定义守卫 【真实应用场景】

luckept
2022-04-12
经过实验,我发现并不是这个函数的返回值去决定它是否能点出来属性和方法,而是他会默认将函数执行结果视作真,若直接调用,它会直接将判断的内容类型范围收缩为守卫的类型。如果在判断语句中取反,它才默认不视作守卫的类型
【就其实跟老师您说的,自定义守卫是在编译期间确定类型的,那它如何能够根据函数返回 true 或 false 来决定类型是否被守卫呢,它又没有去实际运行】
也即是说,不做取反操作时 TS 就默认认为这个函数的逻辑是成功的,于是类型缩窄为守卫定义的类型,而取反时,TS 会认为这个函数的逻辑要在取反后才为真,这时形参的类型就不再是守卫的类型。下面是实验的代码,若有理解不当,请老师指正
函数返回为 false,但 if 中不做取反操作,可以点出来属性
function isString(str: any): str is string {
return false
}
['1',2,3].forEach((item) => {
if(isString(item)) {
// 此时可以点出来 string 类型的方法和属性
}
})
函数返回为 true,但 if 中取反,不能点出来属性
function isString(str: any): str is string {
return true
}
['1',2,3].forEach((item) => {
if(!isString(item)) {
// 此时无法点出来 string 类型的方法和属性
}
})
1回答
-
理解基本正确:我总结下:
1.首先 常规来说: 运行时代码不能判断 编译时的 if 判断条件是true还是false ,这个定律正确。
2. 但TS 自定义守卫中 [str is 类型] 返回语法 的出现 打破 了这一定律, 底层增加了其他处理机制,让其在编译期间 拥有 根据 if 范围 来决定 变量 类型的能力。
更多理解如下。。。
3. TS 自定义守卫只存在于编译期间,运行转换为js后就不存在了。
4. 在编译期间,TS 识别自动守卫中的类型判断结果并不是根据 自定守卫函数内部的运行时代码来确定的; isString 返回了false 还是返回 true 对 自动守卫的语法使用规则没影响。
5. 当TS 编译器在编译期间遇到 使用自定义守卫方法的 if 语句的内部时【能进入内部就一定为true], 这时编译器会认为 str 为String 成立,会自动把 参数 str 的类型范围缩小为定义时的 String 。
TS编译器底层这样识别自定义守卫的类型。
112022-04-13
相似问题