typescript 为什么 && 运算符会产生第二个操作数的类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12693787/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does the && operator produce the type of the second operand
提问by Peter Olson
The TypeScript specification states in §4.15.6 about the &&operator:
TypeScript 规范在 §4.15.6 中关于&&操作符的说明:
The && operator permits the operands to be of any type and produces a result of the same type as the second operand.
&& 运算符允许操作数为任何类型,并产生与第二个操作数相同类型的结果。
In Javascript, the &&operator returns the first operand if it is falsy, otherwise it returns the second operand (see ECMA-262 §11.11).
在 Javascript 中,&&如果第一个操作数为假,则运算符返回第一个操作数,否则返回第二个操作数(参见 ECMA-262 §11.11)。
That means that if the left operand is falsy, &&will return a value that matches the type of the left operand. For example,
这意味着如果左操作数为假,&&将返回一个与左操作数类型匹配的值。例如,
typeof ( false && {} ) === "boolean" // true
typeof ( '' && 1 ) === "string" // true
typeof ( null && "hello" ) === "object" // true
typeof ( NaN && true ) === "number" // true
Typescript, according to the rule quoted above, would incorrectlypredict the types of the above expressions to be Object, Number, Stringand Boolean, respectively.
打字稿,根据上面引述的规则,将不正确地预测的类型上面的表达式的是Object,Number,String和Boolean,分别。
Am I missing something? Is there a good reason to make the type of an &&expression match the type of the second operand? Shouldn't the result type behave like the ||operator, and return the best common type of the two operands, and Anyif there is no best common type?
我错过了什么吗?是否有充分的理由使&&表达式的类型与第二个操作数的类型相匹配?结果类型不应该像||运算符一样,并返回两个操作数的最佳公共类型,Any如果没有最佳公共类型?
采纳答案by Ryan Cavanaugh
Long story short, there's no solution here that pleases everyone.
长话短说,这里没有让每个人都满意的解决方案。
Consider this common idiom:
考虑这个常见的习语:
var customer = GetCustomer(...); // of type 'Customer'
var address = customer && customer.address;
if(address) {
printAddressLabel(address); // Signature: (Address) => void
} else {
// Couldn't find the customer or the customer has no address on file
}
It'd be pretty lame to give up and decide that 'address' is 'any' because there's no best common type between Customer and Address.
放弃并决定 'address' 是 'any' 是非常蹩脚的,因为 Customer 和 Address 之间没有最好的通用类型。
In the majority of cases where the && operator is used, either the types alreadymatch, or && is being used in a value-coalescing manner like above. In either case, returning the type of the right operand gives the user the expected type.
在使用 && 运算符的大多数情况下,类型已经匹配,或者 && 正在以如上所述的值合并方式使用。在任何一种情况下,返回正确操作数的类型都会为用户提供预期的类型。
While the type safety is technically breaking down at this point, it's not doing so in a way that's likely to result in an error. Either you're going to test the resultant value for truthiness (in which case the type is more or less irrelevant), or you're going to use the presumptive right operand for some operation (the example above doing both).
虽然此时类型安全在技术上正在崩溃,但它并没有以可能导致错误的方式进行。要么您要测试真实性的结果值(在这种情况下类型或多或少无关),要么您将使用推定的正确操作数进行某些操作(上面的示例同时进行)。
If we look at the examples you listed and pretend the left operand is indeterminately truthy or falsy and then try to write sane code that would operate on the return value, it becomes a lot clearer - there's just not much you can dowith 'false && {}' that isn't already going into an 'any' argument position or truthiness test.
如果我们查看您列出的示例并假设左操作数不确定地为真或假,然后尝试编写可对返回值进行操作的合理代码,它会变得更加清晰 - 您可以用 'false &&做的不多{}' 尚未进入“任何”论证立场或真实性测试。
Addendum
附录
Since some people were not convinced by the above, here's a different explanation.
由于有些人不相信上述内容,因此这里有不同的解释。
Let's pretend for a moment that the TypeScript type system added three new types: Truthy<T>, Falsy<T>, and Maybe<T>, representing possible truthy/falsy values of type T. The rules for these types are as follows:
让我们假设一下,如果打字稿类型系统增加了三种新类型:Truthy<T>,Falsy<T>,和Maybe<T>,代表类型的可能truthy / falsy值T。这些类型的规则如下:
Truthy<T>behaves exactly likeT- You can't access any properties of
Falsy<T> - An expression of type
Maybe<T>, when used as the condition in anifblock, becomes aTruthy<T>in the body of that sameifblock and aFalsy<T>in theelseblock
Truthy<T>表现得一模一样T- 您无法访问的任何属性
Falsy<T> - 类型的表达式
Maybe<T>,如在条件中使用时if块,成为Truthy<T>在同一的主体if块和Falsy<T>在else块
This would let you do things like this:
这会让你做这样的事情:
function fn(x: Maybe<Customer>) {
if(x) {
console.log(x.address); // OK
} else {
console.log(x.phone); // Error: x is definitely falsy
}
console.log(x.name); // Warning: x might be falsy!
}
Pretty good so far. Now we can figure out what the type rules are for the && operator.
到目前为止还不错。现在我们可以弄清楚 && 运算符的类型规则是什么。
Truthy<T> && xshould be an error - if the left side is known to be truthy, you should have just writtenxFalsy<T> && xshould be an error - if the left side is known to be falsy,xis unreachable codeMaybe<T> && xshould produce... what?
Truthy<T> && x应该是一个错误 - 如果左侧被认为是真实的,你应该刚刚写xFalsy<T> && x应该是一个错误 - 如果左侧被认为是错误的,x则是无法访问的代码Maybe<T> && x应该产生……什么?
We know the result of Maybe<T> && xwill be either a falsy value of type T, or x. It cannot produce Truthy<T>(unless T== the type of xin which case this entire discussion is moot). Let's call this new type Falsy<T> XOR Maybe<U>.
我们知道 的结果Maybe<T> && x要么是一个类型为 的假值T,要么是x。它不能产生Truthy<T>(除非T== 类型,x在这种情况下整个讨论都没有实际意义)。让我们称这种新类型为Falsy<T> XOR Maybe<U>。
What should the rules of Falsy<T> XOR Maybe<U>be?
规则应该Falsy<T> XOR Maybe<U>是什么?
- Clearly, you can't use properties of
Ton it. If the value is of typeT, it's falsy, and not safe for use. - You should be able to use it as a
Maybe<U>, sinceFalsy<T>andFalsy<U>have the same behaviors - You shouldn't be able to use properties of
U, because the value still might be falsy. - If you use it in an
iftest, then it should become aTruthy<U>in the block of thatifstatement
- 显然,您不能
T在其上使用的属性。如果该值是 typeT,则它是错误的,并且使用起来不安全。 - 您应该能够将其用作
Maybe<U>, 因为Falsy<T>并且Falsy<U>具有相同的行为 - 您不应该使用 的属性
U,因为该值仍然可能为假。 - 如果您在
if测试中使用它,那么它应该成为Truthy<U>该if语句块中的a
In other words, Falsy<T> XOR Maybe<U>isMaybe<U>. It follows all the same rules. You don't need to complicate the type system at all here by adding this weird XORtype, because a type that fits all the specifications you need already exists.
换句话说,Falsy<T> XOR Maybe<U>是Maybe<U>。它遵循所有相同的规则。您完全不需要通过添加这种奇怪的XOR类型来使类型系统复杂化,因为符合您需要的所有规范的类型已经存在。
This is a bit like giving someone a box and saying "This is either an empty box of garbage, or a full box of recyclables". You can safely empty the contents of the box into the recycling bin.
这有点像给某人一个盒子并说“这要么是一盒空垃圾,要么是一整盒可回收物”。您可以安全地将盒子里的东西倒进回收箱。

