De ce operatorul && produce tipul celui de al doilea operand

voturi
24

Specificația typescript state din §4.15.6 despre &&operatorul:

Operatorul && permite operanzi să fie de orice tip și produce un rezultat de același tip ca și al doilea operand .

În JavaScript, &&operatorul returnează primul operand dacă este falsy, altfel returnează al doilea operand ( a se vedea ECMA-262 §11.11 ).

Asta înseamnă că , dacă operandul din stânga este falsy, &&va returna o valoare care se potrivește cu tipul operandului stâng. De exemplu,

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

Typescript, în conformitate cu regula de mai sus citat, ar incorect prezice tipurile de expresiile de mai sus să fie Object, Number, Stringși Boolean, respectiv.

Am pierdut ceva? Există un motiv bun pentru a face tipul de &&expresie se potrivesc cu tipul celui de al doilea operand? Nu ar trebui tipul de rezultat se comportă la fel ca ||operatorul, și să se întoarcă cel mai bun tip comun al celor doi operanzi, iar în Anycazul în care nu există nici un tip este cel mai bun comun?

Întrebat 02/10/2012 la 16:50
sursa de către utilizator
În alte limbi...                            


1 răspunsuri

voturi
20

Pe scurt, nu există nici o soluție aici care place tuturor.

Luați în considerare acest idiom comun:

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
}

Ar fi destul de lame să renunțe și să decidă că „adresa“ este „orice“, pentru că nu există nici cel mai bun tip comun între Client și adresă.

În majoritatea cazurilor în care se utilizează operatorul &&, fie tipurile deja se potrivesc, sau && este utilizat într - o manieră valoare de coalescență ca mai sus. În ambele cazuri, revenind tipul operandului din dreapta oferă utilizatorului tipul de așteptat.

În timp ce siguranța de tip este de rupere jos punct de vedere tehnic, în acest moment, nu face acest lucru într-un mod care ar putea avea ca rezultat o eroare. Ori vei testa valoarea rezultată pentru truthiness (caz în care tipul este mai mult sau mai puțin irelevante), sau ai de gând să utilizați drept prezumtiv pentru operandul o operație (exemplul de mai sus face ambele).

Dacă ne uităm la exemple pe care le enumerate și pretinde că operandul stâng este neprecizat truthy sau falsy și apoi încercați să scrie cod sănătos , care să funcționeze pe valoarea returnată, devine mult mai clar - nu doar de mult vă puteți face cu „fals && {}“ , care nu este deja merge într - o«orice»poziție argument sau testul truthiness.


addenda

Din moment ce unii oameni nu au fost convinși de cele de mai sus, aici este o altă explicație.

Să presupunem pentru un moment că sistemul de tip typescript a adăugat trei noi tipuri: Truthy<T>, Falsy<T>și Maybe<T>, reprezentând valorile posibile truthy / falsy de tip T. Regulile pentru aceste tipuri sunt după cum urmează:

  1. Truthy<T> se comportă exact ca T
  2. Nu puteți accesa orice proprietăți ale Falsy<T>
  3. O expresie de tip Maybe<T>, atunci când este utilizat ca starea într - un ifbloc, devine Truthy<T>în corpul același ifbloc și un Falsy<T>în elsebloc

Acest lucru ar lăsa să faci lucruri de genul asta:

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

Destul de bine până acum. Acum ne putem da seama ce regulile de tip sunt pentru operatorul &&.

  • Truthy<T> && x ar trebui să fie o eroare - în cazul în care partea stângă este cunoscută a fi truthy, ar fi trebuit să doar în scris x
  • Falsy<T> && xar trebui să fie o eroare - în cazul în care partea stângă este cunoscută a fi falsy, xeste imposibil de găsit codul
  • Maybe<T> && x ar trebui să producă ... ce?

Știm rezultatul Maybe<T> && xva fi o valoare falsy de tip Tsau x. Ea nu poate produce Truthy<T>( cu excepția cazului în T== tipul de xcaz în care toată această discuție este controversată). Să numim acest nou tip Falsy<T> XOR Maybe<U>.

Ce ar trebui regulile să Falsy<T> XOR Maybe<U>fie?

  • În mod evident, nu puteți utiliza proprietățile Tpe ea. Dacă valoarea este de tip T, este falsy, și nu în condiții de siguranță pentru utilizare.
  • Tu ar trebui să poată să - l folosească ca Maybe<U>, din moment Falsy<T>și Falsy<U>au aceleași comportamente
  • Nu ar trebui să poată utiliza proprietățile U, deoarece valoarea ar putea fi încă falsy.
  • Dacă îl utilizați într - un iftest de , atunci ar trebui să devină Truthy<U>în blocul acestei ifdeclarații

Cu alte cuvinte, Falsy<T> XOR Maybe<U> este Maybe<U> . Prin urmare , toate aceleași reguli. Nu aveți nevoie pentru a complica sistemul de tip la toate aici prin adăugarea acestui ciudat XORtip, pentru că un tip care se potrivește toate specificațiile de care aveți nevoie există deja.

Acesta este un pic ca da cineva o cutie și spunând „Acesta este fie o cutie goală de gunoi, sau o cutie plină de materiale reciclabile“. Puteți goli în condiții de siguranță a conținutului cutiei în coșul de reciclare.

Publicat 02/10/2012 la 17:55
sursa de către utilizator

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