Typescript: Vorschlag: "safe navigation operator", dh x?.y

Erstellt am 15. Juli 2014  ·  205Kommentare  ·  Quelle: microsoft/TypeScript

Aktueller Status

  • Der TC39-Vorschlag befindet sich jetzt in Phase 3 (🎉🎉🎉🎉🎉)
  • Die Umsetzung ist im Gange
  • Sie können diese Funktion in TypeScript 3.7 erwarten
  • Wir werden hier aktualisieren, wenn es in einem nächtlichen Build verfügbar ist
  • Warten auf Optional Call, bis seine Semantik im Komitee geklärt ist

Offene Fragen

  • Welchen Sonderfall sollte document.all erhalten, wenn überhaupt?

C# und andere Sprachen haben Syntaxzucker für den Zugriff auf Eigenschaftsketten, bei denen null (oder in unserem Fall undefined ) an jedem Punkt in der Objekthierarchie auftreten können.

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'

Benötigen Sie einen Vorschlag, was genau wir kodieren sollten, unter Berücksichtigung der Nebenwirkungen von Zugriffsmitteln.


Bearbeiten von @DanielRosenwasser 27. Februar 2018: Dieser Vorschlag wird auch als "Null-Propagation"-Operator bezeichnet.

Committed ES Next Suggestion Update Docs on Next Release

Hilfreichster Kommentar

Optionale Verkettung ist Stufe 3

Diesen nur zur Feier kurz aufsperren

Alle 205 Kommentare

Im ersten Beispiel könnten wir es also wie folgt ausgeben:

x && xy && xyz && xyzfoo

Aber dann müssten wir irgendwie dafür sorgen, dass x, y, z und foo jeweils höchstens einmal ausgewertet werden.

Sie können in vielen Fällen auch nicht wirklich && machen, weil Wahrhaftigkeit für Primitiven zu einem kleinen Problem wird.

Zum Beispiel:

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

gibt "" .

Sie müssen also einige explizite Vergleiche mit null durchführen, wobei == für den allgemeinen Fall verwendet wird, es sei denn, wir nutzen das Typsystem (was ziemlich cool wäre, wenn wir das tun würden).

Wir könnten möglicherweise eine monadische Bindungsfunktion ausgeben (nicht hübsch für die JS-Ausgabe) oder eine Transformation für ternäre Operatoren verwenden (näher an einem typischen JS-Äquivalent). Ich bin eindeutig etwas voreingenommen gegenüber letzterem.

:+1:

Idealerweise sollte ES7 (oder ES8 oder ES9 oder ...) dies zuerst implementieren, da es wahrscheinlich einige Meinungsverschiedenheiten über die genaue Semantik darüber geben würde, ob 0 / "" tatsächlich verwendet werden soll oder nicht.

:+1: Ich würde gerne sehen, dass TypeScript dies zuerst bekommt, ohne auf ESxx warten zu müssen.

Die Tatsache, dass einfache und wahnsinnig nützliche Nullsicherheitsoperatoren wie "?." und "?:" SIND NICHT in der ES6-Spezifikation bedeutet, dass die Leute, die die ES6-Spezifikation zusammenstellen, ihre Köpfe vor Scham hängen lassen sollten. Dies ist eine so einfache und offensichtliche Sache, dass es ehrlich gesagt verrückt wäre, es nicht zu integrieren. Es gibt einen Grund, warum die meisten modernen Sprachen diese unterstützen: Sie sind unverzichtbar.

Mir ist klar, dass dies eine Abweichung von der aktuellen Spezifikation wäre (da die aktuelle Spezifikation so kurzsichtig ist, dies wegzulassen). Aber es ist so lächerlich nützlich, dass ich denke, dass diese eine Abweichung gerechtfertigt wäre. Die überwiegende (GROSSE) Mehrheit der TS-Entwickler wäre von geringfügigen Änderungen an der Implementierung nicht betroffen, falls oder wenn diese schließlich zu einer ES-Spezifikation hinzugefügt werden. Die enormen Vorteile, die dies bieten würde, sind die potenziellen zukünftigen Auswirkungen für einen winzigen Bruchteil der Entwickler wert. Und angesichts des lächerlich langsamen ES-Spezifikationsprozesses würde dies (mindestens) mehrere Jahre lang überhaupt keine Rolle spielen.

Ich stimme brain428 vollkommen zu

@brian428 Das Problem hier ist, dass dieser Operator möglicherweise in ES7 implementiert ist. Wenn also Typoskript mit einer Spezifikation verwendet wird, die sich von der endgültigen ES7-Spezifikation unterscheidet, wird niemand glücklich sein.

Das Problem dabei ist, dass dieser Operator möglicherweise in ES7 implementiert ist. Wenn also Typoskript mit einer Spezifikation verwendet wird, die sich von der endgültigen ES7-Spezifikation unterscheidet, wird niemand glücklich sein.

Ich denke, es ist ein positiverer Ansatz für TypeScript, Funktionen zu implementieren, die es möglicherweise _ (oder auch nicht) in eine zukünftige ES-Version schaffen, da dies eine nützliche Testumgebung für die Beeinflussung der ES-Richtung sein wird.

Hier ist ein Beispiel für eine ES-Diskussion, die von TypeScript beeinflusst wird :

Die Option TypeScript... zum Deklarieren und Initialisieren über ein privates Präfix für einen der Parameter des Konstruktors wäre für viele Entwickler hilfreich

Darüber hinaus ist es sicherlich möglich, dass ES eine Funktion übernimmt, die bereits in TypeScript vorhanden ist, jedoch mit einer anderen Semantik (z. B. in Bezug auf die Funktionsweise von Modulen).

Es ist sicherlich möglich, dass ES eine Funktion übernimmt, die bereits in TypeScript vorhanden ist, jedoch mit einer anderen Semantik

Ich sollte anmerken, dass wir dies im Großen und Ganzen als ein Worst-Case-Szenario betrachten. Wir wollten wirklich, dass Module in ES6 fertiggestellt werden, bevor wir TypeScript 1.0 deklarieren, aber die Zeitplanverzögerungen des Komitees verhinderten dies. Dies ist etwas zu vermeiden, nicht zu wiederholen. Wir würden wirklich gerne Funktionen treffen, die entweder eine Chance von ~0 % haben, es in ES7+ zu schaffen (z. B. Typanmerkungen), oder eine Chance von ~100 % haben, es in ES7+ zu schaffen (z. B. wo dicker Pfeil zwei war vor Jahren). Neue Betreiber fallen wahrscheinlich in die unangenehme Mitte.

Könnte ein Compiler-Flag im schlimmsten Fall, wenn ES7 sich unterscheidet, die Legacy-TS-Implementierung unterstützen und somit eine Nachfrist bieten? Dies in Verbindung mit einer klaren Migrationsdokumentation sollte Entwicklern einen einfachen Weg zu jedem neuen Standard bieten.

Letztendlich ist die Verwendung einer solchen Funktion – obwohl wahnsinnig nützlich – für Entwickler nicht unbedingt erforderlich. TS sollte potenzielle zukünftige Auswirkungen seiner Nutzung vom ersten Tag an deutlich machen. Mögen Sie die Idee eines potenziell verwalteten Refactoring nicht, verwenden Sie es nicht. Vielleicht ein Opt-in-Compiler-Flag, um diese Nachricht zu erzwingen?

TS sollte nicht wild darauf sein, ES beeinflussen zu wollen, aber in kleinen Einzelfällen wie diesem wäre es schade, wenn TS komplett davor zurückschrecken würde.

Vielleicht könnten wir dafür einen Strohmannvorschlag zusammenstellen und dann eine Referenzimplementierung hinter einem --harmony-Flag (oder so ähnlich) haben. Auf diese Weise können wir die ES7-Entwicklung dieser Funktion vorantreiben.

Um Seiteneffekte durch wiederholtes Nachschlagen zu vermeiden, muss der Compiler entweder temporäre Variablen ausgeben:

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

oder verwenden Sie eine memoisierende Membran, die auf Proxy basiert.

Aus kategorialer Sicht ist dies nur die Vielleicht-Monade, die auf die Eigenschaftssuche angewendet wird, also ist es ein sehr natürliches Merkmal für eine Sprache, in der alle Eigenschaftssuchen undefiniert zurückgeben können. Ich wäre überrascht, wenn ES7 eine andere Semantik als die im obigen Code beschriebene annehmen würde.

Die Codeplex-Ausgabe hatte eine ganze Reihe von Stimmen (61)

Ich brauche das wirklich dringend, um die Schmerzen bei der Verwendung von atom für Atomtyposkript zu lindern.

Es ist im Coffescript-Code sehr idiomatisch (obwohl ich möchte, dass es nicht so beliebt ist, da Determinismus besser ist als ein fummeliges ? ). Öffnen Sie eine beliebige Coffescript-Datei, insbesondere eine, die mit dem DOM direkt wie ein Leerzeichen funktioniert (wobei Funktionen ausgeführt werden können, nachdem die Ansicht zerstört oder bevor die Ansicht angehängt wurde), und Sie werden eine Unmenge ? Verwendungen finden. zB hat diese Datei 16 https://github.com/atom-community/autocomplete-plus/blob/f17659ad4fecbd69855dfaf00c11856572ad26e7/lib/suggestion-list-element.coffee

Auch hier gefällt es mir nicht, dass ich das brauche, aber es ist der Zustand von JavaScript, und ich hätte lieber ? als eine Million if( && fest ) { then }

Aber ich brauche es wirklich, um meinen Code lesbar zu halten. Es ist auch sehr üblich, dies zu _brauchen_, wenn Sie darauf warten, dass ein XHR seine Digest-Schleife abschließt und eckig durchläuft.

Okay, jetzt habe ich den Thread gelesen und sehe, warum wir warten. Ich verstehe _seufz_.

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

coffeescript führt einige Optimierungen durch, z. B. speichert Zwischenzugriffsergebnisse :

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

(Ich bin der festen Überzeugung, dass die undefined -Prüfung für Typoskript unnötig ist: da wir eine var -Init-Typprüfung durch Typoskript haben sollten.)

+1

In den heutigen Nachrichten erhält Dart offizielle Unterstützung dafür: https://github.com/gbracha/nullAwareOperators/blob/master/proposal.md

Sehr wichtige Funktion.

Möglicherweise eine ausgefallene Idee, aber das Codegen für dieses Feature könnte sehr einfach ohne Nebenwirkungen durchgeführt werden, wenn alle entscheiden würden, dass es in Ordnung wäre, das Feature mit verschlüsseltem Eigenschaftszugriff zu handhaben:

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

