Dlaczego operator && produkować typ drugiego argumentu

głosy
24

W specyfikacji wynikowego §4.15.6 temat &&Operator:

Operator && umożliwia operandy być dowolnego typu i wytwarza wynik tego samego typu, jako drugi argument operacji .

W JavaScript &&operator zwraca pierwszy argument operacji, jeżeli jest falsy, w przeciwnym przypadku powrót do drugiego operandu ( patrz ECMA 262 §11.11 ).

Oznacza to, że jeśli lewy argument jest falsy, &&zwróci wartość odpowiadającą rodzajowi lewego argumentu. Na przykład,

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

Maszynopis, zgodnie z zasadą, cytowany powyżej, byłoby nieprawidłowo przewidzieć typy powyższych wyrażeń być Object, Number, Stringi Boolean, odpowiednio.

Ja czegoś brakuje? Czy istnieje dobry powód, aby type &&ekspresji pasować do typu drugiego argumentu? Gdyby nie typ wynik zachowuje się jak ||operator i powrót najlepszy wspólny typ dwoma argumentami, a Anyjeśli nie jest najlepiej popularny typ?

Utwórz 02/10/2012 o 16:50
źródło użytkownik
W innych językach...                            


1 odpowiedzi

głosy
20

Krótko mówiąc, nie ma tu rozwiązanie, które zadowala wszystkich.

Rozważmy ten wspólny 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
}

Byłoby dość kulawy zrezygnować i zdecydować, że „adres” jest „każdy”, ponieważ nie ma najlepszy spotykany typ pomiędzy Klientem i adres.

W większości przypadków, w których operator && jest stosować albo typy już same, lub && jest używany w taki sposób wartości koalescencji jak wyżej. W każdym razie, wracając typ prawego argumentu daje użytkownikowi oczekiwanego typu.

Chociaż bezpieczeństwo typ jest technicznie uszkodzi się w tym momencie, to nie robi tego w sposób, który jest prawdopodobne, aby spowodować wystąpienie błędu. Albo masz zamiar przetestować wypadkową wartość dla truthiness (w tym przypadku typ jest mniej lub bardziej nieistotne), lub masz zamiar użyć wstępną prawy operand jakiegoś działania (przykład powyżej robi obie).

Jeśli spojrzymy na przykładach ty giełdowych i udawać lewy argument jest indeterminately truthy lub falsy a następnie spróbuj napisać sane kod, który działałby na zwracanej wartości, staje się dużo jaśniej - nie tylko wiele można zrobić z „false && {}”, który nie jest już wchodząc w dowolnej pozycji«»argumentu lub testu truthiness.


Uzupełnienie

Ponieważ niektórzy ludzie nie byli przekonani o powyższym, oto inny wyjaśnienie.

Załóżmy, że na chwilę, że system typ maszynopis plus trzy nowe typy: Truthy<T>, Falsy<T>, i Maybe<T>, co stanowi ewentualne truthy / wartości falsy typu T. Zasady te typy są następujące:

  1. Truthy<T> zachowuje się dokładnie tak, jak T
  2. Nie można uzyskać dostępu do żadnych właściwości Falsy<T>
  3. Wyrażenie rodzaju Maybe<T>, gdy stosuje się jako stan, w ifbloku staje się Truthy<T>w organizmie tego samego ifbloku, i A Falsy<T>w elsebloku

To pozwoli Ci robić takie rzeczy:

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

Całkiem dobre do tej pory. Teraz możemy dowiedzieć się, jakie zasady typu są dla operatora &&.

  • Truthy<T> && x powinien być błąd - jeśli po lewej stronie jest znany truthy, należy właśnie napisane x
  • Falsy<T> && xpowinien być błąd - jeśli po lewej stronie jest znany falsy, xjest martwy kod
  • Maybe<T> && x powinny produkować ... co?

Wiemy, że wynikiem Maybe<T> && xbędzie albo falsy wartość typu T, lub x. To nie może produkować Truthy<T>(chyba T== typ xw takim przypadku cała ta dyskusja jest dyskusyjna). Nazwijmy ten nowy typ Falsy<T> XOR Maybe<U>.

Jakie powinny być zasady Falsy<T> XOR Maybe<U>być?

  • Oczywiście, nie można użyć właściwości Tna nim. Jeżeli wartość jest typu T, to falsy, i nie jest bezpieczne do użycia.
  • Powinieneś być w stanie wykorzystać go jako Maybe<U>, skoro Falsy<T>i Falsy<U>mają te same zachowania
  • Nie powinno być w stanie wykorzystać właściwości U, ponieważ wartość nadal może być falsy.
  • Jeśli używamy go w ifteście, to powinno stać się Truthy<U>w bloku z tym ifstwierdzeniem

Innymi słowy, Falsy<T> XOR Maybe<U> jest Maybe<U> . Wynika z tego, wszystkie te same zasady. Nie trzeba skomplikować system typu w ogóle tutaj dodając ten dziwny XORtyp, ponieważ typ, który pasuje do wszystkich specyfikacji musisz już istnieje.

To jest trochę jak dając komuś pole i mówiąc: „To jest albo pusta skrzynka śmieci lub pełne pudełko z surowców wtórnych”. Można bezpiecznie opróżnić zawartość pudełka do kosza.

Odpowiedział 02/10/2012 o 17:55
źródło użytkownik

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