老师好,感觉「只有当函数返回 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回答

keviny79

2022-04-13

理解基本正确:我总结下:

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编译器底层这样识别自定义守卫的类型。

1
1
luckept
非常感谢老师的解答,让我能对这一块理解更深
2022-04-13
共1条回复

晋级TypeScript高手,成为抢手的前端开发人才

轻松驾驭 TypeScript 高级用法, 突破前端成长瓶颈

871 学习 · 425 问题

查看课程