Typescript: Saran: "operator navigasi aman", yaitu x?.y

Dibuat pada 15 Jul 2014  ·  205Komentar  ·  Sumber: microsoft/TypeScript

Status terkini

  • Proposal TC39 sekarang berada di tahap 3 (🎉🎉🎉🎉🎉)
  • Implementasi sedang berlangsung
  • Anda dapat mengharapkan fitur ini di TypeScript 3.7
  • Kami akan memperbarui di sini ketika tersedia di build malam
  • Menunda Panggilan Opsional sampai semantiknya diklarifikasi di komite

Pertanyaan-pertanyaan terbuka

  • Casing khusus apa, jika ada, yang harus didapatkan document.all ?

C# dan bahasa lain memiliki gula sintaksis untuk mengakses rantai properti di mana null (atau dalam kasus kami, undefined ) mungkin ditemukan pada titik mana pun dalam hierarki objek.

var x = { y: { z: null, q: undefined } };
console.log(x?.y?.z?.foo); // Should print 'null'
console.log(x?.baz); // Still an error
console.log(x.y.q?.bar); // Should print 'undefined'

Butuh proposal tentang apa sebenarnya yang harus kita codegen, mengingat efek samping dari pengakses.


Sunting oleh @DanielRosenwasser 27 Februari 2018: Proposal ini juga disebut operator "propagasi nol".

Committed ES Next Suggestion Update Docs on Next Release

Komentar yang paling membantu

Chaining Opsional adalah Tahap 3

Membuka kunci ini secara singkat hanya untuk tujuan perayaan

Semua 205 komentar

Jadi pada contoh pertama, kita mungkin memancarkannya seperti berikut:

x && xy && xyz && xyzfoo

Tapi kemudian kita harus entah bagaimana membuat x, y, z, dan foo masing-masing mengevaluasi paling banyak satu kali.

Anda juga benar-benar tidak dapat melakukan && dalam banyak kasus karena kejujuran menjadi sedikit masalah bagi primitif.

Sebagai contoh:

"     "?.trim()?.indexOf("hello")

memberikan "" .

Jadi, Anda perlu melakukan beberapa perbandingan eksplisit dengan null menggunakan == untuk kasus umum, kecuali jika kami memanfaatkan sistem tipe (yang akan cukup keren untuk melihat kami melakukannya).

Kami mungkin dapat memancarkan fungsi monadic-bind (tidak cantik untuk output JS), atau menggunakan beberapa transformasi pada operator ternary (lebih dekat dengan JS yang setara). Saya jelas sedikit bias terhadap yang terakhir.

:+1:

Idealnya kita memiliki ES7 (atau ES8 atau ES9 atau ...) mengimplementasikan ini terlebih dahulu karena mungkin akan ada beberapa ketidaksepakatan tentang semantik yang tepat tentang apakah akan benar-benar menggunakan 0 / "" sebagai primitif palsu untuk keperluan operator apa pun di sini.

:+1: Saya ingin melihat TypeScript mendapatkan ini terlebih dahulu tanpa harus menunggu ESxx.

Fakta bahwa operator null-safety sederhana dan sangat berguna seperti "?." dan "?:" BUKAN dalam spesifikasi ES6 berarti orang-orang yang menyusun spesifikasi ES6 harus menundukkan kepala karena malu. Ini adalah hal yang sangat sederhana dan jelas sehingga tidak memasukkannya sejujurnya akan menjadi gila. Ada alasan mengapa sebagian besar bahasa modern mendukung ini: mereka sangat diperlukan.

Saya menyadari ini akan menjadi penyimpangan dari spesifikasi saat ini (karena spesifikasi saat ini sangat picik untuk menghilangkan ini). Tapi itu sangat berguna sehingga saya pikir penyimpangan tunggal ini bisa dibenarkan. Sebagian besar (VAST) pengembang TS tidak akan terpengaruh oleh perubahan kecil pada implementasi, jika atau ketika ini akhirnya ditambahkan ke spesifikasi ES. Manfaat besar yang ditawarkan ini sebanding dengan potensi dampak masa depan bagi sebagian kecil pengembang. Dan mengingat proses spesifikasi ES yang sangat lambat, ini bahkan tidak masalah sama sekali selama beberapa tahun (minimal).

Saya sangat setuju dengan brain428

@ brian428 masalahnya di sini adalah bahwa operator itu mungkin diimplementasikan di ES7 jadi jika TypeScript pergi dengan spesifikasi yang akhirnya berbeda dari ES7 final, tidak ada yang akan senang.

masalahnya di sini adalah bahwa operator itu mungkin diimplementasikan di ES7 jadi jika TypeScript pergi dengan spesifikasi yang akhirnya berbeda dari ES7 final, tidak ada yang akan senang.

Saya pikir ini adalah pendekatan yang lebih positif untuk TypeScript untuk mengimplementasikan fitur yang mungkin _berpotensi _ (atau mungkin tidak) membuatnya menjadi versi ES di masa mendatang, karena itu akan menjadi testbed yang berguna untuk mempengaruhi arah ES.

Berikut adalah contoh diskusi ES yang dipengaruhi oleh TypeScript :

Opsi TypeScript... untuk mendeklarasikan dan menginisialisasi melalui awalan pribadi pada salah satu parameter konstruktor akan membantu banyak pengembang

Selain itu, ES tentu saja mungkin untuk mengadopsi fitur yang sudah ada di TypeScript, tetapi dengan semantik yang berbeda (misalnya, seputar cara kerja modul).

ES tentu saja mungkin untuk mengadopsi fitur yang sudah ada di TypeScript, tetapi dengan semantik yang berbeda

Saya harus mencatat bahwa kami secara luas menganggap ini sebagai skenario terburuk. Kami benar-benar ingin modul di ES6 diselesaikan sebelum kami mendeklarasikan TypeScript 1.0, tetapi penundaan jadwal komite mencegahnya. Ini adalah sesuatu yang harus dihindari, tidak diulang. Kami benar-benar ingin mendapatkan fitur yang memiliki peluang ~0% untuk membuatnya menjadi ES7+ (mis. anotasi jenis), atau memiliki peluang ~100% untuk masuk dengan semantik yang mudah ditentukan (mis. di mana panah gemuk adalah dua bertahun-tahun lalu). Operator baru cenderung jatuh di tengah canggung.

Dalam kasus terburuk, jika ES7 berbeda, dapatkah flag compiler mendukung implementasi TS lama, sehingga menawarkan masa tenggang? Ini ditambah dengan dokumentasi migrasi yang jelas harus menawarkan pengembang rute langsung ke standar baru apa pun.

Pada akhirnya, penggunaan fitur semacam itu—walaupun sangat berguna—tidaklah penting bagi pengembang. TS harus membuat potensi implikasi masa depan dari penggunaannya sangat jelas sejak hari pertama. Tidak menyukai gagasan refactor terkelola potensial, jangan gunakan itu. Mungkin flag compiler opt-in untuk menegakkan pesan ini?

TS seharusnya tidak menjadi liar dengan keinginan untuk mempengaruhi ES, tetapi dalam kasus-kasus kecil yang terisolasi seperti ini, akan sangat disayangkan jika TS benar-benar menghindar.

Mungkin kita bisa menyusun proposal strawman untuk ini dan kemudian memiliki implementasi referensi di belakang flag --harmony (atau sesuatu seperti itu). Dengan begitu kita bisa mendorong pengembangan ES7 fitur ini.

Untuk mencegah efek samping karena pencarian berulang, kompiler harus mengeluarkan variabel sementara:

($tmp0 = x, $tmp0 === void 0 ? void 0 : 
    ($tmp1=$tmp0.y,  $tmp1 === void 0 ? void 0 : 
        ($tmp2 = $tmp1.z,  $tmp2 === void 0 ? void 0 : $tmp2)))

atau gunakan membran memoisasi berdasarkan Proxy .

Dari sudut pandang kategoris, ini hanya monad yang mungkin diterapkan pada pencarian properti, jadi ini adalah fitur yang sangat alami untuk bahasa di mana semua pencarian properti mungkin tidak terdefinisi. Saya akan terkejut jika ES7 mengadopsi semantik selain yang dijelaskan oleh kode di atas.

Masalah codeplex memiliki cukup banyak suara (61)

Saya sangat membutuhkan ini untuk mengurangi rasa sakit menggunakan atom untuk atom-typescript .

Ini sangat idiomatis dalam kode coffescript (walaupun saya ingin itu tidak sepopuler determinisme lebih baik daripada fudgy ? ). Buka file coffescript apa pun, terutama yang bekerja dengan DOM secara langsung seperti space-pen (di mana fungsi dapat berjalan setelah tampilan dihancurkan atau sebelum tampilan dilampirkan) dan Anda akan menemukan penggunaan trilyun ? . misalnya file ini memiliki 16 https://github.com/atom-community/autocomplete-plus/blob/f17659ad4fecbd69855dfaf00c11856572ad26e7/lib/suggestion-list-element.coffee

Sekali lagi saya tidak suka bahwa saya membutuhkan ini, tetapi ini adalah keadaan JavaScript, dan saya lebih suka ? daripada satu juta if( && fest ) { then }

Tetapi saya benar-benar membutuhkannya agar kode saya dapat dibaca. Ini juga sangat umum untuk _memerlukan_ ini ketika Anda menunggu XHR selesai dan angular menjalankan loop intisarinya.

Oke sekarang saya telah membaca utas dan melihat mengapa kami menunggu. Saya mengerti _sigh_.

we'd have to somehow make x, y, z, and foo each evaluate at most once.

coffeescript memang melakukan beberapa optimasi misalnya menyimpan hasil akses perantara :

typeof foo !== "undefined" && foo !== null ? (ref = foo.bar) != null ? ref.baz() : void 0 : void 0;

(Saya sangat merasa cek undefined tidak diperlukan untuk TypeScript : karena kita seharusnya memiliki var init typechecked by TypeScript)

+1

Dalam berita hari ini, Dart mendapatkan dukungan resmi untuk itu: https://github.com/gbracha/nullAwareOperators/blob/master/proposal.md

Fitur yang sangat penting.

Mungkin ide yang tidak masuk akal tetapi codegen untuk fitur ini dapat dilakukan dengan sangat mudah tanpa efek samping jika semua orang memutuskan bahwa tidak apa-apa untuk menangani fitur dengan akses properti yang dikunci:

if (aaa?.bbb?.ccc) {}

Bisa dikompilasi ke

if (__chain(aaa, "bbb", "ccc")) {}

Fungsi __chain harus dipancarkan mirip dengan __extends . Fungsi __chain hanya dapat diulang melalui array arguments , mengembalikan null ketika anggota yang akan datang bukan instanceof Object atau tidak berisi nama anggota. Panggilan fungsi dapat ditangani dengan meneruskan array sebagai parameter (dan menggunakan .apply() di bawah penutup), jadi ...