Könnte kompilieren

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

Eine __chain Funktion müsste ähnlich wie __extends werden. Die Funktion __chain könnte einfach das Array arguments durchlaufen und null zurückgeben, wenn das nächste Mitglied nicht instanceof Object ist oder den Mitgliedsnamen nicht enthält. Funktionsaufrufe könnten behandelt werden, indem ein Array als Parameter übergeben wird (und .apply() unter der Decke verwendet wird), also ...

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

Könnte kompilieren

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

Dies würde auch das generierte JS selbst für lange Ketten einigermaßen idiomatisch halten.

Muss natürlich verfeinert werden ... aber vielleicht ist hier etwas dabei?

Wenn aaa?.bbb?.ccc? den Wert von a.b.c #$ zurückgibt, wenn alle Requisiten existieren und es zufällig eine Funktion ist, dann geht das nicht

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

kompilieren zu

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

?

@metaweta : Ihre Lösung sucht nur nach void 0 ... macht das nicht den Zweck der Funktion zunichte?

Was ist damit:

var result = one?.two?.three;

Erzeugt:

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

Ich bin mir ziemlich sicher, dass dies alle Fälle behandelt. Funktionsaufrufe würden wahrscheinlich einen instanceof Function -Check benötigen.

(Kleiner Nachteil hier, dass unerwartete lokale Variablen ausgegeben werden ... könnte vielleicht in ein IIFE gepackt werden)

@kevinb7 : Was passiert, wenn ccc keine Funktion ist? Mit dem von Ihnen beschriebenen Code müsste __chain immer eine gültige Funktion zurückgeben, oder es würde ein TypeError ausgegeben werden.

@Back-io Wenn eine Eigenschaft fehlt, gibt eine Suche undefiniert === void 0 zurück. Ihre Lösung schlägt fehl, um Eigenschaften von falschen Werten wie leere Zeichenfolge und Null nachzuschlagen.

@metaweta : Nein, tut es nicht: http://jsfiddle.net/25LppbL6/

Außerdem könnte ich mir vorstellen, dass das TS-Team nicht gerade verrückt danach ist, lockere Gleichheit zu verwenden, da die Linters einiger Leute davor warnen.

@Back-io Ja, das tut es: http://jsfiddle.net/25LppbL6/2/

@Back-io In Bezug auf null bin ich mir nicht sicher, was die beabsichtigte Semantik von a?.b ist. Wenn es "Wenn die Eigenschaft b definiert ist, dann verwende sie" lautet, ist mein Code fast korrekt. Die einzige Möglichkeit, null zu erhalten, besteht darin, dass es als null zugewiesen wird, da die Suche nach nicht vorhandenen Eigenschaften undefiniert zurückgibt. Der Fall, in dem die Eigenschaft vorhanden ist, aber auf undefiniert gesetzt ist, wird nicht erfasst. Um ganz korrekt zu sein, würde es mit Object.hasOwnProperty() prüfen, anstatt mit void 0 === undefined zu vergleichen.

Wenn die Semantik lautet: "Wenn die Eigenschaft b wahr ist, dann verwenden Sie sie", ist Ihr Code in Ordnung und entspricht bis zu einem gewissen Grad der JS-Sprache.

Ähm ... es sei denn, ich übersehe etwas ... die Änderungen, die Sie an der Geige vorgenommen haben, geben mir nur noch mehr Recht ... var result ist in allen 3 Fällen immer noch undefined . Und ich bin mir nicht sicher, welchen Fall Sie durch die Erweiterung der primitiven Prototypen voranbringen wollen ...

Ich bin mir ziemlich sicher, dass das Verhalten der Funktion darin bestehen würde, mit void 0 kurzzuschließen, anstatt einen Fehler zu generieren. (Mir gefällt Ihre obige Idee, dass im Falle eines fehlenden Mitglieds immer void 0 zurückgegeben werden sollte).

Was ist die beabsichtigte Ausgabe von ''?.toString ?

@kevinb7 : Was passiert, wenn ccc keine Funktion ist? Mit dem von Ihnen beschriebenen Code müsste __chain immer eine gültige Funktion zurückgeben, oder es würde ein TypeError ausgegeben werden.

Guter Punkt.

@metaweta : Ich würde mir vorstellen, dass die meisten Leute einen Verweis auf die Funktion toString erwarten würden, also sehe ich, wo Ihr Punkt ist. Es bricht etwas zusammen, wenn Sie auf die Prototyp-Mitglieder von 0 zugreifen, falsch, oder ''.

:+1:
Angular 2 hat Elvis Operator zu seiner Template-Syntax hinzugefügt

@Metaweta :

Was ist die beabsichtigte Ausgabe von ''?.toString?

Wenn Sie ''?.toString() meinten, wäre es:

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

Probe

Vielleicht könnten wir dafür einen Strohmann-Vorschlag zusammenstellen

@kevinb7 es existiert bereits: http://wiki.ecmascript.org/doku.php?id=strawman :existential_operator

Ich habe einige schnelle Tests durchgeführt, um dies zusätzlich zu PropertyAccessExpression als Sonderfall zu implementieren, aber es hat nicht gut funktioniert, da wir wirklich ?. brauchen, um rechtsassoziativ zu sein (anstatt linksassoziativ wie . ) sonst wird der Emitter unnötig komplex.

Es gibt hier einen Kommentar von BrendenEich, der dies ebenfalls widerspiegelt.

Ich habe einige schnelle Tests durchgeführt, um dies zusätzlich zu PropertyAccessExpression als Sonderfall zu implementieren, aber es hat nicht so gut funktioniert, wie wir es wirklich brauchen. rechtsassoziativ sein (statt linksassoziativ wie .), sonst wird der Emitter unnötig komplex.

@basarat kannst du das bitte näher erläutern? Ein Beispiel für den Unterschied zwischen rechtsassoziativ und linksassoziativ ?. wäre sehr hilfreich für mich.

@Zlumer

Ein Beispiel für den Unterschied zwischen rechtsassoziativem und linksassoziativem ?. wäre mir sehr hilfreich.

. bleibt assoziativ, sodass der Ausdruck foo?.bar?.baz in AST wird (wenn wir ?. gleich behandeln):

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

Die benötigte JavaScript-Ausgabe ist

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

Es ist nur einfacher, diese Ausgabe (insbesondere _rekursiv_) durchzuführen, wenn wir Folgendes in der AST hätten:

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

Denken Sie nur an _wie würden Sie den ersten AST in JavaScript umwandeln_ und die Komplexität wäre klarer. Hoffe das hilft :rose:

@zlumer , um das zu ergänzen, was @basarat gesagt hat, ich werde nur das Beispiel 1 + 2 + 3 ausgeben.

Beim Parsen müssen wir entscheiden, welche dieser Operationen zuerst ausgeführt wird.

Wenn + ist, wird dies als ((1 + 2) + 3) interpretiert.

Wenn + ist, wird dies als (1 + (2 + 3)) interpretiert.

Man könnte sich fragen, ob das wirklich einen Unterschied machen würde. In JavaScript wäre es! Betrachten Sie das Beispiel "hello" + 2 + 3 .

  • Linksassoziativ: (("hello" + 2) + 3) => ("hello2" + 3) => "hello23"
  • Rechtsassoziativ: ("hello" + (2 + 3)) => ("hello" + 5) => "hello5"

(Für den Datensatz verwenden JavaScript/TypeScript Linksassoziativität für den + -Operator.)

@basarat , mein Verständnis von dem, was @BrendanEich gesagt hat (und er kann mich korrigieren, wenn ich falsch liege - sorry für den Ping!) ist _nicht_, dass ?. rechtsassoziativ ist, sondern dass CoffeeScript auf die Eigenschaft für Sonderfälle zugreift das Recht von ?. , rechtsassoziativ zu sein. Zum Beispiel wird es parsen

o.p?.q.r.s

als

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

anstatt

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

weil es leichter zu emittieren ist.

Unser AST muss sich gut für eine vernünftige semantische Analyse eignen, daher kann es sich unser Emissionsverfahren leisten, etwas komplexer zu sein, um diesem Bedarf gerecht zu werden.

@basarat @DanielRosenwasser danke für die Erklärungen. Soweit verstehe ich es, aber bei einer Sache bin ich mir immer noch nicht sicher.
Das linksassoziative ?. ist ziemlich offensichtlich und wird erwartet:

foo?.bar?.baz

Wird (ca.):

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

Aber ich verstehe überhaupt nicht, wie ein rechtsassoziatives ?. funktionieren würde. Können Sie bitte ein Beispiel geben?

Aber ich verstehe überhaupt nicht, wie würde ein rechtsassoziativer ?. Arbeit. Können Sie bitte ein Beispiel geben

@zlumer Das Laufzeitverhalten bleibt assoziativ. Ich sprach gerade vom AST, da DanielRosenwasser auch klarstellte: is not that ?. is right-associative, but that CoffeeScript special cases property accesses on the right of the ?. to be right-associative .

Unser AST muss sich gut für eine vernünftige semantische Analyse eignen, daher kann es sich unser Emissionsverfahren leisten, etwas komplexer zu sein, um diesem Bedarf gerecht zu werden.

@DanielRosenwasser danke für das Feedback :rose:

@basarat danke, plötzlich war alles klar :smiley:

Ähnlich wie im Februar-Kommentar von @basarat , I.... _sigh_...

Wenn Sie jedoch darüber nachdenken, bestehen 99 % der Anwendungsfälle darin, einen Nullzeiger auf ein Objekt zu prüfen. Ehrlich gesagt, wer macht x?.b?.c , wenn x ein number ist? Es gibt einfach nicht viele reale Anwendungsfälle für _lange_ Ketten, wenn wir _nicht_ über ein Objekt sprechen (mit der möglichen Ausnahme von string ). Bei kurzen Ketten denke ich, dass wir mit x && x.b oder x === 0 ? null : x.b leben können.

Können wir also irgendwie sagen, dass ?. nur auf Objekttypen funktioniert? Jeder andere Typ löst einen Syntaxfehler aus. Und verbieten Sie Funktionsaufrufe in der Kette.

Dann wird das Ganze in a && a.b && a.b.c transkribiert.

@schungx Was ist, wenn ein Mitglied in der Kette ein "beliebiger" Typ ist? Komplett verbieten? Oder einfach durchgehen lassen und das Beste hoffen?

Na, mein Vorschlag? Vollständig verbieten. Verdammt unelegant, ich weiß... :-)

