TypeScript acceptă operatorul ?. ? (Și, cum se numește?)
TypeScript suportă în prezent (sau există planuri să suporte) operatorul de navigare sigur ?.?
ie :
var thing = foo?.bar
// same as:
var thing = (foo) ? foo.bar : null;
De asemenea, există un nume mai comun pentru acest operator (este incredibil de greu de căutat pe Google).
Răspuns #1
Da. Începând cu TypeScript 3.7 (lansat pe 5 noiembrie 2019), această funcționalitate este acceptată și se numește Optional Chaining:
În esență, lanțul opțional ne permite să scriem cod în care TypeScript poate opri imediat executarea unor expresii dacă întâlnim un
nullsauundefined. Vedeta lanțului opțional este noul operator?.pentru accesările opționale ale proprietăților.
Consultați notele de lansare TypeScript 3.7 pentru mai multe detalii.
Înainte de versiunea 3.7, acest lucru nu era suportat în TypeScript, deși a fost solicitat încă de la Issue #16 din depozitul TypeScript (datând din 2014).
Cât despre cum să numim acest operator, nu pare să existe un consens. Pe lângă „optional chaining” (care este, de asemenea, cum este numit în JavaScript și Swift), există câteva alte exemple:
- CoffeeScript se referă la aceasta ca la operatorul existențial (mai precis, „varianta accessor” a operatorului existențial):
Varianta accessor a operatorului existențial
?.poate fi folosită pentru a absorbi referințele null într-un lanț de proprietăți. Folosește-o în locul accessorului punct.în cazurile în care valoarea de bază poate fi null sau undefined.
- C# numește aceasta un operator condițional nul.
un operator null-condițional aplică o accesare de membru,
?., sau o accesare de element,?[], operandului său doar dacă acel operand se evaluează ca non-null; altfel, returneazănull.
- Kotlin se referă la asta ca la operatorul de apel sigur.
Probabil că există și multe alte exemple.
Răspunsul #2
Acum este posibil, vezi răspunsul utilizatorului „Donut”.
Răspuns vechi: Comportamentul standard JavaScript în ceea ce privește operatorii booleani are ceva care ar putea ajuta. Metodele booleene nu returnează true sau false atunci când compară obiecte, dar în cazul OR primul valoare care este egală cu true.
Nu la fel de plăcut ca un singur ?, dar funcționează:
var thing = foo && foo.bar || null;
Poți folosi câte && vrei:
var thing = foo && foo.bar && foo.bar.check && foo.bar.check.x || null;
Valorile implicite sunt de asemenea posibile:
var name = person && person.name || "Unknown user";
Răspunsul #3
Acest lucru este definit în specificația ECMAScript despre lanțul opțional, așa că ar trebui probabil să ne referim la lanțul opțional atunci când discutăm despre acesta. Implementarea probabilă:
const result = a?.b?.c;
Pe scurt, echipa TypeScript așteaptă ca specificația ECMAScript să fie întărită, astfel încât implementarea lor să nu ducă la probleme în viitor. Dacă ar implementa ceva acum, ar ajunge să necesite modificări majore dacă ECMAScript își redefineste specificația.
Consultați specificația lanțului opțional
Atunci când ceva nu va fi niciodată JavaScript standard, echipa TypeScript poate implementa cum consideră potrivit, dar pentru viitoarele adăugiri ECMAScript, ei doresc să păstreze semantica chiar dacă oferă acces timpuriu, așa cum au făcut pentru atât de multe alte caracteristici.
Scurtături
Deci toți operatorii ciudați din JavaScript sunt disponibili, inclusiv conversiile de tip, cum ar fi...
var n: number = +myString; // convert to number
var b: bool = !!myString; // convert to bool
Soluție manuală
Dar să revenim la întrebare. Am un exemplu absurd despre cum poți face un lucru similar în JavaScript (și, prin urmare, TypeScript), deși cu siguranță nu sugerez că este la fel de elegant ca funcția pe care o cauți cu adevărat.
(foo||{}).bar;
Deci, dacă foo este undefined, rezultatul este undefined, iar dacă foo este definit și are o proprietate numită bar care are o valoare, rezultatul este acea valoare.
Am pus un exemplu pe JSFiddle.
Acesta pare destul de dubios pentru exemple mai lungi.
var postCode = ((person||{}).address||{}).postcode;
Funcție lanț
Dacă ești disperat după o versiune mai scurtă în timp ce specificația încă nu este clară, folosesc această metodă în unele cazuri. Ea evaluează expresia și returnează un valoare implicită dacă lanțul nu poate fi satisfăcut sau ajunge la null/undefined (observă că != este important aici, nu vrem să folosim !== deoarece ne dorim puțin jonglat pozitiv aici).
function chain<T>(exp: () => T, d: T) {
try {
let val = exp();
if (val != null) {
return val;
}
} catch { }
return d;
}
let obj1: { a?: { b?: string }} = {
a: {
b: 'c'
}
};
// 'c'
console.log(chain(() => obj1.a.b, 'Nothing'));
obj1 = {
a: {}
};
// 'Nothing'
console.log(chain(() => obj1.a.b, 'Nothing'));
obj1 = {};
// 'Nothing'
console.log(chain(() => obj1.a.b, 'Nothing'));
obj1 = null;
// 'Nothing'
console.log(chain(() => obj1.a.b, 'Nothing'));
Răspunsul #4
Actualizare: Da, este suportat acum!
A fost lansat recent împreună cu TypeScript 3.7 : https://devblogs.microsoft.com/typescript/announcing-typescript-3-7/
Se numește lanț opțional : https://devblogs.microsoft.com/typescript/announcing-typescript-3-7/#optional-chaining
Cu el următoarele:
let x = foo?.bar.baz();
este echivalent cu:
let x = (foo === null || foo === undefined) ?
undefined :
foo.bar.baz();
Răspuns vechi
Există o cerere de funcționalitate deschisă pentru acest lucru pe GitHub, unde vă puteți exprima opinia/dorința: https://github.com/Microsoft/TypeScript/issues/16
Răspunsul #5
Editează 13 nov. 2019!
Începând cu 5 noiembrie 2019, TypeScript 3.7 a fost lansat și acum suportă ?. operatorul de concatenare opțională 🎉🎉🍾🍾🎉!!!
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#optional-chaining
Doar în scopuri istorice:
Editare: Am actualizat răspunsul mulțumită comentariului lui fracz.
TypeScript 2.0 lansat !. Nu este același cu ?. (Navigator sigur în C#)
Vezi acest răspuns pentru mai multe detalii:
https://stackoverflow.com/a/38875179/1057052
Acest lucru va spune compilatorului doar că valoarea nu este null sau undefined. Acest lucru nu va verifica dacă valoarea este null sau undefined.
Operatorul de afirmație non-null în TypeScript
// Compiled with --strictNullChecks
function validateEntity(e?: Entity) {
// Throw exception if e is null or invalid entity
}
function processEntity(e?: Entity) {
validateEntity(e);
let s = e!.name; // Assert that e is non-null and access name
}
Răspuns #6
Operatorul Elvis (?.) pentru acces opțional este acceptat în TypeScript 3.7.
Poți să îl folosești pentru a verifica valorile nule: cats?.miows returnează null dacă cats este null sau undefined.
Poți să îl folosești și pentru apelarea metodă opțională: cats.doMiow?.(5) va apela doMiow dacă acesta există.
Accesul la proprietăți este de asemenea posibil: cats?.['miows'].
Referință: https://devblogs.microsoft.com/typescript/announcing-typescript-3-7-beta/
Răspunsul #7
Este în sfârșit aici!
Iată câteva exemple:
// properties
foo?.bar
foo?.bar()
foo?.bar.baz()
foo?.bar?.baz()
// indexing
foo?.[0]
foo?.['bar']
// check if a function is defined before invoking
foo?.()
foo.bar?.()
foo?.bar?.()
Dar nu funcționează exact la fel ca presupunerea ta.
În loc să evalueze
foo?.bar
la această mică bucată de cod la care suntem cu toții obișnuiți să scriem
foo ? foo.bar : null
de fapt se evaluează la
(foo === null || foo === undefined) ?
undefined :
foo.bar
care funcționează pentru toate valorile falsy, cum ar fi un șir gol, 0 sau false.
Pur și simplu nu am o explicație pentru motivul pentru care nu îl compilează la foo == null
Răspuns #8
Operatorul ?. nu este acceptat în TypeScript versiunea 2.0.
Așadar, folosesc următoarea funcție:
export function o<T>(someObject: T, defaultValue: T = {} as T) : T {
if (typeof someObject === 'undefined' || someObject === null)
return defaultValue;
else
return someObject;
}
utilizarea arată astfel:
o(o(o(test).prop1).prop2
în plus, poți seta o valoare implicită:
o(o(o(o(test).prop1).prop2, "none")
Funcționează foarte bine cu IntelliSense în Visual Studio.