if (aaa?.bbb?.ccc?(1, 2, 3)) {}

Bisa dikompilasi ke

if (__chain(aaa, "bbb", "ccc", [1, 2, 3])) {}

Ini juga akan membuat JS yang dihasilkan cukup idiomatis, bahkan untuk rantai panjang.

Perlu perbaikan jelas ... tapi mungkin ada sesuatu di sini?

Jika aaa?.bbb?.ccc? mengembalikan nilai a.b.c jika semua props ada dan itu adalah fungsi, maka tidak bisa

if (aaa?.bbb?.ccc?(1, 2, 3)) {}

kompilasi ke

if (__chain(aaa, "bbb", "ccc")(1, 2, 3)) {}

?

@metaweta : Solusi Anda hanya memeriksa void 0 ... bukankah itu mengalahkan tujuan fitur?

Bagaimana dengan ini:

var result = one?.two?.three;

Menghasilkan:

var $a, $b, $c;
var result = $a = one, $b = $a ? $a.two : void 0, $b ? $b.three : void 0;

Saya cukup yakin ini menangani semua kasus. Panggilan fungsi mungkin memerlukan cek instanceof Function .

(Kelemahan kecil di sini dari variabel lokal tak terduga yang dipancarkan ... mungkin bisa dibungkus dengan IIFE)

@kevinb7 : Apa yang terjadi jika ccc bukan fungsi? Dengan kode yang telah Anda jelaskan, __chain akan selalu mengembalikan fungsi yang valid, atau TypeError akan dipancarkan.

@Back-io Ketika properti tidak ada, pencarian mengembalikan undefined === void 0. Solusi Anda gagal mencari properti nilai falsey seperti string kosong dan nol.

@metaweta : Tidak, tidak: http://jsfiddle.net/25LppbL6/

Juga, saya akan membayangkan tim TS tidak tergila-gila menggunakan kesetaraan longgar karena fakta bahwa beberapa linter orang memperingatkan untuk tidak melakukannya.

@Back-io Ya memang: http://jsfiddle.net/25LppbL6/2/

@Back-io Mengenai null, saya tidak yakin apa semantik yang dimaksud dari a?.b. Jika "Jika properti b didefinisikan kemudian gunakan", maka kode saya hampir benar. Satu-satunya cara Anda mendapatkan null adalah jika itu ditetapkan sebagai null, karena pencarian properti yang tidak ada menghasilkan tidak terdefinisi. Itu gagal untuk menangkap kasus di mana properti itu ada tetapi disetel ke tidak terdefinisi. Agar sepenuhnya benar, itu akan memeriksa dengan Object.hasOwnProperty() alih-alih membandingkan dengan void 0 === undefined.

Jika semantiknya adalah "jika properti b benar maka gunakan itu", kode Anda baik-baik saja dan sampai batas tertentu cocok dengan idiom JS.

Umm ... kecuali saya melewatkan sesuatu ... perubahan yang Anda buat pada biola lebih jauh membuktikan saya benar ... var result masih undefined dalam semua 3 kasus. Dan saya tidak yakin kasus apa yang Anda coba kemukakan dengan memperluas prototipe primitif ...

Saya cukup yakin bahwa perilaku fitur tersebut adalah hubungan pendek dengan void 0 alih-alih menghasilkan kesalahan. (Saya suka ide Anda di atas bahwa itu harus selalu mengembalikan void 0 jika ada anggota yang hilang).

Apa keluaran yang diinginkan dari ''?.toString ?

@kevinb7 : Apa yang terjadi jika ccc bukan fungsi? Dengan kode yang telah Anda jelaskan, __chain harus selalu mengembalikan fungsi yang valid, atau TypeError akan dipancarkan.

Poin bagus.

@metaweta : Saya akan membayangkan kebanyakan orang akan mengharapkan referensi ke fungsi toString , jadi saya melihat di mana maksud Anda, Ini agak rusak dalam kasus di mana Anda mengakses anggota prototipe 0, false, atau ''.

:+1:
Angular 2 menambahkan Operator Elvis ke sintaks template mereka

@metaweta :

Apa keluaran yang dimaksud dari ''?.toString?

Jika yang Anda maksud ''?.toString() itu akan menjadi:

if ('' != null) {
  ''.toString();
}

Sampel

Mungkin kita bisa menyusun proposal strawman untuk ini

@kevinb7 sudah ada : http://wiki.ecmascript.org/doku.php?id=strawman :existential_operator

Saya melakukan beberapa tes cepat untuk mengimplementasikan ini di atas PropertyAccessExpression sebagai kasus khusus tetapi tidak berhasil dengan baik karena kami benar-benar membutuhkan ?. untuk menjadi asosiatif kanan (bukan asosiatif kiri seperti . ) jika tidak, emitor menjadi kompleks yang tidak perlu.

Ada komentar oleh BrendenEich di sini yang mencerminkan hal ini juga.

Saya melakukan beberapa tes cepat untuk mengimplementasikan ini di atas PropertyAccessExpression sebagai kasus khusus tetapi tidak berhasil dengan baik karena kami benar-benar membutuhkan ?. menjadi asosiatif kanan (bukan asosiatif kiri seperti .) jika tidak, emitor menjadi kompleks yang tidak perlu.

@basarat bisa tolong jelaskan itu? Contoh perbedaan antara asosiatif kanan dan asosiatif kiri ?. akan sangat membantu saya.

@zlumer

Contoh perbedaan antara asosiatif kanan dan asosiatif kiri?. akan sangat membantu saya.

. dibiarkan asosiatif sehingga ekspresi foo?.bar?.baz menjadi AST (jika kita memperlakukan ?. sama):

                    // foo.bar.baz = PropertyAccessExpression
                    //   .expr foo.bar =  PropertyAccessExpression
                    //     .expr foo = Identifier
                    //     .name bar = Identifier
                    //   .name baz = Identifier

Emisi JavaScript yang dibutuhkan adalah

foo != null ? (ref_1 = foo.bar) != null ? ref_1.baz() : void 0 : void 0;

Lebih mudah untuk melakukan emisi ini (terutama _rekursif_) jika kita memiliki yang berikut di AST:

                    // foo.bar.baz = PropertySafeAccessExpression
                    //   .name foo =  Identifier
                    //   .expr bar.baz = PropertySafeAccessExpression
                    //      .expr bar = Identifier
                    //      .name baz = Identifier

Pikirkan saja _bagaimana Anda mengonversi AST pertama ke JavaScript_ dan kerumitannya akan lebih jelas. Semoga membantu :rose:

@zlumer , untuk menambahkan apa yang @basarat katakan, saya hanya akan memberikan contoh 1 + 2 + 3 .

Saat parsing, kita harus memutuskan operasi mana yang akan terjadi terlebih dahulu.

Jika + adalah asosiatif kiri, ini akan ditafsirkan sebagai ((1 + 2) + 3) .

Jika + adalah asosiatif kanan, ini akan ditafsirkan sebagai (1 + (2 + 3)) .

Anda mungkin mempertanyakan apakah ini benar-benar akan membuat perbedaan. Dalam JavaScript itu akan! Perhatikan contoh "hello" + 2 + 3 .

  • Asosiatif kiri: (("hello" + 2) + 3) => ("hello2" + 3) => "hello23"
  • Asosiatif kanan: ("hello" + (2 + 3)) => ("hello" + 5) => "hello5"

(Sebagai catatan, JavaScript/TypeScript menggunakan asosiasi kiri untuk operator + .)

@basarat , pemahaman saya tentang apa yang dikatakan @BrendanEich (dan dia dapat mengoreksi saya jika saya salah - maaf atas pingnya!) adalah _not_ bahwa ?. adalah asosiatif-benar, tetapi properti kasus khusus CoffeeScript mengakses hak dari ?. menjadi asosiatif-kanan. Misalnya, itu akan mengurai

o.p?.q.r.s

sebagai

((o . p) ?. (q . (r . s))) # or something close to this

dari pada

((((o . p) ?. q) . r) . s)

karena lebih mudah dikeluarkan.

AST kami perlu meminjamkan dengan baik untuk analisis semantik yang waras, sehingga prosedur pemancaran kami dapat menjadi sedikit lebih kompleks untuk memenuhi kebutuhan ini.

@basarat @DanielRosenwasser terima kasih atas penjelasannya. Sejauh ini saya memahaminya, tetapi saya masih tidak yakin tentang satu hal.
Asosiatif kiri ?. cukup jelas dan diharapkan:

foo?.bar?.baz

Menjadi (perkiraan):

var ref = ((ref = foo) == null) ? null : ((ref = ref.bar) == null) ? null : ref.baz;

Tetapi saya tidak mengerti sama sekali bagaimana cara kerja asosiatif kanan ?. . Bisa tolong berikan contohnya?

Tapi saya sama sekali tidak mengerti bagaimana asosiatif benar?. kerja. Bisa tolong berikan contohnya

@zlumer Perilaku runtime akan dibiarkan asosiatif. Saya baru saja berbicara tentang AST karena DanielRosenwasser juga mengklarifikasi: is not that ?. is right-associative, but that CoffeeScript special cases property accesses on the right of the ?. to be right-associative .

AST kami perlu meminjamkan dengan baik untuk analisis semantik yang waras, sehingga prosedur pemancaran kami dapat menjadi sedikit lebih kompleks untuk memenuhi kebutuhan ini.

@DanielRosenwasser terima kasih atas umpan baliknya :rose:

@basarat terima kasih, tiba-tiba semuanya menjadi jelas :smiley:

Mirip dengan komentar Feb @basarat , saya.... _sigh_...

Namun, jika Anda memikirkannya, 99% dari kasus penggunaan ini adalah untuk memeriksa penunjuk nol ke suatu objek. Terus terang, siapa yang melakukan x?.b?.c ketika x adalah number ? Tidak banyak kasus penggunaan kehidupan nyata untuk rantai _long_ ketika kita _not_ berbicara tentang suatu objek (dengan kemungkinan pengecualian string ). Untuk rantai pendek, saya pikir kita bisa hidup dengan x && x.b atau x === 0 ? null : x.b .

Jadi, bisakah kita, agaknya, mengatakan ?. hanya berfungsi pada tipe objek? Jenis lain apa pun menimbulkan kesalahan sintaksis. Dan larang panggilan fungsi di sisi rantai.

Kemudian semuanya ditranskripsi menjadi a && a.b && a.b.c .

@schungx Bagaimana jika anggota dalam rantai adalah tipe "apa saja"? Larang sepenuhnya? Atau biarkan saja dan berharap yang terbaik?

Nah, saran saya? Larang sepenuhnya. Tidak elegan sekali, saya tahu ... :-)