Aber meine Begründung:

  1. Dies ist eine Abkürzung, wenn also jemand any verwendet, verwenden Sie einfach die Langschrift.
  2. Wenn jemand TypeScript verwendet, verwendet er/sie es höchstwahrscheinlich für die Tippunterstützung, also wird er/sie hoffentlich nicht viele any in der Nähe haben!
  3. any sollte wirklich mit Vorsicht behandelt werden. Die Verwendung solcher Abkürzungen mit einem flexiblen Typ wie any zuzulassen, verlangt wirklich nach Fehlern. Meiner Meinung nach sollten any so begrenzt wie möglich sein. Es ist ein bisschen wie (void *) von C – die Tatsache, dass man eine Atombombe bekommt, bedeutet nicht, dass man sie auslösen muss, nur weil man es kann!

Das wäre ein toller Betreiber!! Besonders für 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

Ich schlage jedoch eine klarere vor - um nicht zu verwirren? aus dem ? b : c Anweisungen mit a?.b Anweisungen:

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'];

Für die Klammernotation empfehle ich zwei Punkte anstelle eines einzigen, da dies mit den anderen konsistent ist, wenn keine Klammern verwendet werden. Daher ist nur der Eigenschaftsname statisch oder dynamisch über Klammern.

Zwei Punkte bedeuten, wenn es null oder undefiniert ist, stoppen Sie die weitere Verarbeitung und nehmen Sie an, dass das Ergebnis des Ausdrucks null oder undefiniert ist. (da d null oder undefiniert wäre).

Zwei Punkte machen es klarer, sichtbarer und räumlicher, damit Sie verstehen, was los ist.

Dies ist auch kein Herumspielen mit Zahlen - da dies nicht der Fall ist, z

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

