为什么 &&运算符产生第二个操作数的类型 [英] Why does the && operator produce the type of the second operand

查看:24
本文介绍了为什么 &&运算符产生第二个操作数的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TypeScript 规范在 §4.15.6 中关于 && 操作符的说明:

The TypeScript specification states in §4.15.6 about the && operator:

&&运算符允许操作数为任何类型并产生与第二个操作数相同类型的结果.

The && operator permits the operands to be of any type and produces a result of the same type as the second operand.

在 Javascript 中,&& 运算符如果为假则返回第一个操作数,否则返回第二个操作数(参见 ECMA-262 §11.11).

In Javascript, the && operator returns the first operand if it is falsy, otherwise it returns the second operand (see 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,根据上面引用的规则,会错误地预测上述表达式的类型为ObjectNumberStringBoolean,分别.

Typescript, according to the rule quoted above, would incorrectly predict the types of the above expressions to be Object, Number, String and Boolean, respectively.

我错过了什么吗?是否有充分的理由使 && 表达式的类型与第二个操作数的类型相匹配?结果类型不应该像||运算符,返回两个操作数的最佳公共类型,如果没有最佳公共类型,则返回Any?>

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 Any if there is no best common type?

推荐答案

长话短说,这里没有让所有人满意的解决方案.

Long story short, there's no solution here that pleases everyone.

考虑这个常见的习语:

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
}

放弃并决定 'address' 是'any' 是非常蹩脚的,因为 Customer 和 Address 之间没有最好的通用类型.

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.

在大多数情况下 &&使用运算符,类型已经匹配,或者 &&正在以如上所述的价值合并方式使用.无论哪种情况,返回正确操作数的类型都会为用户提供预期的类型.

In the majority of cases where the && operator is used, either the types already match, 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).

如果我们查看您列出的示例并假设左操作数不确定地为真或假,然后尝试编写对返回值进行操作的合理代码,它会变得更加清晰 - 您能做的并不多 'false &&{}' 尚未进入任何"论证立场或真实性测试.

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 do with 'false && {}' that isn't already going into an 'any' argument position or truthiness test.

附录

由于有些人不相信上述内容,这里有不同的解释.

Since some people were not convinced by the above, here's a different explanation.

让我们暂时假设 TypeScript 类型系统添加了三个新类型:TruthyFalsyMaybe,表示 T 类型的可能真/假值.这些类型的规则如下:

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:

  1. Truthy 的行为与 T
  2. 完全一样
  3. 您无法访问 Falsy
  4. 的任何属性
  5. Maybe 类型的表达式,当用作 if 块中的条件时,在同一个 if 块的主体和 else 块中的 Falsy
  1. Truthy<T> behaves exactly like T
  2. You can't access any properties of Falsy<T>
  3. An expression of type Maybe<T>, when used as the condition in an if block, becomes a Truthy<T> in the body of that same if block and a Falsy<T> in the else block

这会让你做这样的事情:

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.

  • 真实&&x 应该是一个错误——如果左边是真实的,你应该只写 x
  • Falsy&&x 应该是一个错误——如果左边是假的,x 是无法访问的代码
  • 也许&&x 应该产生……什么?
  • Truthy<T> && x should be an error - if the left side is known to be truthy, you should have just written x
  • Falsy<T> && x should be an error - if the left side is known to be falsy, x is unreachable code
  • Maybe<T> && x should produce... what?

我们知道Maybe的结果;&&x 要么是 T 类型的假值,要么是 x.它不能产生 Truthy(除非 T == x 的类型,在这种情况下整个讨论都没有实际意义).让我们称这种新类型为 Falsy;异或可能.

We know the result of Maybe<T> && x will be either a falsy value of type T, or x. It cannot produce Truthy<T> (unless T == the type of x in which case this entire discussion is moot). Let's call this new type Falsy<T> XOR Maybe<U>.

Falsy的规则应该是什么?XOR 也许 是?

  • 显然,您不能在其上使用 T 的属性.如果该值的类型为 T,则它是错误的,并且使用起来不安全.
  • 您应该能够将其用作 Maybe,因为 FalsyFalsy 具有相同的行为
  • 您不应该使用 U 的属性,因为该值仍然可能为假.
  • 如果您在 if 测试中使用它,那么它应该在 if 语句的块中变成 Truthy
  • Clearly, you can't use properties of T on it. If the value is of type T, it's falsy, and not safe for use.
  • You should be able to use it as a Maybe<U>, since Falsy<T> and Falsy<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 if test, then it should become a Truthy<U> in the block of that if statement

换句话说,FalsyXOR 可能 is Maybe.它遵循所有相同的规则.您完全不需要通过添加这种奇怪的 XOR 类型来使类型系统复杂化,因为符合您需要的所有规范的类型已经存在.

In other words, Falsy<T> XOR Maybe<U> is Maybe<U>. It follows all the same rules. You don't need to complicate the type system at all here by adding this weird XOR type, because a type that fits all the specifications you need already exists.

这有点像给某人一个盒子,然后说这要么是一盒空垃圾,要么是一整盒可回收物".您可以安全地将盒子里的东西倒进回收箱.

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.

这篇关于为什么 &amp;&amp;运算符产生第二个操作数的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