Tapi alasan saya:

  1. Ini adalah short-hand, jadi jika seseorang menggunakan any , gunakan saja long-hand.
  2. Jika seseorang menggunakan TypeScript, kemungkinan besar dia menggunakannya untuk dukungan pengetikan, jadi semoga dia tidak memiliki banyak any !
  3. any benar-benar harus ditangani dengan hati-hati. Mengizinkan penggunaan singkatan seperti itu dengan tipe fleksibel seperti any benar-benar meminta bug terjadi. Menurut pendapat saya, any harus dibatasi mungkin. Ini seperti (void *) milik C -- fakta bahwa Anda diberikan nuklir tidak berarti Anda harus memicunya hanya karena Anda bisa!

Ini akan menjadi operator yang luar biasa!! Khusus untuk ES6 / ES7 / TypeScript

var error = a.b.c.d; //this would fail with error if a, b or c are null or undefined.
var current = a && a.b && a.b.c && a.b.c.d; // the current messy way to handle this
var currentBrackets = a && a['b'] && a['b']['c'] && a['b']['c']['d']; //the current messy way to handle this
var typeScript = a?.b?.c?.d; // The typescript way of handling the above mess with no errors
var typeScriptBrackets = a?['b']?['c']?['d']; //The typescript of handling the above mess with no errors

Namun saya mengusulkan yang lebih jelas - agar tidak membingungkan? dari ? b : pernyataan c dengan pernyataan a?.b:

var doubleDots = a..b..c..d; //this would be ideal to understand that you assume that if any of a, b, c is null or undefined the result will be null or undefined.
var doubleDotsWithBrackets = a..['b']..['c']..['d'];

Untuk notasi braket, saya merekomendasikan dua titik alih-alih satu titik karena konsisten dengan yang lain saat tidak menggunakan tanda kurung. Karenanya hanya nama properti yang statis atau dinamis melalui tanda kurung.

Dua titik, berarti jika nol atau tidak terdefinisi berhenti memproses lebih lanjut dan menganggap hasil ekspresi adalah nol atau tidak terdefinisi. (seperti d akan menjadi nol atau tidak terdefinisi).

Dua titik membuatnya lebih jelas, lebih terlihat, dan lebih hemat ruang sehingga Anda memahami apa yang terjadi.

Ini tidak main-main dengan angka juga - seperti kasus yang tidak sama misalnya

1..toString(); // works returning '1'
var x = {};
x.1 = {y: 'test' }; //fails currently
x[1] = {y: 'test' }; //works currently 
var current = x[1].y; //works
var missing= x[2].y; //throws exception
var assume= x && x[2] && x[2].y; // works but very messy

Tentang nomor dua opsi: Panggilan Anda mana yang bisa diadopsi, tetapi saya sarankan yang pertama untuk kompatibilitas dengan aturan yang ada!

  1. Harus gagal seperti sekarang ( x.1.y == runtime error )
var err = x..1..y; // should fail as well, since 1 is not a good property name, nor a number to call a method, since it's after x object.
  1. Seharusnya berfungsi karena ia mengerti bahwa itu bukan nomor yang memanggil properti dari Number.prototype
var err = x..1..y; // should work as well, resulting 'test' in this case
var err = x..2..y; // should work as well, resulting undefined in this case

Dengan nama dinamis:

var correct1 = x..[1]..y; //would work returning 'test'
var correct2 = x..[2]..y; //would work returning undefined;

Bagaimana menurut kalian?

Sintaks PS foo?.bar dan foo?['bar'] akan berfungsi juga.

Namun penggunaan operator ? : saat ini dan ?. mungkin sangat membingungkan pada baris yang sama.

misalnya menggunakan ?. dan ?['prop']

var a = { x: { y: 1 } };
var b = condition ? a?.x.?y : a?.y?.z;
var c = condition ? a?['x']?['y'] : a?['y']?['z'];

sebagai lawan dari titik ganda .. dan ..['prop']

var a = { x: { y: 1 } };
var b = condition ? a..x..y : a..y..z;
var c = condition ? a..['x']..['y'] : a..['y']..['z'];
Mana yang terlihat lebih jelas bagi Anda?

Sangat menarik. :+1:

IMHO, dua titik akan lebih membingungkan. Ada bahasa di mana dua titik mewakili rentang (misalnya 1..4 ) dan TypeScript dapat menambahkan fitur ini di masa mendatang.

Tanda tanya juga memiliki arti semantik ketidakpastian atau kondisional dan dua titik tidak menyampaikan arti yang sama.

@schungx Cukup adil, tetapi itu akan membantu untuk kemungkinan aneh seperti ini : a?['b'] atau ini a?() .

+1 ?

a?['b'] dan a?() berperilaku baik dalam skrip kopi, dan mereka terlihat bagus bagi saya.

Tapi sekali lagi, saya mungkin hanya buta-kopi.

+1 Ruby baru saja mengimplementasikan operator eksistensial https://twitter.com/mikepack_/status/657229703443451904. TypeScript membutuhkan ini juga, terlepas dari sintaks tertentu.

Ini akan membuat kode lebih bersih 👍

+1 Butuh ini!

Tolong, implent?. operator, seperti yang dilakukan C#

+1 Saya sudah lama merindukan ini

+1
sangat jelek untuk ditulis: someVariable && someVariable.someMember
ketika Anda bisa menulis: someVariable?.someMember

+1, ini akan sangat bagus.... (fitur paling dicari untuk saya)

+1, itu ide yang bagus!
Hanya saja, jika objeknya rumit, ekspresinya akan penuh dengan ?. setelah setiap properti (var result=myValue?.a?.b?.c?.d?.e;) ketika saya perlu menerima nilai yang terakhir (var result=?myValue.abcde;).

+1 - Ini bisa dibilang salah satu fitur terbesar dari CoffeeScript dan sejauh ini merupakan fitur TypeScript yang paling diinginkan tim saya setelah mengubah banyak kode kami dari CS ke TS.

+1 namun, ini terlalu rumit:

var x = { y: { z: null, q: undefined } };
var z: x|y|z = x?.y?.z;

Saya suka ini:

var x = { y: { z: null, q: undefined } };
var z: z|void = x?.y?.z;

Jenis x?.y?.z selalu merupakan jenis bidang z . Tentu saja tipenya harus nullable dan nilai sebenarnya mungkin null. Jika bukan nol, maka itu harus dari jenis bidang z .

+1 Ini akan berjalan dengan baik dengan visi TypeScript untuk memudahkan pengembangan Proyek JS kompleks skala besar.

Ada pembaruan tentang ini? Apakah ini kasus komunitas yang memilih fitur ini untuk dipertimbangkan? Atau sudah dipertimbangkan tetapi ada beberapa tantangan rekayasa?

Tidak ada pembaruan sejauh ini karena memperkenalkan sintaks tingkat ekspresi baru berbahaya tanpa semacam proposal dari komite ECMAScript.

Lihat https://github.com/Microsoft/TypeScript/issues/16#issuecomment -57645069.

Berikut ini adalah diskusi terkini tentang operator eksistensial (banyak pemikiran, tetapi tidak terlihat seperti banyak tindakan):

di mana saya harus menulis "+1" untuk membantu membawanya ke ES?

@msklvsk ESDiscuss

Menutup ini untuk saat ini. Karena sebenarnya tidak ada sesuatu yang spesifik untuk TypeScript yang memerlukan ini pada level ekspresi, perubahan operator besar semacam ini harus terjadi di komite spesifikasi ES daripada di sini.

Trik umum untuk mengevaluasi ulang ini akan menjadi proposal ES konkret yang mencapai tahap berikutnya, atau konsensus umum dari komite ES bahwa fitur ini tidak akan terjadi untuk waktu yang lama (sehingga kami dapat mendefinisikan semantik kami sendiri dan bersikap wajar yakin bahwa mereka akan "menang").

hidup menyebalkan

Menghapus mandiri :+1:s. Silakan gunakan fitur reaksi GitHub atau kirim bunga dan permen ke perwakilan TC39 terdekat Anda.

Setelah saya terbiasa dengan coffeescript dan Swift, tidak ada jalan untuk kembali. TS sudah mati bagi saya seperti saat ini.

@algesten Saya setuju tentang swift jika kita mempertimbangkan bahasa itu sendiri, tidak yakin tentang dukungan coffescript jangka panjang (saya menggunakan CoffeScript dalam proyek produksi). Kami mungkin setuju untuk memastikan tren analisis bahasa untuk Juni 2016 seperti ini di mana kami dapat dengan jelas melihat apa yang terjadi pada coffescript baru-baru ini, sementara TypeScript telah melihat pertumbuhan tercepat dalam beberapa tahun terakhir:

TypeScript: Di luar Go atau Swift, bahasa dengan pertumbuhan tercepat yang kami amati dalam beberapa tahun terakhir adalah TypeScript. Superset JavaScript yang didukung Microsoft dan yayasan Angular 2 telah membuat keuntungan yang signifikan untuk kuartal kedua berturut-turut, melompat dari #31 ke #26. Itu adalah perubahan tunggal terbesar dalam bahasa 30 Teratas mana pun, dan lompatan terbesar kedua secara keseluruhan (ML Standar, 7 tempat). Di #26, sebenarnya, TypeScript sekarang terikat dengan Erlang, satu tempat di belakang Powershell dan empat di belakang CoffeeScript, yang berada tepat di luar Top 20. Pertanyaan yang dihadapi bahasa bukanlah apakah itu dapat tumbuh, tetapi apakah ia memiliki momentum untuk memecahkan Top 20 dalam dua sampai tiga kuartal berikutnya, melompati orang-orang seperti CoffeeScript dan Lua dalam prosesnya.

Sampai tahun 2014, tren coffescript lebih dari positif seperti yang Anda lihat di sini , saat itulah penurunan dimulai.

Dengan pemeriksaan ketat null (tidak terdefinisi) TypeScript 2.0 yang baru, itu adalah suatu keharusan, karena jika tidak, Anda tidak dapat menggunakan rantai fungsi!

Ini harus dalam versi ECMAScript berikutnya. Mempertimbangkan ini akan lebih berguna dalam JavaScript Vanilla daripada TypeScript dan mengingat implementasinya secara alami akan menjadi pemeriksaan untuk tidak terdefinisi atau nol sebagai lawan dari pemeriksaan yang sebenarnya, seharusnya sepele untuk ditambahkan TC39.

Implementasi sederhana dan yang akan menjadi idiomatis dalam JavaScript, hanya akan menjadi korsleting saat menemukan null atau tidak terdefinisi, dan mengembalikan tidak terdefinisi.

@bterlson apakah ini masuk akal? Apa kemungkinan proposal seperti itu diterima?

Salah satu manfaat besar dari TypeScript adalah "masa depan diberikan kepada Anda hari ini". Ini adalah salah satu fitur yang saya terkejut yang belum ada.