Über Nummern zwei Möglichkeiten: Ihr Anruf kann angenommen werden, aber ich empfehle zuerst eine für die Kompatibilität mit bestehenden Regeln!

  1. Sollte wie jetzt fehlschlagen ( 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. Sollte funktionieren, da es versteht, dass es sich nicht um eine Nummer handelt, die eine Unterkunft von Number.prototype anruft
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

Mit dynamischen Namen:

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

Was denkt ihr Leute?

PS foo?.bar und foo?['bar'] Syntax würde auch funktionieren.

Die Verwendung der beiden aktuellen Operatoren ? : und ?. kann jedoch in derselben Zeile sehr verwirrend sein.

zB mit ?. und ?['prop']

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

im Gegensatz zu den doppelten Punkten .. und ..['prop']

var a = { x: { y: 1 } };
var b = condition ? a..x..y : a..y..z;
var c = condition ? a..['x']..['y'] : a..['y']..['z'];
Welcher sieht für dich klarer aus?

Sehr interessant. :+1:

IMHO, zwei Punkte werden verwirrender sein. Es gibt Sprachen, in denen zwei Punkte einen Bereich darstellen (z. B. 1..4 ) und TypeScript wird diese Funktion möglicherweise in Zukunft hinzufügen.

Ein Fragezeichen hat auch die semantische Bedeutung von Unsicherheit oder Bedingung und zwei Punkte vermitteln nicht dieselbe Bedeutung.

@schungx Fair genug, aber es würde für die seltsamen Möglichkeiten wie diese helfen: a?['b'] oder diese a?() .

+1 ?

a?['b'] und a?() verhalten sich gut in coffeescript, und für mich sehen sie gut aus.

Aber andererseits bin ich vielleicht einfach Kaffeeskript-blind.

+1 Ruby hat gerade den Existenzoperator https://twitter.com/mikepack_/status/657229703443451904 implementiert. Typoskript benötigt dies auch, unabhängig von der spezifischen Syntax.

Dies würde den Code sauberer machen 👍

+1 Brauche das!

Bitte, implementieren ?. -Operator, wie es C# tut

+1 Das habe ich lange vermisst

+1
so hässlich zu schreiben: someVariable && someVariable.someMember
wenn Sie schreiben könnten: someVariable?.someMember

+1, das wäre großartig .... (meistgesuchtes Feature für mich)

+1, es ist eine gute Idee!
Nur wenn das Objekt kompliziert ist, wird der Ausdruck voller ? sein. nach jeder Eigenschaft (var result=myValue?.a?.b?.c?.d?.e;), wenn ich einen Wert der letzten erhalten muss (var result=?myValue.abcde;).

+1 – Dies ist wohl eine der größten Funktionen von CoffeeScript und bei weitem die begehrteste TypeScript-Funktion meines Teams, nachdem wir einen Großteil unseres Codes von CS nach TS konvertiert haben.

+1 aber das ist zu komplex:

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

Ich mag das:

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

Der Typ von x?.y?.z ist immer der Typ des Feldes z . Natürlich muss der Typ nullable sein und der tatsächliche Wert kann null sein. Wenn es nicht null ist, muss es vom Typ des Felds z sein.

+1 Dies würde gut zur Vision von Typescript passen, die Entwicklung umfangreicher komplexer JS-Projekte zu erleichtern.

Irgendwelche Updates dazu? Ist dies ein Fall, in dem die Community für dieses Feature stimmt, damit es berücksichtigt wird? Oder wurde es in Betracht gezogen, aber es gibt einige technische Herausforderungen?

Bisher keine Aktualisierungen, da die Einführung einer neuen Syntax auf Ausdrucksebene ohne irgendeinen Vorschlag des ECMAScript-Komitees gefährlich ist.

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

Hier ist eine aktuellere Diskussion über existenzielle Operatoren (viele Gedanken, sieht aber nicht nach viel Aktion aus):

Wo soll ich "+1" schreiben, um es zu ES zu bringen?

@msklvsk ESDiscuss

Schließe dies vorerst. Da es nicht wirklich etwas TypeScript-spezifisches gibt, das dies auf Ausdrucksebene erfordern würde, sollte diese Art von großer Operatoränderung eher im ES-Spezifikationskomitee als hier stattfinden.

Die allgemeinen Stolperfallen für eine Neubewertung wären ein konkreter ES-Vorschlag, der die nächste Stufe erreicht, oder ein allgemeiner Konsens des ES-Ausschusses, dass dieses Feature für lange Zeit nicht stattfinden würde (damit wir unsere eigene Semantik definieren und vernünftig sein könnten sicher, dass sie "gewinnen" würden).

das Leben ist scheiße

Eigenständiges :+1:s löschen. Bitte nutzen Sie die GitHub-Reaktionsfunktion oder senden Sie Blumen und Süßigkeiten an Ihren nächsten TC39-Vertreter.

Sobald ich mich in Coffeescript und Swift daran gewöhnt habe, gibt es kein Zurück mehr. TS ist für mich tot, so wie es derzeit aussieht.

@algesten Ich kann swift zustimmen, wenn wir die Sprache selbst betrachten, nicht sicher über die langfristige Unterstützung coffescript (ich verwende CoffeScript in Produktionsprojekten). Wir können sicher sein, dass Sprachanalysetrends für Juni 2016 wie diese hier sind, wo wir deutlich sehen können, was in letzter Zeit bei coffescript vor sich geht, während TypeScript in den letzten Jahren das schnellste Wachstum verzeichnet hat:

TypeScript: Abgesehen von Go oder Swift ist TypeScript die am schnellsten wachsende Sprache, die wir in den letzten Jahren beobachtet haben. Das von Microsoft unterstützte JavaScript-Superset und die Angular 2-Stiftung haben im zweiten Quartal in Folge erhebliche Gewinne erzielt und sind von Platz 31 auf Platz 26 gesprungen. Das war die größte einzelne Änderung in einer der Top-30-Sprachen und der zweitgrößte Sprung insgesamt (Standard ML, 7 Plätze). Tatsächlich ist TypeScript jetzt auf Platz 26 mit Erlang gleichauf, einen Platz hinter Powershell und vier hinter CoffeeScript, das knapp außerhalb der Top 20 liegt. Die Frage, vor der die Sprache steht, ist nicht, ob sie wachsen kann, sondern ob sie das Momentum hat die Top 20 in den nächsten zwei bis drei Quartalen zu knacken und dabei Namen wie CoffeeScript und Lua zu überspringen.

Bis 2014 waren die coffescript Trends mehr als positiv, wie Sie hier sehen können, dann begann der Rückgang.

Mit dem neuen Typoskript 2.0 ist die strikte Nullprüfung (undefiniert) ein Muss, da Sie sonst keine Funktionsverkettung verwenden können!

Dies sollte in der nächsten Version von ECMAScript enthalten sein. In Anbetracht dessen, dass dies in Vanilla-JavaScript noch nützlicher wäre als in TypeScript, und in Anbetracht der Tatsache, dass die Implementierung natürlich eine Prüfung auf undefiniert oder null im Gegensatz zu einer Wahrheitsprüfung wäre, sollte es für TC39 trivial sein, es hinzuzufügen.

Die einfache Implementierung und eine, die in JavaScript idiomatisch wäre, wäre einfach, einen Kurzschluss zu machen, wenn entweder null oder undefiniert auftritt, und undefiniert zurückzugeben.

@bterlson macht das Sinn? Wie stehen die Chancen, dass ein solcher Vorschlag angenommen wird?

Einer der großen Vorteile von Typoskript ist „die Zukunft wird Ihnen heute geschenkt“. Dies ist eine der Funktionen, die mich überrascht hat, die nicht bereits vorhanden sind.

Ich hoffe, dass es bald hinzugefügt wird, da Funktionsverkettung eine beliebte Redewendung ist und die strenge Nullprüfung nicht mehr funktioniert, es sei denn, das ?. Betreiber hinzugefügt.

TS 2 wunderbare Nullprüfung hat es von einem schönen Muss gemacht!

Beim Durchlesen dieses Threads bin ich etwas überrascht, dass dies nicht mehr Aufmerksamkeit von den Betreuern erhält.

In einer idealen Welt sollte TypeScript den Weg für ES weisen und nicht umgekehrt. Im Ernst, wo wäre TypeScript jetzt, wenn das TS-Team immer darauf gewartet hätte, dass ESx ein Feature oder eine Syntax vorschlägt und fertigstellt?

Diese Syntax ist wirklich ein "Muss", wie andere darauf hingewiesen haben. Es sind in diesem Thread bisher sogar einige gute Vorschläge eingegangen. Ich denke, die Umsetzung sollte diesen Erwartungen entsprechen.

  • Im Allgemeinen sollte ein Ausdruck a?.b zur Kompilierzeit gültig sein, wenn und nur wenn a.b gültig ist.
  • Es sollte jeden Ausdruck in der Kette nur einmal auswerten.
  • Es sollte ein Kurzschluss sein.
  • Wenn die Ausführung einen mittleren Ausdruck mit dem null oder undefined erreicht, sollte dieser Wert der Rückgabewert sein.

Was sind Ihrer Meinung nach die Teile, die zu Meinungsverschiedenheiten führen können, wenn ES sie spezifiziert?

Für a?.b sehe ich keine Konflikte mit bestehender (und zukünftiger?) Syntax. Wenn der Parser das Token ?. findet, kann er es als „sicheren Navigationsoperator“ behandeln (mit Erwartungen wie von @cervengoc beschrieben).

Syntaxkonflikte treten nur auf, wenn a?(b) und a?[b] zugelassen werden, da diese auch als Beginn eines ternären Operatorausdrucks ?: interpretiert werden könnten. Aber für den Anfang denke ich, dass diese beiseite gelegt werden könnten, und die Unterstützung nur der a?.b -Syntax würde bereits viele Entwickler glücklich machen!

In einer idealen Welt sollte TypeScript den Weg für ES weisen und nicht umgekehrt.

In Bezug auf die Syntax auf Ausdrucksebene sind wir absolut anderer Meinung. Es gibt einen Grund, warum ein Komitee einen Standard vorantreibt – nicht, damit einmalige Aktionen eines Spielers einseitig über die Zukunft von JavaScript entscheiden können.

Diese Syntax ist wirklich ein "Muss", wie andere darauf hingewiesen haben.

Wenn dies ein Muss für TypeScript ist, ist es auch ein Muss für JavaScript! Bringen Sie Ihre Bedenken erneut vor das ECMAScript-Komitee .

Was sind Ihrer Meinung nach die Teile, die zu Meinungsverschiedenheiten führen können, wenn ES sie spezifiziert?

Zumindest denke ich, dass es Meinungsverschiedenheiten darüber geben wird, ob die Syntax zu null oder undefined , wenn sie auf diese Werte stößt, oder immer zu undefined . Es wird auch Streit darüber geben, ob irgendeine Form von Klammersyntax unterstützt wird oder nicht. Es stellt sich auch die Frage, wie sich a?.b.c verhält. Es gibt auch die Frage von ?. vs. .? vs. a.b? . Es stellt sich die Frage, welche Auswirkungen dies auf den Operator delete hat.

Der ES DIscuss-Thread dazu ist über 100 Kommentare lang. An Zweideutigkeit mangelt es nicht! Es ist leicht, ein Beispiel isoliert zu betrachten und zu denken, dass es nicht unzählige Sonderfälle geben kann. Es gibt. Das ist wahrscheinlich der Grund, warum sich noch niemand bei TC39 dafür eingesetzt hat und _auch_, warum wir es nicht eilig haben, ein Feature hinzuzufügen, bei dem es viele Unklarheiten darüber gibt, wie es sich verhalten sollte.

Ich entschuldige mich, ich habe den erwähnten Thread nicht gelesen, ich werde ihn mir auf jeden Fall ansehen, um mehr zu sehen.

Wir sehen das etwas anders. Über das Komitee, meiner ehrlichen Meinung nach ist dies einer der Hauptgründe, warum JavaScript niemals _gut_ sein wird. Nur um ein Beispiel zu nennen, viele der erfolgreichsten Programme, die ich gesehen habe (wie Total Commander oder IrfanView), sind erfolgreich, weil sie von EINER Person gepflegt und entworfen werden und nicht von einem *Komitee". Natürlich ist dies nicht vollständig richtiges Beispiel, aber ich bin mir fast sicher, wenn Sie zB alleine den kompletten ES6 entworfen hätten, dann wäre die Welt jetzt ein besserer Ort.

Außerdem sind die Unklarheiten, die Sie erwähnt haben, zu 99 % _theoretisch_ und für die Entwicklerseite irgendwie irrelevant. Wen würde es interessieren, was es zurückgibt, null oder undefined ? Wählen Sie einfach eine aus, und wir werden sie so verwenden.

Alles in allem stehen Sie und dieser Ausschuss auf einer anderen Seite als die meisten von uns, und die Dinge auf dieser Seite sind normalerweise komplexer als sie wirklich sind. Und dies kann, gelinde gesagt, zu einer gewissen Kontraproduktivität führen. Nehmen Sie es nicht persönlich, aber nach meiner Erfahrung im Allgemeinen sollten einige Leute besser öfter aus dem Konferenzraum kommen und sich etwas Code ansehen.

Natürlich nichts für ungut, nimm nichts persönlich, ich habe großen Respekt vor dir und dem gesamten TS-Team, denn du hast die clientseitige Entwicklung vieler Entwickler revolutioniert, mich eingeschlossen, und danke dir für all deine Arbeit. Wir sind nur ein bisschen enttäuscht über dieses spezielle, denke ich.

Ein letzter Gedanke. Ich bin den erwähnten ES-Thread durchgegangen, und eines ist absolut sicher: Sie verkomplizieren es zu sehr. Sie wollen etwas entwerfen, das für jedes Szenario gut ist.

Ich persönlich wäre mit einem Conditional Member Access Operator vollkommen zufrieden und glücklich. Benötigen Sie keinen bedingten Aufruf, keine bedingte Indexsignatur, müssen Sie nicht jedes ausgefallene Szenario unterstützen, das gültiger JS-Code ist. Das ist alles. Aber stattdessen werden sie wahrscheinlich weiterhin dort sitzen und diskutieren, wie sie alles auf einmal erledigen können, was ein großartiger Plan ist, aber wir werden am Ende des Tages nichts haben.

Alles in allem stehen Sie und dieser Ausschuss auf einer anderen Seite als die meisten von uns, und die Dinge auf dieser Seite sind normalerweise komplexer als sie wirklich sind.

Ich glaube nicht, dass Sie den wahren Status von Ryan oder TC39 genau wiedergeben. Ryan und das TypeScript-Team haben sich sehr klare Designziele für TypeScript gesetzt. Eines der ursprünglichen und immer noch sehr aktuellen Ziele ist, dass TypeScript eine Obermenge von JavaScript ist. Nicht die Sprache, die die Leute gerne hätten (zB Dart, Haxe). Was die Syntax angeht, hat das TypeScript-Team auf die harte Tour gelernt, wie teuer es ist, sie vorab zu erfinden (z. B. Module). Wir steuern auch kopfüber auf eine Herausforderung mit privaten Klassenmitgliedern zu, bei der die vorgeschlagene ES-Syntax völlig inkompatibel mit der Syntax ist, die TypeScript verwendet. Warum? Denn was an der Oberfläche unkompliziert aussieht, ist angesichts der Laufzeitherausforderungen einer Sprache unmöglich zu erreichen.

TC39 hat meiner Meinung nach JavaScript "gespart". ES4 wurde aufgegeben, nicht weil es an guten, innovativen Ideen mangelte, sondern weil es das Internet kaputt machen würde. TC39 hat sich in Form gebracht, sie haben ihre Diskussionen geteilt und waren völlig offen in ihren Diskussionen und wie sie Entscheidungen treffen und uns ES2015 geliefert haben, das ES4 sehr ähnlich ist, aber das Internet nicht kaputt gemacht hat. Es ist erstaunlich, dass wir im Wesentlichen JavaScript-Laufzeiten haben, die Code von vor 10 Jahren problemlos ausführen, aber viele signifikante Verbesserungen der Sprache unterstützen. ES2016 war die Ruhe vor dem Sturm. ES2017 hat eine "angemessene" Menge an Funktionalität und Änderungen und einen klaren Steuerungsprozess, der in die richtige Richtung weist.

Auf der „anderen Seite“ der Dinge zu stehen, hat meiner Meinung nach also eindeutig funktioniert. Was die Zweckmäßigkeit von „must have“-Features übertrifft.

@kitsonk Ich meinte "andere Seite" nicht negativ und vor allem wollte ich nicht die Arbeit herabsetzen, die in TypeScript oder ES6 gesteckt wurde. Darüber hinaus ist das Beste an TypeScript meiner Meinung nach, dass es wirklich ein klares Designziel hatte und hat, und dass es wie viele andere Open-Source-Sachen gut davor geschützt ist, zu einem Chaos zu werden.

Ich wollte nur sagen, dass genau diese Funktion ein klares Beispiel dafür ist, wo eine Gruppe genialer Leute am Ende Dinge überdenken und übermäßig verkomplizieren wird, anstatt einfach den einfachen Weg zu gehen und einige Einschränkungen zu akzeptieren, wie z. B. keine Unterstützung von Aufrufen oder Indexsignaturen usw Jemand in diesem Forum hat sogar vorgeschlagen, diese Syntax in Aufgaben zu verwenden, was ziemlich verrückt ist. Ich denke immer noch, dass dieses Phänomen in diesem Sinne kontraproduktiv ist.

Ich verstehe, dass es auf Ihrer Seite ärgerlich ist, dass beispielsweise private Mitglieder mit dem endgültigen ES6-Konzept nicht mehr kompatibel sind. Aber auf der anderen Seite hatten wir es. Weit vor ES6. Und das ist der Hauptpunkt von unserer Seite. Grob gesagt ist es uns egal, wie Sie es schaffen, den entsprechenden Code dafür auszugeben, wir verwenden ihn einfach glücklich. Dasselbe gilt für Module und alles. Wir (oder zumindest ich) haben diese Schmerzen nicht gesehen, wovon du sprichst, wir waren immer glücklich mit privaten Mitgliedern oder Modulen.

Diese spezielle Funktion ist in CoffeScript enthalten, wie ich darüber gelesen habe. Warum müssen wir einfachen Entwickler immer Kompromisse bei der Auswahl einer Plattform/Library/Plugin etc. eingehen? Ich meine immer . Das ist irgendwie nervig. Hier haben wir eine großartige Sprache, die großes Potenzial hat, die alle anderen Teilnehmer (einschließlich ES!) komplett hinter sich lässt und die einen großen Teil der clientseitigen Entwicklung erfolgreich revolutioniert hat, und wenn es um dieses "einfache" Feature geht ( Ich meine zumindest den Teil des Mitgliederzugriffs), wir hören, dass es nicht implementiert wird, bis ES sich dazu verpflichtet.

Ich wollte den Leuten kurz mitteilen, dass dieses Feature beim heutigen TC39-Meeting von Stufe 0 auf Stufe 1 verschoben wurde.

Relevantes Commit: https://github.com/tc39/proposals/commit/cb447642290a55398d483f5b55fb7f973273c75d
Tagesordnung des Meetings: https://github.com/tc39/agendas/blob/master/2017/01.md

Beeindruckend! das ist riesig!

Einige "Überraschungen", die ich hier sehe (ohne zu sagen, dass ich anderer Meinung bin, nur Dinge, die wir wahrscheinlich anders gemacht hätten, wenn wir dies früher getan hätten):

  • null wird nicht aus einem a?.b -Ausdruck erzeugt: Wenn a gleich null ist, erzeugt dies stattdessen undefined
  • ~Propagation in verketteten Punkten: a?.b.c.d löst nicht aus, wenn die Eigenschaften b und c undefined sind ~ Ryan kann nicht lesen
  • ~Propagation in Gegenwart von Parens : sogar (a?.b).c löst nichts aus, wenn b undefiniert ist~ Ryan kann nicht lesen
  • ~Die Weitergabe erfolgt sogar bei Methodenaufrufen: a?.b.c().d gibt undefined zurück, wenn der Aufruf von c null zurückgibt ~ Ryan kann nicht lesen
  • Der Operator delete wird unterstützt
  • Klammersyntax a?.[x] wird unterstützt
  • Funktionsaufrufsyntax func?.(...args) wird unterstützt, auch für Nicht-Methodenaufrufe (!)

Ich würde erwarten, dass sich in diesen Bereichen bis Stufe 2 etwas ändern wird.

Ich denke, Coffeescript hat es richtig gemacht.

a?.bc löst aus, wenn b nicht definiert ist.

a?() und a?[0] sind beide gut.

  • Ausbreitung in verketteten Punkten: a?.bcd wird nicht ausgelöst, wenn b- und c-Eigenschaften nicht definiert sind
  • Fortpflanzung in Gegenwart von Klammern: gerade (a?.b).c löst nicht aus, wenn b undefiniert ist
  • Die Weitergabe erfolgt sogar bei Methodenaufrufen: a?.bc().d gibt undefiniert zurück, wenn der c-Aufruf null zurückgibt

Diese Punkte scheinen mir nicht genau zu sein. Aus dem Vorschlag:

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, das habe ich total überlesen. Du hast recht. Aktualisierung

@algesten aus dem ursprünglichen Vorschlag:

a?.()

b?.[0]

Süss. der Operator kann dann als ?. bezeichnet werden.

Hier finden einige zusätzliche Gespräche statt: https://github.com/estree/estree/issues/146

Ein Zitat, das gut zutreffen könnte: «Mache einfache Dinge leicht und schwierige Dinge möglich ». Unterstützen Sie daher vielleicht die häufigsten Fälle gut, während Sie (zumindest anfänglich) die komplizierten/seltenen Fälle überspringen, während sie mit längerer (bestehender) Syntax immer noch "manuell erledigt" werden dürfen.

Nur meine zwei Cent

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

zu:

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

@cedvdb völlig andere Semantik - Ausnahmen, die in Gettern ausgelöst werden, sollten keine Koaleszenz verursachen

@RyanCavanaugh ja .. Ich habe das nicht durchdacht.

Ist dies jetzt auf dem Radar für die Implementierung oder wird das TS-Team warten, bis der ES-Vorschlag weiter voranschreitet?

Es steht auf unserer Shortlist; Wir haben immer noch ein paar Fragen/Bedenken, aber im kommenden Monat sollten Sie diesbezüglich Bewegung sehen.

Ich bin mir nicht sicher, woher der Kommentar von @mhegazy stammt - die Anzahl der offenen Fragen zum TC39-Vorschlag ist zu groß, als dass wir hier sinnvoll arbeiten könnten. Insbesondere Fragen dazu, wie null und undefined interagieren und welche Syntax tatsächlich unterstützt wird, müssen zuerst geklärt werden. Stufe 2 ist ein absolutes Minimum, und wir würden Stufe 3 angesichts der Auswirkungen auf das Laufzeitverhalten bevorzugen.

Funktioniert dieser einfache Code?

a == undefined ? expression : undefined

expression bedeutet ax, a[x], a(x), delete könnte hier auch generiert werden

dann wird a?.b?.[c]?.(d) generiert

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

scheint alle Regeln von RyanCavanaugh zu durchlaufen


Wenn Sie den Operator == hassen, könnte es auch a === undefined || a === null sein

@zh99998 du _musst_ == hassen, weil '' und 0 auch gleichgesetzt werden. Es wird fast argumentiert, dass das Laufzeitverhalten eine Art Überprüfung von (typeof value === 'object' || typeof value === 'function' || typeof value === 'symbol') && value !== null sein sollte, was jetzt ziemlich komplex wird.

Wie @RyanCavanaugh sagte, ist es unwahrscheinlich, dass es Fortschritte macht, bis der TC39-Vorschlag dafür mindestens Stufe 2 oder 3 erreicht hat.

Ich sehe == nur gleich null und undefined als
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness

und Test in der Chrome-Konsole bestanden:

'' == undefined
false
0 == undefined
false

@kitsonk undefined erzwingt nur Null und umgekehrt. Kein anderer Wert wird auf undefined oder null gezwungen.

Sie scheinen mit falschen Werten verwirrt zu sein. 0 und "" sind zwar falsch, werden aber niemals auf null oder undefiniert gesetzt.

== impliziert Zwang. null == 0 ist falsch, weil nichts außer undefined auf null zwingen kann. Gleiches gilt für undefined == 0 .

Ein anderes Beispiel könnte sein

    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

Du bekommst das Bild.

Ich sehe viele Versuche mit ternären Operatoren, aber jede Implementierung, die mehrmals auf dieselbe Eigenschaft verweist, könnte zu unerwarteten Nebenwirkungen führen.

Glücklicherweise verfügt JavaScript über IIFEs, sodass Sie das Ergebnis eines Accessors in einem Funktionsparameter speichern, beliebig oft darauf verweisen und es nie mehr als einmal auswerten können. In meinem Beispiel unten erstelle ich ein coalesce -Lambda, das mehrmals anstelle eines Ausdrucks aufgerufen werden kann, der ?. -Operatoren enthält.

Eine Sache, mit der sich die Sprachimplementierer befassen müssten, sind Array- und Funktionsaufrufe mitten in einem Ausdruck. Ich denke, der Compiler könnte diese Situationen erkennen und diese Ausdrücke einfach an das Ende des Coalesce-Aufrufs anhängen.

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]

