我最近遇到了一个问题,TypeScrip错误地认为变量可以是undefined.这是一个简化版本:

const f = (a?: boolean, b?: boolean) => {
  if (!a && !b) return;
  let c: boolean;
  if (a) c = false;
  else c = b;
}

else c = b;行中,afalseundefined,b只能是true,否则!a && !b就会为真.但TypeScrip抛出了一个错误,说:

Type 'boolean | undefined' is not assignable to type 'boolean'.

TypeScript Playground

为了暂时解决这个问题,我在if (a) c = false;行中添加了|| !b:

const f = (a?: boolean, b?: boolean) => {
  if (!a && !b) return;
  let c: boolean;
  if (a || !b) c = false;
  else c = b;
}

TypeScript Playground

但我很好奇为什么会发生这个错误,而且TypeScrip无法检测到变量不能为undefined.

推荐答案

半Jest 的回答是:因为打字本不能模拟量子纠缠.

更严重的是,字体缩小基本上是一个单向的过程.它从顶部开始,遍历代码的所有分支,并在执行过程中缩小范围.要检测您询问的情况,它需要能够回溯,或者记住比类型系统支持的更复杂的关联

让我们逐步了解一下代码,看看TypeScrip看到了什么.首先,我们有以下内容:

if (!a && !b) return;

在这条线之前,aboolean | undefined,b也是boolean | undefined.TypeScrip试图缩小范围,但它不能.a可能仍然是未定义的(如果b为真),反之亦然.所以在这条线之后,a‘S型仍然是boolean | undefined,b也是一样.

过了一会儿,我们得出了这个结论:

if (a) c = false;

只看这一行上的类型和代码,类型脚本可以推断出什么?它知道,如果我们进入else的情况,那么a一定是falseundefined.但它不能推断出b的任何东西.

要推断出b左右,你需要知道发生在b上的以前的判断.TypeScrip确实间接地有关于过go 判断的信息:它有b‘S缩小的字体.但由于类型实际上并没有缩小(仍然是boolean | undefined),这在这里没有帮助.类型脚本要么需要具有回溯和重新计算的能力,要么需要支持编码多变量之间的相关性的类型(参见量子纠缠Jest )

Typescript相关问答推荐

类型脚本不会推断键的值类型

React Hook中基于动态收件箱定义和断言回报类型

类型脚本接口索引签名

对扩展某种类型的属性子集进行操作的函数

在不更改类型签名的情况下在数组并集上映射文字

打印脚本中的动态函数重载

返回具有递归属性的泛型类型的泛型函数

类型脚本返回的类型包含无意义的泛型类型名称

类型脚本满足将布尔类型转换为文字.这正常吗?

在HighChats列时间序列图中,十字准线未按预期工作

寻址对象中路径的泛型类型

在列表的指令中使用intersectionObservable隐藏按钮

类型脚本-在调用期间解析函数参数类型

react 路由不响应参数

如何填写Partial的一些属性并让类型系统知道它?

React中的效果挂钩在依赖项更新后不会重新执行

确保财产存在

元素隐式具有any类型,因为string类型的表达式不能用于索引类型{Categories: Element;管理员:元素; }'

使用 Next.js 路由重定向到原始 URL 不起作用

如何在故事书的Typescript 中编写decorator ?