Почему оператор && производят типа второго операнда

голоса
24

Спецификация машинописи состояние в §4.15.6 о &&операторе:

Оператор && допускает операнды , чтобы быть любого типа и производит результат того же типа, что и второго операнда .

В JavaScript, то &&оператор возвращает первый операнд , если это falsy, в противном случае он возвращает второй операнд ( см ECMA-262 §11.11 ).

Это означает , что , если левый операнд falsy, &&возвращает значение , которое соответствует типу левого операнда. Например,

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

Машинопись, в соответствии с правилом приведенного выше, будет неправильно предсказывать типы приведенных выше выражений , чтобы быть Object, Number, Stringи Boolean, соответственно.

Я что-то упускаю? Есть хорошая причина , чтобы сделать тип из &&выражения соответствует типу второго операнда? Должно ли не тип результата ведет себя как ||оператор, и вернуть лучший общий тип двух операндов, а Anyесли нет лучшего общий типа?

Задан 02/10/2012 в 16:50
источник пользователем
На других языках...                            


1 ответов

голоса
20

Короче говоря, нет никакого решения здесь, что радует всех.

Рассмотрим эту общую идиому:

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
}

Было бы довольно хромым отказаться и решить, что «адрес» есть «любой», потому что нет лучше общего типа между Клиентом и адресом.

В большинстве случаев , когда используется оператор &&, либо типа уже совпадают, или && используется таким образом , стоимость коалесценции , как и выше. В любом случае, возвращаясь тип правого операнда дает пользователю ожидаемый тип.

В то время как безопасность типа технически разрушения на данный момент, это не делает это таким образом, что это может привести к ошибке. Либо вы собираетесь проверить результирующее значение для truthiness (в этом случае типа является более или менее не имеет значения), или вы собираетесь использовать предположительный правый операнд для некоторой операции (пример выше) и делает.

Если мы посмотрим на примеры , которые вы перечислили , и делать вид , левый операнд неопределенно truthy или falsy , а затем попытаться написать вменяемый код , который будет работать на возвращаемое значение, становится намного яснее - там просто не так много вы можете сделать с «ложным && {}» , что уже не собираюсь в„любой“позицию аргумента или тест truthiness.


добавление

Так как некоторые люди не были убеждены выше, здесь другое объяснение.

Давайте представим на минуту , что система типа машинопись добавлены три новых типа: Truthy<T>, Falsy<T>и Maybe<T>, представляя возможные truthy / falsy значения типа T. Правила для этих типов заключаются в следующем:

  1. Truthy<T> ведет себя так же, как T
  2. Вы не можете получить доступ к любому свойства Falsy<T>
  3. Выражение типа Maybe<T>, при использовании в качестве условия в ifблоке, становится Truthy<T>в теле того же ifблока и Falsy<T>в elseблоке

Это позволит вам сделать что-то вроде этого:

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

Довольно хорошо до сих пор. Теперь мы можем понять, что правила типа являются для оператора &&.

  • Truthy<T> && x должна быть ошибка - если левая сторона, как известно truthy, вы должны просто написали x
  • Falsy<T> && xдолжна быть ошибка - если левая сторона , как известно, falsy, xнедостижима код
  • Maybe<T> && x должен производить ... что?

Мы знаем , что результат Maybe<T> && xбудет либо falsy значения типа T, или x. Он не может производить Truthy<T>(если T== типа xв этом случае вся эта дискуссия является спорной). Давайте назовем этот новый тип Falsy<T> XOR Maybe<U>.

Что правила должны Falsy<T> XOR Maybe<U>быть?

  • Очевидно, что вы не можете использовать свойства Tна нем. Если значение имеет тип T, это falsy, и не безопасно для использования.
  • Вы должны быть в состоянии использовать его в качестве Maybe<U>, так Falsy<T>и Falsy<U>имеют одни и те же модели поведения
  • Вы не должны быть в состоянии использовать свойство U, так как значение по- прежнему может быть falsy.
  • Если вы используете его в ifтесте, то он должен стать Truthy<U>в блоке этого ifзаявления

Другими словами, Falsy<T> XOR Maybe<U> это Maybe<U> . Из этого следует , все те же правила. Вам не нужно усложнять систему типа вообще здесь, добавив этот странный XORтип, так как тип , который соответствует всем спецификациям, нужно уже существует.

Это немного походит на предоставление кому-то коробку и говорит: «Это либо пустая коробка мусора, или полный ящик вторсырья». Вы можете безопасно очистить содержимое коробки в мусорный ящик.

Ответил 02/10/2012 в 17:55
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more