Saya berharap itu akan segera ditambahkan karena rantai fungsi adalah idiom populer dan akankah pemeriksaan nol yang ketat tidak lagi berfungsi kecuali ?. operator ditambahkan.

TS 2 pemeriksaan nol yang luar biasa membuatnya dari yang bagus harus harus dimiliki!

Membaca utas ini, saya agak terkejut bagaimana ini tidak mendapat perhatian lebih dari pengelola.

Di dunia yang ideal TypeScript harus memimpin jalan untuk ES dan bukan sebaliknya. Serius, di mana TypeScript sekarang jika tim TS akan selalu menunggu ESx untuk mengusulkan dan menyelesaikan fitur atau sintaks?

Sintaks ini benar-benar "harus dimiliki", seperti yang ditunjukkan orang lain. Bahkan menerima beberapa proposal bagus di utas ini sejauh ini. Saya pikir implementasinya harus sesuai dengan harapan ini.

  • Secara umum ekspresi a?.b harus valid pada waktu kompilasi jika dan hanya jika a.b valid.
  • Itu harus mengevaluasi setiap ekspresi dalam rantai hanya sekali.
  • Ini harus menjadi arus pendek.
  • Jika eksekusi mencapai ekspresi tengah dengan nilai null atau undefined maka nilai tersebut harus menjadi nilai kembalian.

Menurut Anda, bagian apa saja yang bisa menimbulkan perbedaan pendapat saat ES akan menentukannya?

Untuk a?.b Saya tidak melihat adanya konflik dengan sintaks yang ada (dan yang akan datang?). Jika parser menemukan token ?. ia dapat memperlakukannya sebagai 'operator navigasi yang aman' (dengan harapan seperti yang dijelaskan oleh @cervengoc).

Konflik sintaks hanya muncul ketika mengizinkan a?(b) dan a?[b] , karena ini juga dapat ditafsirkan sebagai awal dari ekspresi operator ternary ?: . Tetapi sebagai permulaan, saya pikir ini dapat dikesampingkan dan hanya mendukung sintaks a?.b sudah akan membuat banyak pengembang senang!

Di dunia yang ideal TypeScript harus memimpin jalan untuk ES dan bukan sebaliknya.

Dalam hal sintaks tingkat ekspresi, kami benar-benar tidak setuju. Ada komite yang mendorong standar karena suatu alasan -- bukan agar tindakan satu kali oleh satu pemain dapat memutuskan masa depan JavaScript secara sepihak.

Sintaks ini benar-benar "harus dimiliki", seperti yang ditunjukkan orang lain.

Jika ini harus dimiliki untuk TypeScript, ini juga harus dimiliki untuk JavaScript! Sekali lagi, sampaikan kekhawatiran Anda ke komite ECMAScript .

Menurut Anda, bagian apa saja yang bisa menimbulkan perbedaan pendapat saat ES akan menentukannya?

Setidaknya, saya pikir akan ada ketidaksepakatan tentang apakah sintaks hubung singkat ke null atau undefined ketika menemukan nilai-nilai itu, atau selalu hubung singkat ke undefined . Juga akan ada beberapa perdebatan tentang apakah beberapa bentuk sintaks kurung didukung atau tidak. Ada juga pertanyaan tentang apa perilaku a?.b.c itu. Ada juga pertanyaan tentang ?. vs .? vs a.b? . Ada pertanyaan tentang apa efeknya pada operator delete .

Utas ES DISKUSI tentang ini lebih dari 100 komentar. Tidak ada kekurangan ambiguitas! Sangat mudah untuk melihat satu contoh secara terpisah dan berpikir tidak mungkin ada banyak kasus sudut. Ada. Itu mungkin mengapa belum ada yang memperjuangkan ini di TC39 dan _juga_ mengapa kami tidak terburu-buru untuk menambahkan fitur yang memiliki banyak ambiguitas tentang bagaimana seharusnya berperilaku.

Saya minta maaf, saya tidak membaca utas yang disebutkan, saya pasti akan melihatnya untuk melihat lebih banyak.

Kami melihat ini sedikit berbeda. Tentang panitia, menurut saya jujur ​​ini adalah salah satu alasan terbesar mengapa JavaScript tidak akan pernah _baik_. Sebagai contoh, banyak perangkat lunak paling sukses yang pernah saya lihat (seperti Total Commander atau IrfanView) berhasil karena dikelola dan dirancang oleh SATU orang, dan bukan oleh *komite". Tentu saja ini tidak sepenuhnya contoh yang benar Tapi saya hampir yakin, bahwa jika misalnya Anda sendiri yang merancang ES6 lengkap, maka dunia akan menjadi tempat yang lebih baik sekarang.

Juga, ambiguitas yang Anda sebutkan ada di 99% _theoretical_ hal dan agak tidak relevan dari sisi pengembang. Siapa yang peduli dengan apa yang dikembalikannya, null atau undefined ? Pilih saja satu, dan kita akan menggunakannya seperti itu.

Secara keseluruhan, Anda dan komite itu berada di sisi yang berbeda dari kebanyakan dari kita, dan hal-hal dari sisi itu biasanya lebih kompleks daripada yang sebenarnya. Dan ini dapat menyebabkan beberapa kontra-produktivitas untuk sedikitnya. Jangan tersinggung, tetapi menurut pengalaman saya secara umum, beberapa orang akan lebih baik keluar dari ruang konferensi lebih sering dan melihat beberapa kode.

Tentu saja jangan tersinggung, jangan tersinggung, saya sangat menghormati Anda dan semua tim TS, karena Anda telah merevolusi banyak pengembangan sisi klien pengembang termasuk saya sendiri, dan terima kasih atas semua pekerjaan Anda. Kami hanya sedikit kecewa tentang yang satu ini, saya kira.

Satu pemikiran terakhir. Saya telah menelusuri utas ES yang disebutkan, dan satu hal yang benar-benar pasti: mereka terlalu memperumitnya. Mereka ingin merancang sesuatu yang bagus untuk setiap skenario.

Saya pribadi akan benar-benar puas dan senang dengan operator akses anggota bersyarat. Tidak perlu doa bersyarat, tanda tangan indeks bersyarat, tidak perlu mendukung setiap skenario mewah yang merupakan kode JS yang valid. Itu saja. Tetapi sebaliknya, mereka kemungkinan akan terus duduk di sana dan mendiskusikan bagaimana melakukan semuanya sekaligus, yang merupakan rencana yang bagus, tetapi kita tidak akan memiliki apa-apa di penghujung hari.

Secara keseluruhan, Anda dan komite itu berada di sisi yang berbeda dari kebanyakan dari kita, dan hal-hal dari sisi itu biasanya lebih kompleks daripada yang sebenarnya.

Saya tidak berpikir Anda mencerminkan status sebenarnya dari Ryan atau TC39 secara akurat. Ryan, dan tim TypeScript, telah menetapkan tujuan desain yang sangat jelas untuk TypeScript. Salah satu tujuan asli dan masih sangat baru adalah TypeScript adalah superset dari JavaScript. Bukan bahasa yang diinginkan orang (misalnya Dart, Haxe). Ketika datang ke sintaks, tim TypeScript telah belajar dengan susah payah tentang biaya pra-penemuannya (misalnya modul). Kami juga menghadapi tantangan dengan anggota kelas privat, di mana sintaks ES yang diusulkan sama sekali tidak sesuai dengan sintaks yang digunakan TypeScript. Mengapa? Karena apa yang mungkin terlihat tidak rumit di permukaan tidak mungkin dicapai mengingat tantangan run-time suatu bahasa.

TC39 telah "menyimpan" JavaScript menurut saya. ES4 ditinggalkan, bukan karena tidak memiliki ide yang bagus dan inovatif, tetapi karena akan merusak internet. TC39 membentuk diri mereka sendiri, mereka telah berbagi dan benar-benar terbuka dalam diskusi mereka dan bagaimana mereka membuat keputusan dan memberikan kami ES2015, yang sangat mirip dengan ES4, tetapi tidak merusak internet. Sungguh menakjubkan bahwa kami pada dasarnya memiliki run-time JavaScript yang menjalankan kode dari 10 tahun yang lalu dengan baik, tetapi mendukung banyak peningkatan signifikan pada bahasa tersebut. ES2016 adalah jeda sebelum badai. ES2017 memiliki jumlah fungsionalitas dan perubahan yang "wajar" serta proses pengaturan yang jelas yang mengarah ke arah yang benar.

Jadi berada di "sisi yang berbeda" jelas telah berhasil, menurut saya. Yang mengalahkan kemanfaatan fitur "harus memiliki".

@kitsonk Saya tidak bermaksud negatif "sisi yang berbeda", dan terutama saya tidak bermaksud untuk menurunkan pekerjaan apa yang dimasukkan ke dalam TypeScript atau ES6. Terlebih lagi, hal terbaik di TypeScript IMO adalah ia benar-benar memiliki dan memiliki tujuan desain yang jelas, dan terlindungi dengan baik agar tidak menjadi malapetaka seperti banyak hal opensource lainnya.

Saya hanya ingin memberi tahu bahwa fitur ini adalah contoh yang jelas di mana sekelompok orang jenius akan berakhir dengan terlalu banyak berpikir dan memperumit hal-hal, alih-alih hanya melakukan cara sederhana yang mudah, dan menerima beberapa batasan seperti tidak mendukung doa atau tanda tangan indeks, dll. Seseorang di forum itu bahkan menyarankan menggunakan sintaks ini dalam tugas, yang agak gila. Saya masih berpikir bahwa fenomena ini kontra-produktif dalam pengertian ini.

Saya mengerti bahwa di pihak Anda itu menyakitkan bahwa misalnya anggota pribadi menjadi tidak sesuai dengan konsep ES6 akhir. Tapi di sisi lain, kami MEMILIKInya. Jauh sebelum ES6. Dan itulah poin utama dari pihak kami. Secara kasar, kami tidak peduli tentang bagaimana Anda mengelola untuk memancarkan kode yang sesuai untuk itu, kami hanya dengan senang hati menggunakannya. Sama dengan modul, dan semuanya. Kami (atau setidaknya saya) tidak mengerti apa yang Anda bicarakan, kami selalu senang dengan anggota atau modul pribadi.

Fitur khusus ini ada di CoffeScript saat saya membacanya. Mengapa kita, pengembang sederhana selalu harus berkompromi saat memilih platform/library/plugin, dll? Maksudku selalu . Ini agak mengganggu. Di sini kami memiliki bahasa yang hebat, yang memiliki potensi besar, yang benar-benar meninggalkan setiap peserta lainnya (termasuk ES!), dan yang telah berhasil merevolusi sebagian besar pengembangan sisi klien, dan ketika datang ke fitur "sederhana" ini ( Maksud saya bagian akses anggota setidaknya), kami mendengar bahwa itu tidak akan diterapkan sampai ES berkomitmen untuk ini.