Beachten Sie, dass kein tatsächlicher globaler Name namens "coalesce" erforderlich ist. Dieser Code könnte direkt in jeden Ausdruck eingebunden werden. Es könnte jedoch das Aufblähen reduzieren, indem es ihm einen Namen gibt.

Ich mache mir keine allzu großen Sorgen um die Syntax, die für den Operator verwendet wird, oder ob die Sprachimplementierer auf einen Standard warten möchten. Ich dachte nur, ich würde einen anderen Ansatz zeigen.

Dies bringt auch die Notwendigkeit eines ?? -Operators mit sich. In C# ersetzt dies jeden null -Ausdruck durch das, was rechts davon steht.

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";

Leider erfasst Wahrhaftigkeit zu viele Grenzfälle ( 0 , false , etc.). Wenn Sie mit einem Null-Coalesce-Operator ( ?. ) arbeiten, möchten Sie etwas Spezifisches für null -ness.

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

@jehugaleahsa , in Ihrem Beispiel mit Coalesce müsste es eine Möglichkeit geben, Funktionsaufrufe und Memberzugriff zu verhindern, wenn die vorherige Prüfung null zurückgegeben hat. Im x?.f()-Beispiel sollte f nicht aufgerufen werden, wenn x null ist.

@bschlenk Ich glaube nicht, dass ich damit einverstanden bin. Ich denke, es sollte mit einer Nachricht wie null is not a function fehlschlagen, aber das liegt nicht an mir, denke ich.

Die jüngste Flut an Kommentaren, die mögliche Wege zur Implementierung des Operators beschreiben, ist etwas seltsam.
Die Implementierung ist wahrscheinlich ein gelöstes Problem.

Wenn Sie interessiert sind, gibt es die idx-Bibliothek , die dem Verhalten des Operators ?. sehr ähnlich ist, obwohl sie auch viele Details des geplanten Operators ignoriert. Wie auch immer, ihre Spezifikationen für die Kompilierausgabe könnten für jeden interessant sein, der sich fragt, wie dieses Zeug implementiert werden könnte.

TS könnte so etwas ausgeben oder es könnte etwas völlig anderes ausgeben, aber ich glaube nicht, dass wir hier darauf warten. Es wurde hier oft gesagt, dass TS den Betreiber nicht bekommt, bis der ES-Vorschlag in die eine oder andere Richtung geht.

Es ist die Semantik, die noch einige Unbekannte hat, die hier und hier aufgelistet sind.

Seien Sie versichert, dass wir dies korrekt implementieren und hier keine weiteren 100 Kommentare benötigen, um herauszufinden, was || und ? ... : ... tun. Wie @noppa feststellte, warten wir nur darauf, dass die ES-Spezifikation fertiggestellt wird.

https://github.com/babel/babel/pull/5813 (zugehörig zu babylon PR ) wurde gerade in Babels preset-stage-1 eingebunden. Die Spezifikation befindet sich natürlich noch in Phase 1, aber dies wird dazu beitragen, sie voranzutreiben.

Vielleicht irre ich mich, aber ich habe in diesem Thread keinen offensichtlichen Link zum tc39-Vorschlag gesehen, also hier für die zukünftigen Leser: https://github.com/tc39/proposal-optional-chaining

FYI optional Chaining wird nächste Woche bei TC39 https://github.com/tc39/agendas/blob/master/2017/07.md sein

@jehugaleahsa Ich denke, du hast Recht und ich werde nächste Woche ?? auf der TC39 präsentieren. Sie können den Vorschlag hier verfolgen: https://github.com/gisenberg/proposal-nullary-coalescing

Ich sehe, dass die optionale Verkettung beim TC39 abgedeckt wurde ... Wie war das Urteil?
Hoffentlich hat es gereicht, um das in Typescript voranzubringen 😉

@markwhitfeld Aus der Zusammenfassung der Notizen :
Optionale Verkettungsoperatoren: Bleibt auf Stufe 1, kommt später mit klareren Definitionen für verschiedene Optionen und Antworten auf Feedback

