Question

Le Tapuscrit de la spécification des états dans le §4.15.6 sur le && opérateur:

L'opérateur& permet de les opérandes d'être de tout type et produit un à la suite du même type que le deuxième opérande.

En Javascript, le && l'opérateur renvoie le premier opérande si c'est falsy, sinon, elle retourne la deuxième opérande (voir ECMA-262 §11.11).

Cela signifie que si l'opérande de gauche est falsy, && renvoie la valeur qui correspond au type de l'opérande de gauche.Par exemple,

typeof ( false && {}      ) === "boolean" // true
typeof ( ''    && 1       ) === "string"  // true
typeof ( null  && "hello" ) === "object"  // true
typeof ( NaN   && true    ) === "number"  // true

Tapuscrit, selon la règle citée ci-dessus, de manière incorrecte prévoir les types des expressions ci-dessus pour être Object, Number, String et Boolean, respectivement.

Ai-je raté quelque chose?Est-il une bonne raison de faire le type d'un && l'expression correspondant au type de la deuxième opérande?Ne devrait pas le type de résultat comporter comme l' || l'opérateur, et le retour le meilleur type le plus commun des deux opérandes, et Any si il n'y a pas de meilleur type le plus commun?

Était-ce utile?

La solution

Longue histoire courte, il n'y a pas de solution ici qui plaît à tout le monde.

Considérer cet idiome commun:

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
}

Ce serait assez boiteux de l'abandonner et de décider que "adresse" est "tout", car il n'y a pas de meilleur type commun entre le Client et l'Adresse.

Dans la majorité des cas où l'opérateur& est utilisé, les types déjà match, ou && est utilisé d'une valeur de coalescence, comme ci-dessus.Dans les deux cas, en retournant le type de l'opérande de droite donne à l'utilisateur le type attendu.

Bien que le type de sécurité est techniquement casser vers le bas à ce point, c'est de ne pas le faire d'une manière qui est susceptible d'entraîner une erreur.Soit vous allez pour tester la valeur résultante de truthiness (dans ce cas, le type est plus ou moins pertinent), ou vous allez utiliser la présomption opérande de droite pour certains de fonctionnement (l'exemple ci-dessus de faire les deux).

Si l'on regarde les exemples que vous avez énumérés, et prétendre que l'opérande de gauche est pour une période indéterminée truthy ou falsy et puis essayez d'écrire sane code qui fonctionne sur la valeur de retour, il devient beaucoup plus claire: il n'y a tout simplement pas beaucoup que vous pouvez faire avec " false && {}' qui n'est pas déjà en cours dans un " tout l'argument de position ou truthiness test.


Addendum

Étant donné que certaines personnes n'ont pas été convaincus par les ci-dessus, voici une explication différente.

Imaginons un instant que le Tapuscrit type de système a ajouté trois nouveaux types: Truthy<T>, Falsy<T>, et Maybe<T>, représentant possible truthy/falsy les valeurs de type T.Les règles pour ces types sont comme suit:

  1. Truthy<T> se comporte exactement comme T
  2. Vous ne pouvez pas accéder à toutes les propriétés de Falsy<T>
  3. Une expression de type Maybe<T>, lorsqu'il est utilisé comme la condition dans une if bloc, devient un Truthy<T> dans le corps de la même if bloc et Falsy<T> dans le else bloc

Cela vous permettrait de faire des choses comme ça:

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!
}

Assez bonne jusqu'à présent.Maintenant, nous pouvons déterminer quel est le type de règles sont pour l'opérateur&.

  • Truthy<T> && x doit être une erreur - si le côté gauche est connu pour être truthy, vous devriez avoir juste écrit x
  • Falsy<T> && x doit être une erreur - si le côté gauche est connu pour être falsy, x est code inaccessible
  • Maybe<T> && x devrait produire...quoi?

Nous savons que le résultat de Maybe<T> && x sera soit un falsy valeur de type T, ou x.Il ne peut pas produire Truthy<T> (à moins que T == le type de x auquel cas, toute cette discussion est sans objet).Appelons ce nouveau type Falsy<T> XOR Maybe<U>.

Quelles devraient être les règles de Falsy<T> XOR Maybe<U> l'être?

  • Clairement, vous ne pouvez pas utiliser les propriétés de T sur elle.Si la valeur est de type T, c'est falsy, et pas sûr pour l'usage.
  • Vous devriez être capable de l'utiliser comme un Maybe<U>, depuis Falsy<T> et Falsy<U> ont les mêmes comportements
  • Vous ne devriez pas être en mesure d'utiliser les propriétés de U, parce que la valeur pourrait être falsy.
  • Si vous l'utilisez dans une if test, alors il devrait devenir un Truthy<U> dans le bloc de if déclaration

En d'autres termes, Falsy<T> XOR Maybe<U> est Maybe<U>.Il suit les mêmes règles.Vous n'avez pas besoin de compliquer le système de type à tous ici, par l'ajout de cette bizarre XOR type, parce qu'un type qui s'adapte à toutes les spécifications sont déjà existantes.

C'est un peu comme donner à quelqu'un une boîte et en disant: "C'est une boîte vide ordures, ou une boîte pleine de matières recyclables".Vous pouvez vider le contenu de la boîte dans le bac de recyclage.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top