Saya ingin memberi tahu orang-orang bahwa fitur ini dipindahkan dari tahap 0 ke tahap 1 pada rapat TC39 hari ini.

Komit yang relevan: https://github.com/tc39/proposals/commit/cb447642290a55398d483f5b55fb7f973273c75d
Agenda rapat: https://github.com/tc39/agenda/blob/master/2017/01.md

Wow! itu sangat besar!

Beberapa "kejutan" yang saya lihat di sini (bukan berarti saya tidak setuju, hanya hal-hal yang mungkin akan kita lakukan secara berbeda jika kita melakukannya lebih awal):

  • null tidak dihasilkan dari ekspresi a?.b : ketika a adalah null ini menghasilkan undefined sebagai gantinya
  • ~Propagasi dalam titik-titik berantai: a?.b.c.d tidak akan muncul jika properti b dan c adalah undefined ~ Ryan tidak dapat membaca
  • ~Propagasi di hadapan parens : bahkan (a?.b).c tidak akan dilempar jika b tidak terdefinisi~ Ryan tidak bisa membaca
  • ~Propagasi bahkan terjadi pada pemanggilan metode: a?.b.c().d akan mengembalikan undefined jika permintaan c mengembalikan null ~ Ryan tidak dapat membaca
  • delete operator didukung
  • Sintaks tanda kurung a?.[x] didukung
  • Sintaks panggilan fungsi func?.(...args) didukung, bahkan untuk panggilan non-metode (!)

Saya berharap melihat perubahan di area tersebut antara sekarang dan tahap 2.

Saya pikir coffeescript sudah benar.

a?.bc melempar jika b tidak terdefinisi.

a?() dan a?[0] keduanya bagus.

  • Propagasi dalam titik-titik berantai: a?.bcd tidak akan muncul jika properti b dan c tidak ditentukan
  • Propagasi di hadapan parens: genap (a?.b).c tidak akan muncul jika b tidak terdefinisi
  • Propagasi bahkan terjadi pada pemanggilan metode: a?.bc().d akan mengembalikan undefined jika pemanggilan c mengembalikan null

Poin-poin itu tampaknya tidak akurat bagi saya. Dari usulan:

a?.b.c().d      // undefined if a is null/undefined, a.b.c().d otherwise.
                // NB: If a is not null/undefined, and a.b is nevertheless undefined,
                //     short-circuiting does *not* apply

Wow, saya benar-benar salah membaca itu. Kamu benar. Memperbarui

@algesten dari proposal asli:

a?.()

b?.[0]

manis. operator dapat diurutkan sebagai ?. lalu.

Ada beberapa percakapan tambahan yang terjadi di sini: https://github.com/estree/estree/issues/146

Sebuah kutipan yang dapat diterapkan dengan baik: «Jadikan hal-hal sederhana menjadi mudah , dan hal-hal sulit menjadi mungkin ». Jadi mungkin, dukung kasus yang paling umum dengan baik, sementara lewati (setidaknya pada awalnya) kasus yang rumit/langka, sementara mereka masih diizinkan untuk "dilakukan secara manual" dengan sintaks yang lebih lama (yang ada).

Hanya dua sen saya

let a = b?.c?.d?.e;

ke:

let a;
try{
   a = b.c.d.e;
}catch(e){
   a = undefined;
}

@cedvdb semantik yang sama sekali berbeda -- pengecualian yang dilemparkan ke getter seharusnya tidak menyebabkan penggabungan

@RyanCavanaugh ya.. Saya tidak memikirkan ini.

Apakah ini dalam radar untuk implementasi sekarang, atau akankah tim TS menunggu proposal ES untuk melangkah lebih jauh?

Itu ada dalam daftar pendek kami; kami masih memiliki beberapa pertanyaan/kekhawatiran tetapi Anda akan melihat pergerakan ini di bulan mendatang.

Tidak yakin dari mana komentar @mhegazy berasal - jumlah pertanyaan terbuka pada proposal TC39 terlalu besar bagi kami untuk melakukan pekerjaan yang berarti di sini. Secara khusus pertanyaan seputar bagaimana null dan undefined berinteraksi dan sintaks mana yang benar-benar didukung perlu ditangani terlebih dahulu. Tahap 2 adalah minimum mutlak dan kami lebih suka tahap 3 mengingat dampak pada perilaku runtime.

apakah ini hanya kode yang berfungsi?

a == undefined ? expression : undefined

expression berarti kapak, a[x], a(x), delete juga dapat dihasilkan di sini

maka a?.b?.[c]?.(d) akan menghasilkan

a == undefined ? (a.b == undefined ? (a.b[c] == undefined ? a.b[c](d) : undefined) : undefined) : undefined

tampaknya akan melewati semua aturan RyanCavanaugh


jika membenci operator == , bisa juga a === undefined || a === null

@zh99998 kamu _harus_ membenci == karena '' dan 0 juga disamakan. Hampir dikatakan bahwa perilaku runtime harus menjadi semacam pemeriksaan pada (typeof value === 'object' || typeof value === 'function' || typeof value === 'symbol') && value !== null , yang sekarang menjadi agak rumit.

Seperti yang dikatakan @RyanCavanaugh , itu tidak mungkin berkembang sampai Proposal TC39 untuk itu berkembang setidaknya ke tahap 2 atau 3.

Saya melihat == hanya sama dengan null dan undefined sebagai
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness

dan tes lulus di konsol chrome:

'' == undefined
false
0 == undefined
false

@kitsonk undefined hanya memaksa ke nol dan sebaliknya. Tidak ada nilai lain yang memaksa undefined atau null.

Anda tampaknya bingung dengan nilai-nilai palsu. 0 dan "" memang salah, tetapi tidak akan pernah memaksa ke nol atau tidak terdefinisi.

== menyiratkan paksaan. null == 0 salah karena tidak ada apa pun kecuali undefined yang dapat memaksa ke nol. Hal yang sama berlaku untuk undefined == 0 .

Contoh lain bisa jadi

    if(!NaN) console.log("NaN is falsy") // NaN is falsy
    if(false == NaN) console.log("NaN coerces to false")
   else console.log("NaN doesn't coerce to false");// NaN doesn't coerce

Anda mendapatkan gambarnya.

Saya melihat banyak upaya menggunakan operator ternary, tetapi implementasi apa pun yang merujuk ke properti yang sama beberapa kali dapat mengakibatkan efek samping yang tidak terduga.

Untungnya, JavaScript memiliki IIFE, sehingga Anda dapat menyimpan hasil pengakses dalam parameter fungsi, merujuknya sebanyak yang Anda inginkan dan tidak pernah mengevaluasinya lebih dari sekali. Dalam contoh saya di bawah ini, saya membuat lambda coalesce yang dapat dipanggil beberapa kali sebagai pengganti ekspresi yang berisi operator ?. .

Satu hal yang perlu diperhatikan oleh para pelaksana bahasa adalah pemanggilan array dan fungsi di tengah ekspresi. Saya pikir kompiler dapat menangani pendeteksian situasi itu dan cukup menambahkan ekspresi itu ke akhir panggilan gabungan.

const coalesce = (x: any, y: string) => x == null ? null : x[y];

const x = {
    y: {
        z: "Hello, World!!!"
    },
    f: () => "Foo!",
    a: ["Array!"]
};

// x?.y?.z
const value1 = coalesce(coalesce(x, 'y'), 'z');

// x?.f()
const value2 = coalesce(x, 'f')()

// x?.a[0]
const value3 = coalesce(x, 'a')[0]

Perhatikan bahwa tidak perlu untuk global yang sebenarnya bernama "menyatu". Kode ini dapat langsung dimasukkan ke dalam ekspresi apa pun. Itu mungkin mengurangi mengasapi memberinya nama.

Saya tidak terlalu mempermasalahkan sintaks yang digunakan untuk operator atau jika para pelaksana bahasa ingin menunggu standar. Hanya berpikir saya akan memamerkan pendekatan lain.

Ini juga memunculkan kebutuhan akan operator ?? . Di C#, ini menggantikan ekspresi null dengan apa pun yang ada di sebelah kanan.

string x = null ?? "Hello";
````

In JavaScript, it is more idiomatic to use `||` to replace "falsey" values with the value on the right. 