Vollständige Notizen hier: https://github.com/rwaldron/tc39-notes/blob/master/es8/2017-07/jul-27.md#13iia -optional-chaining-operator

Es gibt noch offene Fragen dazu, wie sich der Operator verhalten soll, also scheint es, als wäre er noch nicht in einem Zustand, in dem er zu TypeScript hinzugefügt werden kann.

Aus diesen Notizen geht hervor, dass der Ausschuss keine Ahnung hat, wie die vorgestellten Optionen funktionieren. Ich hätte gedacht, dass sie sich vor der Diskussion über die Vorschläge informiert hätten, die sie diskutieren wollten. Ich schätze, es wird noch eine Weile dauern, bis ich strenge Nullprüfungen aktivieren kann.

Ich hoffe sehr, dass sie sich für Option 2/4 entscheiden (was ohnehin der aktuelle Stand des Vorschlags ist).

15. Juli 2014 - 4. September 2017, noch nichts

@frankfvb Sie haben die Ausgabe eindeutig nicht gelesen.

Es gab viele Diskussionen, die das Kernteam zu der Annahme veranlasst haben, dass es unklug wäre, an dieser Stelle zu implementieren, bis weitere Fortschritte beim ECMAScript-Vorschlag vorliegen, die sich direkt auf die Funktionalität dieser Funktion in TypeScript auswirken würden.

Seit der letzten Sitzung des ECMAScript-Standardausschusses befindet sich der Vorschlag in Phase 1 , da er einige sehr grundlegende Fragen zur Implementierung enthält. Obwohl es keine feste Regel ist, implementiert TypeScript nur Vorschläge der Stufe 3. Es implementiert manchmal Vorschläge der Stufe 2, wenn sie der Meinung sind, dass dies von entscheidender Bedeutung ist, und die potenzielle Verwendung in TypeScript die Entwicklung des Standards vorantreibt.

Ich bin mir nicht sicher, wie klarer die Leute darüber sein können.

Wie ich bereits sagte , steht dies auf unserer Shortlist. wir warten auf TC39, um eine Art Konsens über die Semantik des Operators zu erzielen. Wir würden es hassen, es zu veröffentlichen und dann Benutzer zu brechen.

Dies ist nicht der Thread, um die TC39-Diskussion wieder aufzuwärmen

Wenn Sie sich zu dem Vorschlag äußern möchten, kommentieren Sie ihn an der entsprechenden Stelle . Ich habe auch Meinungen, aber sie in diesem Thread fallen zu lassen, wird nichts tun.

Ich habe etwas Einfaches geschaffen, das meinen aktuellen Bedürfnissen entspricht. Es funktioniert nur in einer Kette, in der jeder Link ein Eigenschaftsname ist, sodass der Zugriff auf ein Element in einem Array (z. B.) nicht unterstützt wird.

Implementieren eines wirklich einfachen Elvis-Operators in TypeScript

Auch wenn Sie Lodash/Unterstrich haben, können Sie bereits _.get(Book, 'author.name.firstName') verwenden, was das tut, was dies will

Bearbeiten: Anscheinend ist dies ein schlechter Rat wegen Typproblemen mit der Methode _.get() . Siehe Kommentar unten

@tolgaek , _.get hat schlechte Typisierungen, selbst mit diesen besseren Typisierungen ( noch nicht zusammengeführt , wegen Autoren) kann Typoskript den Ergebnistyp nur dann definitiv ableiten, wenn die Objekttiefe 1 ist, in allen anderen Fällen ist es any und muss zur Laufzeit überprüft werden

Auf der anderen Seite kann Typoskript mit Elvis Operator in der Lage sein, den Ergebnistyp in Objekten mit beliebiger Tiefe abzuleiten, deshalb freue ich mich auf Elvis Operator

Oh, ich verstehe, ich wusste nicht, dass es ein Tippproblem gibt. Danke @BjornMelgaard

@mhegazy kann diese Funktion nicht zuerst implementiert und als experimentelle Funktion markiert werden? Ich denke, die Leute sollten kein Problem haben, wenn die Spezifikation in der experimentellen Funktion geändert wird.

Elvis ist nicht amüsiert, so lange zu warten.

Es ist in Babel7 gelandet. Typoskript, wir laufen langsam. Jemand, bitte, mach das möglich.
:)

@gs-akhan das Babel-Plugin implementiert eine alte Version des Vorschlags von vor einigen Monaten. Seitdem gab es Änderungen an dem Vorschlag (einschließlich einer wesentlichen Änderung, wie der Operator geparst wird), und es wird wahrscheinlich weitere Änderungen geben, bevor das Feature Stufe 2 erreicht (geschweige denn Stufe 3), also jeder Code, der mit dem aktuellen babel geschrieben wurde Plugin könnte kaputt gehen, wenn das eigentliche Feature veröffentlicht wird. Babel implementiert absichtlich vorgeschlagene Features, bevor sie stabil sind, damit die Spezifikationsautoren und andere interessierte Parteien das Feature wie vorgeschlagen ausprobieren können. Nur weil Babel ein Feature implementiert hat, bedeutet das nicht, dass es auf eine Art und Weise implementiert werden kann, die in Zukunft keine Breaking Changes erfordert.

@alangpierce Das macht Sinn. Danke

Ich verstehe, dass dies ein wirklich, wirklich netter Betreiber ist, aber ihn verfügbar zu haben, bevor seine Regeln ausgebügelt wurden, ist ein Fußgewehr, und das werden wir nicht tun. Das Laufzeitverhalten des Operators ist noch im Fluss; Wenn Sie heute Code schreiben, könnte er morgen auf eine Weise nicht mehr funktionieren, die nicht sofort ersichtlich ist - vielleicht seltene Abstürze, vielleicht Datenbeschädigung, wer weiß? Ein wenig Geduld erspart Ihnen jetzt in ein paar Monaten viel Schmerz.

Beginnen zu glauben, dass dieses Ticket gesperrt (nicht geschlossen) werden sollte, bis die Spezifikation fertig ist.

Wann wird die Spezifikation fertig sein?

@oliverjanik Den aktuellen Spezifikationsentwurf finden Sie hier . Es gibt einen Tagesordnungspunkt, um den Vorschlag beim nächsten TC39-Treffen (26.9.-28.9.) auf Stufe 2 vorzurücken. Ich werde diese Folien zu dieser Zeit präsentieren. Personen, die frühzeitig eine Überprüfung vornehmen und Feedback geben möchten, melden Probleme bitte im Proposal-Repository .

Vielen Dank @gisenberg , dass du dich für dieses Thema für uns eingesetzt hast! Ich habe darüber nachgedacht, eine zusammenfassende Präsentation zusammenzustellen, um die Optionen rund um den Bediener zu klären, die beim TC39-Meeting verwendet werden könnten, um Verwirrung zu vermeiden, aber Sie haben dies bereits getan. Tolle Arbeit!
Vielleicht ist eine andere Sache, die für die TC39-Konversation (und das Foliendeck) von Vorteil sein könnte, die Semantik und Syntax des Operators in anderen Sprachen zu betrachten. Obwohl andere Sprachen nicht unbedingt vorschreiben sollten, wie es in Javascript funktionieren sollte, wäre es hilfreich, den Operator ähnlich wie in anderen Sprachen zu halten, um Verwirrung zu vermeiden.
Viel Glück für nächste Woche!!!

Entschuldigen Sie, dass ich wieder einmal etwas vom Thema abgekommen bin, aber ich dachte, einige Leute hier könnten es interessant finden, dass es in Flow jetzt möglich ist, einigermaßen funktionierende Typdefinitionen für sichere Getter-Funktionen wie _.get hinzuzufügen.

Beispiel: flowtype.org/try

Nicht das schönste Stück Code aller Zeiten und es unterscheidet nicht richtig zwischen null und undefiniert, aber ansonsten scheint es ganz gut zu funktionieren.

AFAIK das einzige, was TS fehlt, um dasselbe zu tun, ist so etwas wie $NonMaybeType .
Natürlich nicht, dass es diesen Operator überflüssig machen würde, ich fand das nur cool.

Dies erreichte Stufe null beim letzten undefined -Meeting aufgrund von Bedenken hinsichtlich der syntaktischen Konsistenz in Bezug auf den Zugriff von Klammern vs null -ausgewerteter Operand) sowie offene Fragen darüber, welche Art von Ausdrücken no-op'd sein dürfen (zB x.?b() wenn x.b ein number ist)

(stimme 🎉 über diesen Kommentar ab, um faule Früchte zu werfen)

Danke, dass Sie uns das mitteilen. Ach wie schade. Vielleicht muss der Geltungsbereich eingeschränkt werden, damit er einfacher, aber dennoch nützlich ist?

Vielleicht muss der Geltungsbereich eingeschränkt werden, damit er einfacher, aber dennoch nützlich ist?

Das ist die Herausforderung, der sich TC39 gegenübersieht, und obwohl es beschissen ist, muss ich zugeben, dass ich froh bin, dass die Leute das durchmachen. Es ist wirklich schwierig für sie, eine ziemlich komplexe Level-Syntax einzuführen, und tatsächlich verursacht die schwache Typisierung der Sprache in diesem Fall tatsächlich eine erhebliche Menge an Grenzfällen, die angegangen werden müssen, oder Sie erhalten Code, der 💥 geht, was nicht geht ist für niemanden gut. Ich glaube nicht, dass Sie durch die Einführung eines Operators wie diesem seinen Geltungsbereich einschränken können. Es wäre einfacher für die Implementierer, 90 % der Fälle abzudecken, aber ich glaube nicht, dass ¯\_(ツ)_/¯ für die restlichen 10 % gültiger Code ist.

Leute, mehr als 3 Jahre später würde ich sagen, es ist an der Zeit, dem Komitee „Fuck you“ zu sagen und es auf unsere eigene Weise zu tun, was auch immer für TypeScript idiomatisch ist. Diese Funktion kann ohne statische Eingabe sowieso nicht richtig funktionieren.

Erstellen Sie eine TypeScript-Implementierung mit einer Syntax, die ausdrücklich nicht mit dem TC39-Vorschlag kompatibel ist. Sobald ES einen Safe-nav-Operator erhält, hat TypeScript zwei Optionen: eine mit beschissener Semantik, die mit ES kompatibel ist, und eine, die an das Typsystem gebunden ist. Dies bedeutet, dass Sie den TS-Safe-Nav-Operator nicht mit einem beliebigen "Typ" verwenden können, und das ist in Ordnung.

@notsnotso Typescript soll JS nicht brechen, dafür ist Coffeescript da.

