TypeScript 类型缩小似乎做出了不正确的假设

互联网 行业动态 更新时间:2024-06-13 00:19:07

jca*_*alz 6

从纯健全性的角度来看,赋值是正确的,而in运算符缩小是不正确的。从实用的角度来看,in运算符缩小非常有用,而赋值则不然。这两个功能不匹配,因此您提供了一个很好的 TypeScript 代码示例,无论是纯粹的类型主义者还是惯用的 JS 编码人员都不会对该语言的行为特别满意。


首先我们来看一下作业

let x: T = {num1: 1, num2: 2, str1: 'hello'};

根据结构类型,初始化x器肯定是类型的值T,所以也是{num1: 1, num2: 2, str1: true, randomThingy: "x"}。额外的属性不违反类型。

但是 TypeScript 确实将多余的属性检查作为一种 linter 规则来捕捉人们丢弃类型信息的情况。当您分配时const x: {a: string} = {a: "", b: 0},您将丢弃有关该b属性的信息,因为编译器无法恢复它;编译器会完全忘记b。另一方面,const y = {a: "", b: 0}; const x: {a: string} = y;很好,因为即使x不知道by仍然知道。多余的属性检查规则是对实用主义的认可,而不是类型安全。

此规则有时使人们认为 TypeScript 中的对象类型不允许额外的属性,并且它们是microsoft/TypeScript#12936中要求的“精确类型” 。但是 TypeScript 没有确切的类型,而且过多的属性检查规则也不会出现在人们认为应该出现的任何地方。

一个这样的地方是当你分配一个类型时T,一个联合类型,它不是一个可区分的联合。在执行多余的属性检查之前,编译器不会将联合拆分为其成员。只要至少一个联合成员中需要一个属性,编译器就会对它感到满意。在microsoft/TypeScript#20863中存在一个长期未解决的问题,要求对此进行更改,但在可预见的未来,情况就是这样。

因此,如果您主要关心类型安全,则分配很好,但如果您关心确切类型,则不适用。


现在让我们看看缩小

if('str1' in x) {
  console.log(x.str2.toUpperCase());
}

这显然不是合理的行为。毕竟,TypeScript 中的对象类型并不精确,所以如果你知道这"str1"是一个关键,x你就不能从逻辑上断定它"str2"也是一个关键。如果您非常关心类型安全,那将是非常不幸的。

另一方面,它非常有用。即使你不能从技术上说这"str1"绝对意味着 的存在"str2",但它们之间的相关性可能非常强。通常,当人们检查仅已知存在于工会的一个成员中的属性时,他们会这样做,因为它确实让他们在实践中(如果在理论上不是)歧视工会。

在microsoft/TypeScript#15256中,实现in运算符缩小的拉取请求中, TS 团队的开发负责人有以下评论:

We considered the soundness aspect and it's not very different from existing soundness issues around aliased objects with undeclared properties. ... The reality is that most unions are already correctly disjointed and don't alias enough to manifest the problem. Someone writing an in test is not going to write a "better" check; all that really happens in practice is that people add type assertions or move the code to an equally-unsound user-defined type predicate. On net I don't think this is any worse than the status quo (and is better because it induces fewer user-defined type predicates, which are error-prone if written using in due to a lack of typo-checking).

So in operator narrowing is definitely a case of pragmatism winning out over soundness.


And there you have it... pragmatically speaking nobody would assign a weird union-straddling value to x, and it would be nice if the piler could warn you when you did. And technically speaking it's wrong to use k in o to imply anything about a key other than k, and the piler shouldn't do it.

不过,退后一步,这只是纯粹主义者的问题。TypeScript 的类型系统并不完全健全,也不打算如此(根据同一开发负责人的说法,试图用编译为 JavaScript 的东西来做到这一点是“愚蠢的差事” )。TypeScript的第一个设计目标是捕捉可能的错误,显然很少有人像这个例子那样不小心撞到自己的脚。

语言的一部分偏爱健全性,而另一部分偏爱实用主义这一事实可以被视为语言设计的实用主义:健全性在帮助人们编写无错误的程序方面是伟大的,但如果它会被丢弃以支持其他东西,如果它的伤害大于它的帮助。 再次引用:

归根结底,类型系统是我们为帮助我们编写正确程序而创建的工具。可证明的稳健性是该努力的替代指标。如果您的程序通过构造仅在运行时观察到正确的类型,那么计算机是否可以证明是这种情况是该短语的两种含义的学术练习。

这意味着如果你想看到这个例子的改变,你必须证明这样的错误比 TS 团队认为的更常见。通常带有来自流行包的真实代码示例。

更多推荐

出了,不正确,类型,TypeScript

本文发布于:2023-04-20 20:57:13,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/hyzx/52711a06e5bea414b2b7d8d598c3eb45.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:出了   不正确   类型   TypeScript

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!