```javascript
var x = null || "Hello";

Sayangnya, kebenaran menangkap terlalu banyak kasus tepi ( 0 , false , dll.). Bekerja dengan null coalesce ( ?. ), operator, Anda ingin sesuatu yang spesifik untuk null -ness.

const x = { y: "" };
const result1 = x?.y || "default";  // I'd expect "default"
const result2 = x?.y ?? "default";  // I'd expect "" 

@jehugaleahsa , dalam contoh Anda dengan penggabungan harus ada cara untuk mencegah panggilan fungsi dan akses anggota terjadi jika pemeriksaan sebelum mengembalikan nol. Dalam contoh x?.f(), f tidak boleh dipanggil jika x adalah nol.

@bschlenk Saya rasa saya tidak setuju. Saya pikir itu harus gagal dengan pesan seperti null is not a function , tapi itu bukan terserah saya, saya kira.

Lonjakan komentar baru-baru ini yang merinci kemungkinan cara untuk mengimplementasikan operator agak aneh.
Implementasinya mungkin merupakan masalah yang terpecahkan.

Jika Anda tertarik, ada idx library , yang sangat mirip dengan perilaku operator ?. , meskipun juga mengabaikan banyak detail dari operator yang direncanakan. Bagaimanapun, spesifikasi mereka untuk hasil kompilasi mungkin menarik bagi siapa pun yang bertanya-tanya tentang cara hal ini dapat diimplementasikan.

TS bisa menghasilkan sesuatu seperti itu atau bisa menghasilkan sesuatu yang sama sekali berbeda, tapi saya rasa bukan itu yang kita tunggu di sini. Sudah berkali-kali dikatakan di sini bahwa TS tidak akan mendapatkan operator sampai proposal ES bergerak ke satu arah atau ke yang lain.

Ini adalah semantik yang masih memiliki beberapa hal yang tidak diketahui, tercantum di sini dan di sini .

Yakinlah bahwa kami akan menerapkan ini dengan benar dan tidak perlu 100 komentar lagi di sini untuk mengetahui apa yang dilakukan || dan ? ... : ... . Seperti yang dicatat @noppa , kami hanya menunggu spesifikasi ES untuk diselesaikan.

https://github.com/babel/babel/pull/5813 (mendampingi babylon PR ) baru saja digabungkan ke preset-stage-1 Babel. Spesifikasinya masih pada tahap 1, tentu saja, tetapi ini akan membantu memajukannya.

Mungkin saya salah, tetapi saya tidak melihat tautan yang jelas ke proposal tc39 di utas ini, jadi ini untuk pembaca masa depan: https://github.com/tc39/proposal-optional-chaining

FYI opsional chaining akan berada di TC39 minggu depan https://github.com/tc39/agendas/blob/master/2017/07.md

@jehugaleahsa Saya rasa Anda benar dan saya akan mempersembahkan ?? di TC39 minggu depan. Anda dapat mengikuti proposal di sini: https://github.com/gisenberg/proposal-nullary-coalescing

Saya melihat bahwa rantai opsional tercakup di TC39... Apa keputusannya?
Semoga cukup untuk memajukan ini di TypeScript

@markwhitfeld Dari ringkasan catatan :
Operator Rantai Opsional: tetap di Tahap 1, akan kembali lagi nanti dengan definisi yang lebih jelas untuk berbagai opsi dan jawaban atas umpan balik

Catatan lengkap di sini: https://github.com/rwaldron/tc39-notes/blob/master/es8/2017-07/jul-27.md#13iia -opsional-chaining-operator

Masih ada pertanyaan terbuka seputar bagaimana operator harus berperilaku, jadi sepertinya itu belum dalam keadaan di mana ia dapat ditambahkan ke TypeScript.

Dari catatan itu, sepertinya panitia tidak tahu bagaimana opsi yang disajikan bekerja, saya pikir mereka akan mempelajari proposal yang akan mereka diskusikan, sebelum mendiskusikannya. Saya kira ini akan memakan waktu lebih lama sampai saya dapat mengaktifkan pemeriksaan nol yang ketat.

Saya sangat berharap mereka memilih opsi 2/4 (yang merupakan status proposal saat ini).

15 Jul 2014 - 4 Sep 2017, belum ada

@frankfvb Anda jelas belum membaca masalahnya.

Ada banyak diskusi yang membuat tim inti percaya bahwa tidak bijaksana untuk menerapkan pada saat ini sampai ada kemajuan lebih lanjut pada proposal ECMAScript yang akan berdampak langsung pada fungsionalitas fitur ini di TypeScript.

Pada pertemuan terakhir komite standar ECMAScript, proposal tersebut tetap berada di Tahap 1 karena memiliki beberapa pertanyaan mendasar tentang bagaimana hal itu akan diterapkan. Meskipun bukan aturan yang keras dan cepat, TypeScript hanya akan mengimplementasikan proposal Tahap 3. Kadang-kadang mengimplementasikan proposal Tahap 2 jika mereka yakin itu sangat penting dan berpotensi digunakan dalam TypeScript mendorong evolusi standar.

Saya tidak yakin bagaimana orang bisa lebih jelas tentang itu.

Seperti yang saya katakan sebelumnya , ini adalah daftar pendek kami. kami menunggu TC39 untuk mencapai semacam konsensus tentang semantik operator. kami akan benci untuk memadamkannya dan kemudian menghancurkan pengguna.

Ini bukan utas untuk mengulangi diskusi TC39

Jika Anda ingin mempertimbangkan proposal, beri komentar di tempat yang sesuai . Saya juga punya pendapat, tetapi memasukkannya ke utas ini tidak akan menghasilkan apa-apa.

Saya membuat sesuatu yang sederhana yang memenuhi kebutuhan saya saat ini. Ini hanya akan bekerja pada rantai di mana setiap tautan adalah nama properti, jadi mengakses elemen dalam array (misalnya) tidak didukung.

Menerapkan Operator Elvis yang sangat sederhana di TypeScript

Juga jika Anda memiliki lodash/garis bawah, Anda sudah dapat menggunakan _.get(Book, 'author.name.firstName') yang akan melakukan apa yang diinginkannya

Sunting: Tampaknya ini adalah saran yang buruk karena masalah tipe dengan metode _.get() . Lihat komentar di bawah

@tolgaek , _.get memiliki pengetikan yang buruk, bahkan dengan pengetikan yang lebih baik ini ( belum digabungkan , karena penulis) TypeScript pasti dapat menyimpulkan jenis hasil hanya jika kedalaman objek adalah 1, dalam semua kasus lain any dan harus diperiksa saat runtime

Di sisi lain dengan operator elvis TypeScript mungkin dapat menyimpulkan jenis hasil pada objek dengan kedalaman apa pun, inilah sebabnya saya menantikan operator elvis

oh begitu, saya tidak tahu ada masalah pengetikan. Terima kasih @BjornMelgaard

@mhegazy tidak bisakah fitur ini diimplementasikan terlebih dahulu dan ditandai sebagai fitur eksperimental? Saya pikir orang seharusnya tidak memiliki masalah jika ada perubahan spesifikasi dalam fitur eksperimental.

Elvis tidak senang menunggu selama ini.

Itu telah mendarat di Babel7. TypeScript, kami berjalan lambat.. Seseorang tolong buat ini terjadi.
:)

@gs-akhan plugin Babel mengimplementasikan versi lama dari proposal dari beberapa bulan yang lalu. Ada perubahan pada proposal sejak saat itu (termasuk perubahan signifikan pada cara operator diurai), dan kemungkinan akan ada lebih banyak perubahan sebelum fitur mencapai tahap 2 (apalagi tahap 3), jadi kode apa pun yang ditulis dengan babel saat ini plugin bisa rusak ketika fitur sebenarnya dirilis. Babel dengan sengaja mengimplementasikan fitur yang diusulkan sebelum stabil sehingga pembuat spesifikasi dan pihak berkepentingan lainnya dapat mencoba fitur seperti yang diusulkan. Hanya karena Babel telah mengimplementasikan sebuah fitur, bukan berarti fitur tersebut dapat diimplementasikan dengan cara yang tidak memerlukan perubahan besar di masa mendatang.

@alangpierce Masuk akal. Terima kasih

Saya mengerti bahwa ini adalah operator yang sangat, sangat baik, tetapi menyediakannya sebelum aturannya dihapus adalah langkah mudah dan kami tidak akan melakukan itu. Perilaku runtime operator masih berubah-ubah; jika Anda menulis kode hari ini mungkin berhenti bekerja besok dengan cara yang tidak segera terlihat - mungkin crash yang jarang terjadi, mungkin korupsi data, siapa tahu? Sedikit kesabaran sekarang akan menyelamatkan Anda dari banyak rasa sakit beberapa bulan ke depan.

Mulai berpikir tiket ini harus dikunci (tidak ditutup) sampai spek siap.

speknya kapan ready?

@oliverjanik Spesifikasi draf saat ini dapat ditemukan di sini . Ada agenda untuk memajukan proposal ke tahap 2 pada pertemuan TC39 berikutnya (26-9/28). Saya akan menyajikan slide ini pada saat itu. Untuk orang-orang yang ingin meninjau lebih awal dan memberikan umpan balik, silakan ajukan masalah di repo proposal .

Terima kasih banyak @gisenberg telah memperjuangkan masalah ini untuk kami! Saya sedang berpikir untuk menyusun ringkasan slide dek untuk membantu menjernihkan opsi seputar operator yang dapat digunakan pada rapat TC39 untuk menghindari kebingungan, tetapi Anda sudah melakukannya. Pekerjaan yang luar biasa!
Mungkin hanya satu hal lain yang bisa bermanfaat untuk percakapan TC39 (dan slide deck) adalah melihat semantik dan sintaks operator dalam bahasa lain. Meskipun bahasa lain tidak harus mendikte cara kerjanya di Javascript, akan sangat membantu jika operator tetap serupa dengan bahasa lain untuk menghindari kebingungan.
Sukses buat minggu depan!!!

Maaf untuk sedikit keluar dari topik sekali lagi, tetapi saya pikir beberapa orang di sini dapat menganggapnya menarik bahwa di Flow sekarang mungkin untuk menambahkan definisi tipe yang berfungsi untuk fungsi pengambil aman seperti _.get .

Contoh: flowtype.org/try

Bukan bagian kode tercantik yang pernah ada dan tidak membedakan dengan benar antara nol dan tidak terdefinisi, tetapi selain itu tampaknya berfungsi dengan cukup baik.

AFAIK satu-satunya hal yang hilang dari TS untuk melakukan hal yang sama adalah sesuatu seperti itu $NonMaybeType .
Bukan berarti itu akan menghilangkan kebutuhan akan operator ini, tentu saja, saya hanya berpikir itu keren.

Ini tidak mencapai Tahap 2 pada pertemuan TC39 terbaru karena kekhawatiran tentang konsistensi sintaksis terkait braket vs titik vs akses panggilan dan perilaku semantik (prediktabilitas seputar efek samping ekspresi di sebelah kanan undefined / null -evaluated operand) serta pertanyaan terbuka tentang jenis ekspresi apa yang diperbolehkan untuk tidak di-op' (misalnya x.?b() ketika x.b adalah number )

(vote pada komentar ini untuk membuang buah busuk)

Terima kasih telah memberi tahu kami. Apa yang mengecewakan. Mungkin cakupannya perlu dipersempit agar lebih simpel tapi tetap bermanfaat?

Mungkin cakupannya perlu dipersempit agar lebih simpel tapi tetap bermanfaat?

Ini adalah tantangan yang dihadapi TC39, yang meskipun payah, harus saya akui bahwa saya senang orang-orang melalui ini. Sangat sulit bagi mereka untuk memperkenalkan sintaks tingkat yang cukup kompleks dan pada kenyataannya, dalam hal ini pengetikan bahasa yang lemah sebenarnya menyebabkan sejumlah besar kasus tepi yang harus ditangani, atau Anda mendapatkan kode yang berbunyi yang tidak 'tidak baik untuk siapa pun. Saya tidak berpikir jika Anda memperkenalkan operator seperti ini, Anda sebenarnya dapat mempersempit cakupannya. Akan lebih mudah bagi para pelaksana untuk mencakup 90% kasus, tetapi menurut saya ¯\_(ツ)_/¯ bukan kode yang valid untuk 10% sisanya.

Kawan, 3+ tahun kemudian, saya akan mengatakan inilah saatnya untuk mengatakan "bercinta Anda" kepada komite dan melakukannya dengan cara kami sendiri, apa pun yang idiomatis untuk TypeScript. Fitur ini tidak dapat bekerja dengan baik tanpa pengetikan statis.

Buat implementasi TypeScript dengan sintaks yang secara eksplisit tidak sesuai dengan proposisi TC39. Setelah ES mendapatkan operator safe-nav, TypeScript akan memiliki dua opsi: satu dengan semantik menyebalkan yang kompatibel dengan ES, dan satu lagi yang terkait dengan sistem tipe. Ini berarti Anda tidak dapat menggunakan operator TS safe-nav dengan "tipe" apa pun , dan itu tidak masalah.

@notsnotso TypeScript tidak seharusnya merusak JS, itulah gunanya Coffeescript.

Mungkin solusi yang baik adalah:

  • menerapkan sangat sederhana? operator untuk pengembang yang tidak sabar, sebagai fitur eksperimental (seperti dekorator), dengan peringatan - ini AKAN merusak kode Anda di masa mendatang
  • tunggu 3 tahun lagi ketika standar akan ditulis, implementasikan sebagai fitur non-eksperimental. Menulis tutorial, apa yang bisa rusak. Bahkan, dengan pengetikan statis, dimungkinkan untuk menulis peringatan ketika orang akan mengkompilasi kode dengan implementasi operator baru.
    "lakukan dengan cara kami sendiri, apa pun yang idiomatis untuk TypeScript" tidak menjadi masalah, karena dalam 3 tahun orang akan menghadapi masalah, bahwa ts elvis tidak bekerja dengan cara yang sama seperti di js.

Saya tidak terkejut ini tidak berjalan, jujur. Dalam asli saya
posting, saya menunjukkan ambiguitas mengenai pengindeksan, panggilan fungsi, dll.
Sejujurnya, semakin saya memikirkan ?. , semakin terasa tidak
termasuk dalam JavaScript, karena memiliki undefined .

Saya lebih suka utilitas tujuan umum yang memecahkan masalah ini
dan banyak lagi. Satu pemikiran yang saya miliki adalah sesuatu seperti try/catch sebaris
ekspresi ( let x = try a.b.c else 0 ) bersama dengan operator yang
diperiksa untuk "nully" (misalnya, x ?? 1) daripada "falsey" (misalnya, x || 1).
Jadi, Anda akan menggabungkannya seperti ini: try a.b.c ?? 0 else 0 . Ini bertele-tele, ya,
tetapi pada dasarnya mengatakan: Cobalah untuk mengevaluasi abc dan jika hasilnya adalah null atau
undefined , kembalikan 0. Jika a atau b adalah undefined dan pengecualian dilemparkan,
tangkap dan kembalikan 0.

Alternatifnya adalah membuat klausa else opsional, default ke
undefined . Kemudian Anda dapat menulis ekspresi sebagai: let x= (try a.b.c) ?? 0 . Itu sangat kompak, menghindari ambiguitas dan memberikan lebih banyak
solusi tujuan umum yang dapat memecahkan masalah lain.

Saya tidak mengatakan bahwa kita harus mendorong hal ini; semua yang saya katakan ada di sana
adalah alternatif dari ?. dan kita harus benar-benar mengeksplorasi pilihan kita sampai kita
temukan yang cocok dengan bahasa JavaScript.

Pada Kam, 5 Okt 2017 jam 07:51, Dmitry Radkovskiy [email protected]
menulis:

@notsnotso TypeScript tidak seharusnya merusak JS, itulah yang
Coffeescript adalah untuk.


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/Microsoft/TypeScript/issues/16#issuecomment-334441781 ,
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/ABTgPilbZfuKc2egdBrYfdTHHeDl3F6Sks5spMLLgaJpZM4CNapf
.

@zlumer lelucon yang bagus. Yang mengatakan, fitur khusus TS tidak akan merusak Javascript.

@jehugaleahsa Saya suka proposal Anda, dan itu ditemukan dalam bahasa lain. Saya pikir itu akan bekerja dengan baik untuk TS.

Saya akan mengatakan saya tidak begitu mengerti kebutuhan yang kuat untuk menunggu sampai ECMAScript menerima operator. TypeScript menambahkan kelas, modul, lambda, jauh sebelum mereka menemukan jalannya ke ECMAScript. Sebenarnya salah satu tujuan TypeScript yang dinyatakan adalah / sedang menguji coba fitur JS eksperimental. TypeScript yang menyediakan implementasinya sendiri tidak diragukan lagi akan membantu menginformasikan diskusi ini di komite.

Kalian telah bersedia untuk mengambil perubahan sebelumnya ketika komite akhirnya pergi ke arah yang berbeda, saya tidak begitu mengerti mengapa fitur ini sangat berbeda.

async/await juga diperkenalkan ke TypeScript pada tahap awal.

Yang mengatakan, fitur khusus TS tidak akan merusak Javascript.

Tidak akan ada sesuatu seperti "fitur khusus TS", silakan periksa Tujuan Desain TypeScript untuk informasi lebih lanjut.

TypeScript tiba sebelum ES pergi ke jalur yang cerah, mungkin ada beberapa yang sudah ada,mereka hanya disimpan untuk kompatibilitas.

TypeScript menambahkan kelas, modul, lambda, jauh sebelum mereka menemukan jalannya ke ECMAScript.

Dan modul khususnya adalah bencana besar yang masih menyebabkan kebingungan tanpa akhir. Itu adalah contoh yang telah digunakan tim TypeScript berulang kali sebagai contoh _mistake_ dan melompat terlalu dini. Kami juga memiliki ladang pribadi yang menjulang sekarang, yang sekali lagi, saya telah berterima kasih atas private selama 5 tahun terakhir tetapi itu akan menyebabkan kebingungan tanpa akhir.

Sekali lagi, dekorator telah tersedia di bawah bendera, tetapi sekarang dekorator benar-benar mencapai Tahap 3, itu akan memerlukan implementasi ulang dan kerusakan kode untuk TypeScript. Itulah mengapa hal-hal ini _tidak_ dapat dianggap mungkin.

async/await juga diperkenalkan ke TypeScript pada tahap awal.

Setelah proposal ECMAScript mencapai Tahap 3.

Tidak ada yang nakal tetapi jika percakapan ini tidak bisa kemana-mana kecuali berputar-putar (bagaimana jika ada bendera? Ya, kami mengetahui bendera) atau di luar topik (bagaimana jika TS berhenti menjadi JS? Tidak, lima tahun kemudian kami tidak berubah pikiran kita tentang itu), kita tidak perlu memilikinya. Kami telah mengatakan selama sekitar 3 tahun sekarang bahwa kami akan menerapkan ini tepat ketika komite ES mengunci semantiknya.

Sekali lagi, repo proposal adalah https://github.com/tc39/proposal-optional-chaining dan Anda dapat mengikuti perkembangannya di sana. Kami akan bekerja secara offline untuk mencoba meningkatkan peluang proposal pada pertemuan TC39 berikutnya karena kami benar-benar ingin ini berjalan juga.

Pembaruan: Kami mencapai tahap 2 sore ini di TC39!!!

Chaining Opsional adalah Tahap 3

Membuka kunci ini secara singkat hanya untuk tujuan perayaan

Hore!

jangan spam...

Anda dapat mengirim emoji yang mengekspresikan perasaan Anda

jangan spam...

Anda dapat mengirim emoji yang mengekspresikan perasaan Anda

Plus, menyenangkan melihat jumlah emoji naik seperti ini. Saya belum pernah melihat komentar masalah mendapatkan popularitas begitu cepat!

Saya merekam video kecil dari pembaruan waktu nyata https://youtu.be/JLBrgPjeGhc

Dapatkah seseorang berhenti berlangganan saya dari hal ini?

@DanielRosenwasser Jika Anda tidak bercanda, atau siapa pun yang ingin berhenti berlangganan dan tidak tahu caranya, Anda mencari tombol ini di bilah sisi kanan:

image

Belum lagi ada tautan di email:

image

Itu lelucon, saya sedang mengerjakan proposal.

@RyanCavanaugh setelah membuka kunci masalah ini:
martian

Sangat bersemangat untuk melihat ini akhirnya mendarat! 🎈 🎉.

Tidak sabar menunggu perbaikan cepat VSCode yang cocok

image

Saya pergi ke @ @RyanCavanaugh karena dia mungkin berhenti berlangganan utas ini dan saya ingin bersikap kasar! (dan @DanielRosenwasser untuk ukuran yang baik)

@kitsonk Jangan jadi keledai. Orang bebas untuk berhenti berlangganan dan tidak diganggu.

@kitsonk , Mengapa RyanCavanaugh atau DanielRosenwasser berhenti berlangganan utas ini? Ryan membuka kunci masalah ini dan Daniel menanggapi tiga komentar di atas Anda.

Bahkan jika mereka berhenti berlangganan, tidak perlu menyebabkan lebih banyak kelelahan pemberitahuan dengan mengirim spam kepada mereka.

Rupanya GitHub adalah tempat yang mengerikan untuk humor sarkastik, wah...

Terima kasih banyak kepada juara kami di TC39 karena telah menemukan detail buruk dari fitur bahasa baru ini!

thanks

Saya pikir @kitsonk hanya bercanda, seperti yang saya lakukan. Meskipun kami sedikit konyol di sekitar kegembiraan, ini adalah pengingat lembut untuk menjaga hal-hal sipil sesuai CoC.

@DanielRosenwasser
Bisakah saya harus mencoba ini? Atau @rbuckton memiliki cabang lain yang ada untuk itu ️


Oke, saya mengerti https://github.com/microsoft/TypeScript/commits/optionalChainingStage1

Ya, itu cukup ketinggalan zaman, sayangnya.

Saya baru menyadari masalah ini dibuka 5 tahun yang lalu. :heran:

@rbuckton

Ya, itu cukup ketinggalan zaman, sayangnya.

Bisakah saya mencoba ini?

Maaf @jhpratt @MatthiasKunnen Saya lupa kita tidak semua berbagi konteks yang sama di GitHub. Saya telah terpental di sini untuk waktu yang lama dan telah menghabiskan waktu dengan Ryan dan Daniel IRL dan secara singkat berpartisipasi dalam acara baru-baru ini yang memunculkan lelucon orang dalam yang disalahpahami. Permintaan maaf.

Seluruh masalah ini menunjukkan arkeologi yang menarik dari prinsip-prinsip desain TypeScript. Ryan mengangkatnya pada saat TypeScript _might_ benar-benar mempertimbangkan sintaks yang mendahului pertimbangan serius dalam ECMAScript. Sekitar waktu itu meskipun TypeScript secara internal mempelajari beberapa pelajaran memprediksi sintaks ES2015 yang berdampak serius pada bahasa tersebut. Tim memutuskan untuk tidak mempertimbangkan penyertaan sampai ada proposal Tahap 3 TC39.

Sementara @RyanCavanaugh dapat mengatasinya, dan saya tahu dia sudah dekat dengan apa yang telah terjadi dengan proposal tersebut, saya menduga tidak mungkin apa yang akan diterapkan tim pada tahun 2014 akan 100% kompatibel dengan proposal Tahap 3 saat ini. . Jadi, meskipun ini adalah perayaan, juga bersyukur bahwa kami tidak memiliki kode TypeScript selama 5 tahun dengan operator navigasi yang aman yang tidak akan sepenuhnya konsisten dengan perilaku dalam proposal.

🙏

westwing

Apakah ini saatnya untuk menghapus label Waiting for TC39 ? 🤔.

Apakah ini saatnya untuk menghapus label Waiting for TC39 ? 🤔.

Dan tambahkan ship-it

wowowow

Akhirnya. Secara harfiah bertanya-tanya tentang opsional chaining y'day, bertanya-tanya kapan itu akan menjadi tahap 3, dan bam! Terima kasih semua orang yang bekerja untuk mendorongnya!

Bagaimana cara menonaktifkan utas ini? :)

@opnksyn Jika Anda tidak peduli dengan kegembiraan spam, ada fitur untuk mendapatkan pemberitahuan ketika masalah ini ditutup. Ini akan mencegah semua komentar muncul di notifikasi seperti yang baru saja Anda buat

image

image

Adakah solusi emisi yang sudah ditentukan?
Sesuatu seperti ini mungkin menarik:

function __chain<T extends object, U>(value: T|null|undefined, callback: (value: T) => U): U|undefined {
    if (value !== null && value !== undefined) {
        return callback(value);
    }

    return undefined;
}

type Foo = { x?: { y?: { z?: () => number } } }

const foo: Foo|null = { }

// foo?.x?.y?.z?()
const value = __chain(foo, _a => __chain(_a.x, _b => __chain(_b.y, _c => __chain(_c.z, _d => _d()))));

Saya lebih suka apa yang dilakukan Babel karena menghindari pembuatan cakupan fungsi yang tidak perlu:

var _foo, _foo$x, _foo$x$y, _foo$x$y$z;

// foo?.x?.y?.z?.()
(_foo = foo) === null || _foo === void 0 ? void 0
    : (_foo$x = _foo.x) === null || _foo$x === void 0 ? void 0
    : (_foo$x$y = _foo$x.y) === null || _foo$x$y === void 0 ? void 0
    : (_foo$x$y$z = _foo$x$y.z) === null || _foo$x$y$z === void 0 ? void 0
    : _foo$x$y$z.call(_foo$x$y);

Saya lebih suka apa yang dilakukan Babel karena menghindari pembuatan cakupan fungsi yang tidak perlu:

var _foo, _foo$x, _foo$x$y, _foo$x$y$z;

// foo?.x?.y?.z?.()
(_foo = foo) === null || _foo === void 0 ? void 0
  : (_foo$x = _foo.x) === null || _foo$x === void 0 ? void 0
  : (_foo$x$y = _foo$x.y) === null || _foo$x$y === void 0 ? void 0
  : (_foo$x$y$z = _foo$x$y.z) === null || _foo$x$y$z === void 0 ? void 0
  : _foo$x$y$z.call(_foo$x$y);

Saya setuju, @ExE-Boss. Saya merasa bahwa menghindari membuat cakupan fungsi yang tidak perlu sangat ideal (bahkan jika itu membuat kode yang dikompilasi agak jelek)

Performa dan kepatuhan terhadap spesifikasi ES pasti harus menang atas keterbacaan ketika kita berbicara tentang kode yang dikompilasi.

Apakah ada alasan mengapa kode yang dikompilasi oleh Babel dibandingkan dengan null dan void 0 dengan triple equals daripada == null sederhana?

Apakah ada alasan mengapa kode yang dikompilasi oleh Babel dibandingkan dengan null dan void 0 dengan triple equals daripada == null sederhana?

@proteria Saya baru saja melihat sekilas kode rantai opsional untuk __Babel__ ; tampaknya jika Anda memasukkan opsi loose dan menyetelnya ke nilai yang benar, itu tidak menghasilkan pemeriksaan kesetaraan yang ketat

Itu karena document.all (atau lebih tepatnya, slot internal [[IsHTMLDDA]] ), sebuah quirk yang mendapat perlakuan khusus dalam bahasa untuk kompatibilitas mundur.

document.all == null // true
document.all === null || document.all === undefined // false

Dalam proposal rantai opsional

document.all?.foo === document.all.foo

tetapi document.all == null ? void 0 : document.all.foo akan salah mengembalikan void 0 . Dalam mode longgar, detail spesifikasi ini diabaikan karena kesederhanaan/kinerja/ukuran kode yang dihasilkan karena kebanyakan orang tidak harus berurusan dengan document.all .

Tentunya kasing document.all bisa jadi spesial? Seharusnya tidak memerlukan banyak kode tambahan, hanya beberapa baris untuk memeriksa objek dan properti.

Kecuali bahwa document.all dapat ditetapkan ke variabel, dan pelacakan di mana itu digunakan memerlukan sistem tipe, itulah sebabnya Babel menghasilkan secara default:

(_prop = prop) === null || _prop === void 0 ? void 0 : _prop./* do stuff */;

Saya sadar akan hal itu. Babel tidak memiliki sistem tipe, TypeScript memilikinya. Mungkin tidak sesederhana yang saya katakan, tetapi saya membayangkan sudah ada kode untuk situasi tertentu yang mampu melacak penggunaan.

Sebenarnya, Anda tidak memerlukan sistem tipe untuk melacak variabel document.all , karena perilaku khusus sebenarnya ada di HTMLAllCollection , bukan document.all .

Jadi Anda seharusnya bisa melakukan cek instanceof HTMLAllCollection , dan Anda akan menjadi emas.

Ya tapi... kenapa kamu melakukan instanceof padahal kamu bisa melakukan === null || === void 0 ? Tentunya itu lebih sederhana.

Pasti - saya hanya menunjukkan bahwa Anda tidak memerlukan sistem tipe untuk melacak document.all :)

Secara pribadi saya tergoda untuk mengatakan istirahat saja dan lihat siapa yang mengeluh, tapi itu dalam spesifikasi, jadi paling mudah untuk tetap dengan itu.

@noppa Itu dapat dilakukan pada waktu kompilasi. Jika foo instanceof HTMLAllCollection adalah true , emit foo === null || foo === void 0 , jika tidak kita dapat _safely_ emit foo == null .

@G-Rath Suka atau tidak, ditinggalkan bukan berarti tidak berfungsi. TypeScript harus tetap kompatibel dengan JavaScript.

@jhpratt Tapi itu saat ini bertentangan dengan TypeScript Design Non‑Goals .

Juga, Anda masih harus melakukan foo === null || foo === void 0 untuk apa pun yang HTMLAllCollection dapat ditetapkan, mis. any atau object , jadi menurut saya itu tidak sepadan.

Saya kira Anda mengacu pada non-tujuan (5)

Tambahkan atau andalkan informasi tipe run-time dalam program, atau keluarkan kode berbeda berdasarkan hasil sistem tipe. Sebaliknya, dorong pola pemrograman yang tidak memerlukan metadata run-time.

Meskipun saya setuju ini pasti akan memancarkan kode yang berbeda berdasarkan jenisnya, itu hanya untuk mengurangi ukuran kode. Meskipun seperti yang telah Anda tunjukkan, itu tidak sesederhana memeriksa HTMLAllCollection .

Agar adil, TS _has_ menolak minifier potensial yang menggunakan informasi tipe, dan ini (semacam) terkait — alasan utama untuk memancarkan == null adalah untuk mengurangi ukuran kode berdasarkan informasi tipe.

Jika _tidak_ ini diimplementasikan, akan sangat bagus jika tim lang menambahkan opsi ke tsconfig yang mirip dengan opsi "longgar" Babel.

Setelah memeriksa dengan cepat, terser secara otomatis mengonversi foo === null || foo === undefined menjadi foo == null , yang tidak aman karena kasus tepi ini.

Jika ini tidak diterapkan, akan sangat bagus jika tim lang menambahkan opsi ke tsconfig yang mirip dengan opsi "longgar" Babel.

Terkait, banyak dari kita menggunakan TypeScript untuk membangun alat, dan untuk aplikasi seluler, tidak ada yang perlu khawatir tentang kendala browser!

Faktanya, kami menggunakan TS & Babel bersama-sama, jadi mungkin salah satu opsi ini adalah melewati operator ke Babel/runtime yang mendasarinya!

@fbartho

Faktanya, kami menggunakan TS & Babel bersama-sama, jadi mungkin salah satu opsi ini adalah melewati operator ke Babel/runtime yang mendasarinya!

Saya tidak mengerti komentar ini. Anda tidak memerlukan opsi tambahan untuk melewati operator ke Babel; jika Anda telah menyiapkan TypeScript untuk Babel, Anda sudah memiliki noEmit: true yang telah melewati _everything_ ke Babel.

Implementasi TypeScript @Zarel Babel tidak memiliki beberapa fitur yang telah diandalkan oleh basis kode kami, termasuk ruang nama dan const enum. Kami menggunakan TSC dengan emit diaktifkan, dan menerapkan Babel sebagai transformasi kedua. (Kami sedang berupaya menyingkirkan ruang nama, tetapi tidak jelas apakah kami akan dapat menghapus semua fitur yang tidak cocok)

Orang-orang yang datang ke utas ini harus mulai dari pengumuman tahap 3 sebelumnya dan membaca komentar mulai dari sana (salahkan GitHub karena menyembunyikan banyak konten pengguna tanpa cara langsung memuat semuanya)

Fitur hebat - "rantai opsional" / "navigasi aman". Terutama dalam mode ketat TypeScript. Luar biasa mendengar bahwa ini akan segera diterapkan. ❤️

Ini membawa saya ke sini dan saya berharap itu akan didukung. Hanya kasus penggunaan:

Diharapkan dalam TypeScript 3.7.

document.querySelector('html')?.setAttribute('lang', 'en');

VS

Saat ini dalam TypeScript 3.5.

const htmlElement = document.querySelector('html');
if (htmlElement) {
  htmlElement.setAttribute('lang', 'en');
}

Apakah ini akan berfungsi tanpa kesalahan? Atau apakah ini masih TypeError: Cannot read property 'setAttribute' of null. ? Operasi ? harus membatalkan rantai lebih lanjut setelah null / tidak terdefinisi.

class Test {
  it() {
    console.log('One');
    document.querySelector('html')?.setAttribute('lang', 'en');
    console.log('Two');
  }
}
new Test().it();

Saya mengharapkan berikut:
Jika elemen html tidak ada (null). Konsol harus mencatat One dan Two , dan metode setAttribute tidak dicoba untuk dipanggil. (Tidak ada kesalahan).
Apakah saya memahaminya dengan benar?

@domske FYI, ini bukan sepenuhnya fitur TS; itu adalah fitur JS.

Menurut proposal TC39 sintaksnya adalah:

document.querySelector('html')?.setAttribute?.('lang', 'en');

Diskusi sudah mulai berputar-putar lagi jadi kita kembali ke keadaan terkunci.

Saya benar-benar memohon kepada siapa pun yang tergoda untuk meninggalkan komentar di utas GitHub yang panjangnya 100+ komentar untuk benar-benar berkomitmen membaca semua komentar sebelumnya terlebih dahulu. Mungkin pertanyaan Anda, dan jawabannya, akan ditemukan di sana!

Apakah halaman ini membantu?
0 / 5 - 0 peringkat