Vielleicht ist eine gute Lösung:

  • ganz einfach umsetzen? Operator für ungeduldige Entwickler, als experimentelles Feature (wie Decorator), mit Warnung - es WIRD Ihren Code in Zukunft brechen
  • warten Sie weitere 3 Jahre, wenn der Standard geschrieben wird, implementieren Sie es als nicht-experimentelles Feature. Tutorial schreiben, was kaputt sein könnte. Sogar mit statischer Typisierung ist es möglich, Warnungen zu schreiben, wenn Leute Code mit einer neuen Operatorimplementierung kompilieren.
    "Mach es auf unsere eigene Weise, was auch immer für TypeScript idiomatisch ist" ist kein Fall, denn in 3 Jahren werden die Leute mit dem Problem konfrontiert sein, dass ts elvis nicht so funktioniert wie in js.

Ich bin nicht überrascht, dass das nicht geklappt hat, um ehrlich zu sein. In meinem Original
post, wies ich auf die Mehrdeutigkeit bezüglich Indizierung, Funktionsaufrufen usw. hin.
Ehrlich gesagt, je mehr ich über ?. nachdenke, desto mehr fühlt es sich so an, als ob es das nicht wäre
gehören in JavaScript, da es undefined hat.

Ich hätte viel lieber ein allgemeineres Dienstprogramm, das dieses Problem löst
und mehr. Ein Gedanke, den ich hatte, war so etwas wie ein Inline- try/catch
Ausdruck ( let x = try a.b.c else 0 ) in Verbindung mit einem Operator that
auf „nully“ (z. B. x ?? 1) und nicht auf „falsey“ (z. B. x || 1) geprüft.
Sie würden sie also folgendermaßen kombinieren: try a.b.c ?? 0 else 0 . Es ist wortreich, ja,
aber es heißt im Grunde: Versuchen Sie, abc auszuwerten und ob das Ergebnis null oder ist
undefined , gib 0 zurück. Wenn a oder b undefined ist und eine Ausnahme ausgelöst wird,
Fangen Sie es und geben Sie eine 0 zurück.

Eine Alternative wäre, die Klausel else optional zu machen, was standardmäßig der Fall ist
undefined . Dann könnten Sie den Ausdruck schreiben als: let x= (try a.b.c) ?? 0 . Das ist verdammt kompakt, vermeidet Mehrdeutigkeiten und bietet mehr
Allzwecklösung, die andere Probleme lösen kann.

Ich sage nicht, dass wir stattdessen darauf drängen sollten; Alles, was ich sage, ist da
sind Alternativen zu ?. und wir sollten unsere Möglichkeiten wirklich erkunden, bis wir
Finden Sie eine, die gut zur JavaScript-Sprache passt.

Am Donnerstag, 5. Oktober 2017 um 7:51 Uhr, Dmitry Radkovskiy [email protected]
schrieb:

@notsnotso Typescript soll JS nicht brechen, das ist was
Coffeescript ist für.


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/Microsoft/TypeScript/issues/16#issuecomment-334441781 ,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/ABTgPilbZfuKc2egdBrYfdTHHeDl3F6Sks5spMLLgaJpZM4CNapf
.

@zlumer netter Witz. Allerdings würde eine TS-spezifische Funktion Javascript nicht beschädigen.

@jehugaleahsa Ich mag deinen Vorschlag und er ist in anderen Sprachen zu finden. Ich denke, es würde gut für TS funktionieren.

Ich werde sagen, dass ich die starke Notwendigkeit, zu warten, bis ECMAScript den Operator akzeptiert, nicht wirklich verstehe. TypeScript fügte Klassen, Module und Lambdas hinzu, lange bevor sie ihren Weg in ECMAScript fanden. Tatsächlich war/ist eines der erklärten Ziele von TypeScript die Erprobung experimenteller JS-Funktionen. TypeScript, das seine eigene Implementierung bereitstellt, würde zweifellos dazu beitragen, diese Diskussionen im Komitee zu informieren.

Ihr wart bereit, bahnbrechende Änderungen vorzunehmen, bevor das Komitee schließlich eine andere Richtung einschlägt. Ich verstehe nicht wirklich, warum diese Funktion so anders ist.

Auch async/await wurde schon früh in TypeScript eingeführt.

Allerdings würde eine TS-spezifische Funktion Javascript nicht beschädigen.

Es wird so etwas wie „TS-spezifisches Feature“ nicht geben, bitte überprüfen Sie TypeScript Design Goals für weitere Informationen.

TypeScript kommt an, bevor ES auf einen hellen Pfad geht, es könnte einige existieren,Sie werden nur aus Kompatibilitätsgründen beibehalten.

TypeScript fügte Klassen, Module und Lambdas hinzu, lange bevor sie ihren Weg in ECMAScript fanden.

Und gerade Module sind ein riesiges Debakel, das noch immer für Verwirrung sorgt. Das ist ein Beispiel, das das TypeScript-Team wiederholt als Beispiel für einen _Fehler_ und zu frühes Überspringen verwendet hat. Wir haben jetzt auch private Felder, für die ich in den letzten 5 Jahren dankbar war für private , aber es wird kein Ende der Verwirrung stiften.

Auch hier waren Dekorateure unter der Flagge verfügbar, aber jetzt, wo Dekorateure tatsächlich Stufe 3 erreichen, wird es eine Neuimplementierung und einen Codebruch für TypeScript erfordern. Deshalb können diese Dinge _nicht_ für wahrscheinlich gehalten werden.

Auch async/await wurde schon früh in TypeScript eingeführt.

Sobald der ECMAScript-Vorschlag Stufe 3 erreicht hat.

Niemand benimmt sich schlecht, aber wenn dieses Gespräch nur im Kreis geführt werden kann (was wäre, wenn es eine Flagge gäbe? Ja, wir sind uns der Flaggen bewusst) oder off-topic (was, wenn TS aufhört, JS zu sein? Nein, fünf Jahre später ändern wir uns nicht unsere Gedanken darauf), wir müssen es nicht haben. Wir sagen seit ungefähr 3 Jahren, dass wir dies genau dann implementieren werden, wenn das ES-Komitee seine Semantik sperrt.

Auch hier ist das Proposal-Repo https://github.com/tc39/proposal-optional-chaining und Sie können den Fortschritt dort verfolgen. Wir werden offline arbeiten, um zu versuchen, die Chancen des Vorschlags beim nächsten TC39-Treffen zu verbessern, weil wir wirklich wollen, dass dies auch durchgeht.

Update: Wir haben heute Nachmittag bei TC39 Stufe 2 erreicht!!!

Optionale Verkettung ist Stufe 3

Diesen nur zur Feier kurz aufsperren

Hurra!

Nicht spammen...

Sie können ein Emoji senden, das Ihre Gefühle ausdrückt

Nicht spammen...

Sie können ein Emoji senden, das Ihre Gefühle ausdrückt

Außerdem macht es Spaß, zuzusehen, wie die Emoji-Zählung so steigt. Ich habe noch nie gesehen, dass ein Kommentar zu einem Thema so schnell so viel Popularität erlangt hat!

Ich habe ein kleines Video der Echtzeit-Updates aufgenommen https://youtu.be/JLBrgPjeGhc

Kann mich jemand von diesem Ding abmelden?

@DanielRosenwasser Falls du nicht scherzt, oder für alle anderen, die sich abmelden wollen und nicht wissen wie, suchst du diesen Button in der rechten Seitenleiste:

image

Ganz zu schweigen von einem Link in der E-Mail:

image

Es war ein Witz, ich arbeite an dem Vorschlag.

@RyanCavanaugh nach dem Freischalten dieses Problems:
martian

Wirklich aufgeregt, das endlich landen zu sehen! 🎈 🎉

Ich kann den passenden VSCode-Quick-Fix kaum erwarten 😆

image

Ich gehe zu @ @RyanCavanaugh , weil er diesen Thread wahrscheinlich nicht abonniert hat und ich unhöflich sein möchte! (und @DanielRosenwasser zur Sicherheit)

@kitsonk Sei kein Arsch. Es steht den Menschen frei, sich abzumelden und nicht belästigt zu werden.

@kitsonk , Warum sollten RyanCavanaugh oder DanielRosenwasser diesen Thread abbestellen? Ryan hat dieses Problem freigeschaltet und Daniel hat drei Kommentare über Ihnen beantwortet.

Selbst wenn sie abgemeldet wurden, besteht keine Notwendigkeit, mehr Benachrichtigungsmüdigkeit durch Spam zu verursachen.

Anscheinend ist GitHub ein schrecklicher Ort für sarkastischen Humor, gee ...

Ein großes Dankeschön an unsere Champions bei TC39, die die fiesen Details dieser neuen Sprachfunktion herausgefunden haben!

thanks

Ich denke, @kitsonk hat nur Spaß gemacht, genau wie ich es irgendwie war. Während wir angesichts der Aufregung ein wenig albern sind, ist dies eine sanfte Erinnerung daran, die Dinge gemäß dem CoC höflich zu halten.

@DanielRosenwasser
Muss ich das mal ausprobieren? Oder @rbuckton hat noch einen anderen existierenden Zweig dafür 🙋🏻‍♂️


Ok, ich habe es verstanden https://github.com/microsoft/TypeScript/commits/optionalChainingStage1 🤦🏻‍♂️

Ja, das ist leider ziemlich veraltet.

Mir ist gerade aufgefallen, dass dieses Thema vor 5 Jahren eröffnet wurde. :erstaunt:

@rbuckton

Ja, das ist leider ziemlich veraltet.

Könnte ich das mal anprobieren?

Entschuldigung @jhpratt @MatthiasKunnen Ich habe vergessen, dass wir auf GitHub nicht alle denselben Kontext teilen. Ich bin hier schon lange herumgesprungen und habe Zeit mit Ryan und Daniel IRL verbracht und kurz an dem jüngsten Ereignis teilgenommen, das Anlass zu meinem missverstandenen Insider-Witz gab. Entschuldigung.

Diese ganze Ausgabe zeigt jedoch eine interessante Archäologie der Designprinzipien von TypeScript. Ryan sprach es zu einer Zeit an, in der TypeScript _vielleicht_ tatsächlich eine Syntax in Betracht gezogen hat, die vor der ernsthaften Überlegung in ECMAScript lag. Es war jedoch ungefähr zu dieser Zeit, als TypeScript intern einige Lektionen über die Vorhersage der ES2015-Syntax lernte, die schwerwiegende Auswirkungen auf die Sprache hatten. Das Team beschloss, die Aufnahme erst in Betracht zu ziehen, wenn ein TC39-Vorschlag für Stufe 3 vorlag.

Während @RyanCavanaugh darauf eingehen kann und ich weiß, dass er nahe daran war, was mit dem Vorschlag passiert ist, vermute ich, dass es unwahrscheinlich gewesen wäre, dass das, was das Team 2014 implementiert hätte, zu 100 % mit dem aktuellen Vorschlag für Phase 3 kompatibel gewesen wäre . Obwohl es sicherlich ein Fest ist, sollten Sie auch dankbar sein, dass wir keinen 5-jährigen TypeScript-Code mit einem sicheren Navigationsoperator haben, der nicht vollständig mit dem Verhalten im Vorschlag vereinbar wäre.

🙏

westwing

Ist dies der Moment, um das Label Waiting for TC39 zu entfernen? 🤔

Ist dies der Moment, um das Label Waiting for TC39 zu entfernen? 🤔

Und fügen Sie ship-it hinzu

wowow

Endlich. Ich habe mich buchstäblich nach optionalen Verkettungen heute erkundigt und mich gefragt, wann es Phase 3 sein wird, und bam! Danke an alle, die daran gearbeitet haben, es durchzubringen!

Wie kann man diesen Thread stumm schalten? :)

@opnksyn Wenn Ihnen die Spam-Aufregung egal ist, gibt es eine Funktion, um benachrichtigt zu werden, wenn dieses Problem geschlossen wird. Dadurch wird verhindert, dass alle Kommentare in Benachrichtigungen wie der gerade erstellten angezeigt werden 😄

image

image

Irgendeine Emit-Lösung bereits definiert?
So etwas könnte interessant sein:

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()))));

Ich bevorzuge, was Babel tut, da es unnötige Funktionsumfänge vermeidet:

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);

Ich bevorzuge, was Babel tut, da es unnötige Funktionsumfänge vermeidet:

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);

Dem stimme ich zu, @ExE-Boss. Ich denke, dass es ideal ist, unnötige Funktionsumfänge zu vermeiden (auch wenn es den kompilierten Code etwas hässlich macht).

Wenn es um kompilierten Code geht, sollten Leistung und Einhaltung der ES-Spezifikation definitiv die Lesbarkeit übertreffen.

Gibt es einen Grund, warum der von Babel kompilierte Code sowohl null als auch mit void 0 mit dreifachem Gleichheitszeichen anstelle eines einfachen == null verglichen wird?

Gibt es einen Grund, warum der von Babel kompilierte Code sowohl null als auch mit void 0 mit dreifachem Gleichheitszeichen anstelle eines einfachen == null verglichen wird?

@proteria Ich habe mir nur kurz den optionalen Verkettungscode für __Babel__ angesehen ; Es scheint, dass, wenn Sie die Option loose übergeben und auf einen wahren Wert setzen, die strengen Gleichheitsprüfungen nicht erzeugt werden

Das liegt an document.all (oder, um es pedantisch zu sagen, dem [[IsHTMLDDA]]-internen Steckplatz ), einer Eigenart, die in der Sprache für Abwärtskompatibilität eine Sonderbehandlung erhält.

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

Im optionalen Verkettungsvorschlag

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

aber document.all == null ? void 0 : document.all.foo würde fälschlicherweise void 0 zurückgeben. Im losen Modus wird dieses Detail der Spezifikation aus Gründen der Einfachheit/Leistung/generierten Codegröße verworfen, da die meisten Leute sowieso nicht mit document.all umgehen müssen.

Der document.all -Fall könnte doch sicher etwas Besonderes sein? Es sollte nicht viel zusätzlichen Code erfordern, nur ein paar Zeilen, um das Objekt und die Eigenschaft zu überprüfen.

Abgesehen davon, dass document.all einer Variablen zugewiesen werden kann und das Nachverfolgen, wo es verwendet wird, ein Typsystem erfordert, weshalb Babel standardmäßig Folgendes ausgibt:

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

Das ist mir bewusst. Babel hat kein Typensystem, TypeScript schon. Vielleicht ist es nicht so einfach, wie ich es klingen lasse, aber ich kann mir vorstellen, dass es bereits Code für bestimmte Situationen gibt, der in der Lage ist, die Nutzung zu verfolgen.

Tatsächlich benötigen Sie kein Typsystem, um document.all -Variablen zu verfolgen, da das spezielle Verhalten tatsächlich auf HTMLAllCollection und nicht document.all liegt.

Sie sollten also nur in der Lage sein, einen instanceof HTMLAllCollection -Check zu machen, und Sie werden golden sein.

Ja, aber... warum hast du instanceof gemacht, wenn du auch nur === null || === void 0 machen kannst? Das ist sicher einfacher.

Sicher - ich habe nur darauf hingewiesen, dass Sie kein Typsystem benötigen, um document.all zu verfolgen :)

Persönlich bin ich versucht zu sagen, brechen Sie es einfach und sehen Sie, wer sich beschwert, aber es ist in der Spezifikation, also ist es am einfachsten, sich einfach daran zu halten.

@noppa Es kann zur Kompilierzeit ausgeführt werden. Wenn foo instanceof HTMLAllCollection true ist, geben Sie foo === null || foo === void 0 aus, andernfalls können wir foo == null _sicher_ ausgeben.

@G-Rath Ob es Ihnen gefällt oder nicht, veraltet bedeutet nicht, dass es nicht funktionieren sollte. TypeScript soll mit JavaScript kompatibel bleiben.

@jhpratt Aber das widerspricht derzeit den TypeScript Design Non-Goals .

Außerdem müssten Sie immer noch foo === null || foo === void 0 für alles tun, dem HTMLAllCollection zugewiesen werden könnte, z. any oder object , also denke ich nicht, dass es sich wirklich lohnt.

Ich nehme an, Sie beziehen sich auf Nicht-Ziel (5)

Fügen Sie Laufzeittypinformationen in Programmen hinzu oder verlassen Sie sich darauf, oder geben Sie basierend auf den Ergebnissen des Typsystems unterschiedlichen Code aus. Ermutigen Sie stattdessen Programmiermuster, die keine Laufzeitmetadaten erfordern.

Obwohl ich zustimme, dass dies sicherlich je nach Typ unterschiedlichen Code ausgeben würde, dient dies nur dazu, die Codegröße zu reduzieren. Wie Sie bereits betont haben, ist es jedoch nicht ganz so einfach, nach HTMLAllCollection zu suchen.

Um fair zu sein, hat TS _has_ einen potenziellen Minifier abgelehnt, der Typinformationen verwendet, und dies hängt (irgendwie) zusammen – der Hauptgrund für die Ausgabe von == null ist die Reduzierung der Codegröße basierend auf Typinformationen.

Wenn dies _nicht_ implementiert ist, wäre es großartig, wenn das lang-Team eine Option zu tsconfig hinzufügt, die der "loose"-Option von Babel ähnelt.

Nach einer schnellen Überprüfung konvertiert terser automatisch foo === null || foo === undefined in foo == null , was aufgrund dieses Randfalls nicht sicher ist.

Wenn dies nicht implementiert ist, wäre es großartig, wenn das lang-Team eine Option zu tsconfig hinzufügt, die der Option "loose" von Babel ähnelt.

Dementsprechend verwenden viele von uns TypeScript für Build-Tools und für mobile Anwendungen, von denen sich keine über Browsereinschränkungen Gedanken machen muss!

Tatsächlich verwenden wir sowohl TS als auch Babel zusammen, also sollte eine dieser Optionen vielleicht darin bestehen, den Operator an Babel/die zugrunde liegende Laufzeit zu übergeben!

@fbartho

Tatsächlich verwenden wir sowohl TS als auch Babel zusammen, also sollte eine dieser Optionen vielleicht darin bestehen, den Operator an Babel/die zugrunde liegende Laufzeit zu übergeben!

Ich verstehe diesen Kommentar nicht. Sie benötigen keine zusätzlichen Optionen, um den Operator an Babel weiterzuleiten; Wenn Sie TypeScript für Babel eingerichtet haben, haben Sie bereits noEmit: true , das bereits _alles_ an Babel durchgibt.

Der TypeScript-Implementierung von @Zarel Babel fehlen mehrere Funktionen, auf die sich unsere Codebasis bereits verlassen hat, darunter Namespaces und Const-Enumerationen. Wir verwenden TSC mit aktiviertem Emit und wenden Babel als zweite Transformation an. (Wir arbeiten daran, die Namensräume loszuwerden, aber es ist unklar, ob wir jemals in der Lage sein werden, alle nicht übereinstimmenden Funktionen loszuwerden.)

Leute, die zu diesem Thread kommen, sollten mit der früheren Ankündigung von Phase 3 beginnen und die dort beginnenden Kommentare lesen (geben Sie GitHub die Schuld dafür, dass es Tonnen von Benutzerinhalten versteckt, ohne dass es eine einfache Möglichkeit gibt, alles zu laden).

Tolles Feature - "optionale Verkettung" / "sichere Navigation". Besonders im strengen TypeScript-Modus. Schön zu hören, dass dies bald umgesetzt wird. ❤️

Das hat mich hierher gebracht und ich hoffe, dass es unterstützt wird. Nur ein Anwendungsfall:

Erwartet in TypeScript 3.7.

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

VS

Derzeit in TypeScript 3.5.

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

Funktioniert das ohne Fehler? Oder ist das immer noch ein TypeError: Cannot read property 'setAttribute' of null. ? Die ? -Operation. sollten weitere Ketten nach null / undefined abgebrochen werden.

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

Ich erwarte folgendes:
Wenn das HTML-Element nicht existiert (null). Die Konsole sollte One und Two protokollieren, und es wird nicht versucht, die Methode setAttribute aufzurufen. (Keine Fehler).
Hab ich das richtig verstanden?

@domske FYI, das ist nicht unbedingt eine TS-Funktion; es ist eine JS-Funktion.

Gemäß dem TC39-Vorschlag lautet die Syntax:

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

Die Diskussion hat begonnen, wieder im Kreis zu gehen, also sind wir wieder im gesperrten Zustand.

Ich bitte wirklich jeden, der versucht ist, einen Kommentar in einem mehr als 100 Kommentare langen GitHub-Thread zu hinterlassen, sich wirklich dazu zu verpflichten, zuerst alle vorherigen Kommentare zu lesen. Wahrscheinlich finden Sie dort Ihre Frage und die Antwort darauf!

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen