Typescript: Suggestion : "opérateur de navigation sûre", c'est-à-dire x?.y

Créé le 15 juil. 2014  ·  205Commentaires  ·  Source: microsoft/TypeScript

Statut actuel

  • La proposition TC39 est maintenant à l'étape 3 (🎉🎉🎉🎉🎉)
  • La mise en œuvre est en cours
  • Vous pouvez vous attendre à cette fonctionnalité dans TypeScript 3.7
  • Nous mettrons à jour ici quand il sera disponible dans une version nocturne
  • Retarder l'appel facultatif jusqu'à ce que sa sémantique soit clarifiée au comité

Questions ouvertes

  • Quelle casse spéciale, le cas échéant, devrait avoir document.all ?

C# et d'autres langages ont un sucre de syntaxe pour accéder aux chaînes de propriétés où null (ou dans notre cas, undefined ) peut être rencontré à n'importe quel point de la hiérarchie d'objets.

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'

Besoin d'une proposition sur ce que nous devrions exactement coder, en gardant à l'esprit les effets secondaires des accesseurs.


Édité par @DanielRosenwasser le 27 février 2018 : Cette proposition est également appelée opérateur de "propagation nulle".

Committed ES Next Suggestion Update Docs on Next Release

Commentaire le plus utile

Le chaînage facultatif est l'étape 3

Déverrouiller brièvement celui-ci uniquement à des fins de célébration

Tous les 205 commentaires

Ainsi, dans le premier exemple, nous pourrions l'émettre comme suit :

x && xy && xyz && xyzfoo

Mais alors nous devrions faire en sorte que x, y, z et foo évaluent chacun au plus une fois.

Vous ne pouvez pas non plus faire && dans de nombreux cas, car la véracité devient un peu un problème pour les primitifs.

Par exemple:

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

donne "" .

Vous devez donc faire des comparaisons explicites avec null en utilisant == pour le cas général, à moins que nous ne tirions parti du système de type (ce qui serait plutôt cool de nous voir faire).

Nous pourrions éventuellement émettre une fonction de liaison monadique (pas jolie pour la sortie JS), ou utiliser une transformation sur les opérateurs ternaires (plus proche de l'équivalent JS typique). Je suis clairement un peu biaisé envers ce dernier.

:+1:

Idéalement, ES7 (ou ES8 ou ES9 ou ...) implémenterait cela en premier car il y aurait probablement un désaccord sur la sémantique exacte quant à l'utilisation ou non de 0 / "" en tant que fausses primitives pour les besoins de n'importe quel opérateur ici.

:+1: J'aimerais que TypeScript obtienne cela en premier sans avoir à attendre ESxx.

Le fait que des opérateurs de sécurité null simples et incroyablement utiles comme "?." et "?:" NE SONT PAS dans la spécification ES6 signifie que les personnes qui élaborent la spécification ES6 devraient avoir honte. C'est une chose tellement simple et évidente que ne pas l'intégrer serait franchement insensé. Il y a une raison pour laquelle la plupart des langages modernes les prennent en charge : ils sont indispensables.

Je me rends compte que ce serait un écart par rapport à la spécification actuelle (puisque la spécification actuelle est si myope qu'elle omet cela). Mais c'est tellement ridiculement utile que je pense que ce seul écart serait justifié. La grande majorité (VAST) des développeurs TS ne serait pas affectée par des modifications mineures de l'implémentation, si ou quand cela est finalement ajouté à une spécification ES. Les énormes avantages que cela offrirait valent l'impact futur potentiel sur une infime fraction de développeurs. Et étant donné le processus de spécification ES ridiculement lent, cela n'aurait même pas d'importance du tout pendant plusieurs années (au minimum).

Je suis tout à fait d'accord avec brain428

@ brian428 le problème ici est que cet opérateur peut être implémenté dans ES7 donc si le tapuscrit va avec une spécification qui finit par différer de la version finale ES7, personne ne sera content.

le problème ici est que cet opérateur peut être implémenté dans ES7, donc si le tapuscrit va avec une spécification qui finit par différer de la version finale d'ES7, personne ne sera content.

Je pense que c'est une approche plus positive pour TypeScript d'implémenter des fonctionnalités qui peuvent _potentiellement _ (ou non) en faire une future version ES, car ce sera un banc d'essai utile pour influencer la direction ES.

Voici un exemple de discussion ES influencée par TypeScript :

L'option TypeScript... pour déclarer et initialiser via un préfixe privé sur l'un des paramètres du constructeur serait utile à de nombreux développeurs

De plus, il est certainement possible pour ES d'adopter une fonctionnalité déjà présente dans TypeScript, mais avec une sémantique différente (par exemple, autour du fonctionnement des modules).

il est certainement possible pour ES d'adopter une fonctionnalité déjà présente dans TypeScript, mais avec une sémantique différente

Je dois noter que nous considérons généralement qu'il s'agit du pire scénario. Nous voulions vraiment que les modules dans ES6 soient finalisés avant de déclarer TypeScript 1.0, mais les retards du comité l'ont empêché. C'est quelque chose à éviter, pas à répéter. Nous aimerions vraiment toucher des fonctionnalités qui ont soit ~ 0 % de chances d'être intégrées à ES7 + (par exemple, les annotations de type), soit environ 100 % de chances d'être intégrées avec une sémantique facilement définie (par exemple, où la grosse flèche était deux il y a des années). Les nouveaux opérateurs sont susceptibles de tomber dans le milieu maladroit.

Dans le pire des cas, si ES7 diffère, un indicateur de compilateur pourrait-il prendre en charge l'implémentation TS héritée, offrant ainsi une période de grâce ? Ceci, associé à une documentation claire sur la migration, devrait offrir aux développeurs une voie simple vers toute nouvelle norme.

En fin de compte, l'utilisation d'une telle fonctionnalité, bien qu'incroyablement utile, n'est pas essentielle pour les développeurs. TS devrait rendre les implications futures potentielles de son utilisation très claires dès le premier jour. Vous n'aimez pas l'idée d'un refactoring géré potentiel, ne l'utilisez pas. Peut-être un indicateur de compilateur opt-in pour appliquer ce message ?

TS ne devrait pas se déchaîner en voulant influencer ES, mais dans de petits cas isolés comme celui-ci, il serait dommage que TS se dérobe complètement.

Peut-être pourrions-nous élaborer une proposition d'homme de paille pour cela, puis avoir une implémentation de référence derrière un drapeau --harmony (ou quelque chose comme ça). De cette façon, nous pouvons piloter le développement ES7 de cette fonctionnalité.

Pour éviter les effets secondaires dus à des recherches répétées, le compilateur devra soit sortir des variables temporaires :

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

ou utilisez une membrane de mémorisation basée sur Proxy .

D'un point de vue catégoriel, il ne s'agit que de la monade peut-être appliquée à la recherche de propriété, c'est donc une fonctionnalité très naturelle pour un langage où toutes les recherches de propriété peuvent renvoyer undefined. Je serais surpris si ES7 adoptait une sémantique autre que celle décrite par le code ci-dessus.

La question du codeplex a eu un certain nombre de votes (61)

J'en ai vraiment besoin pour soulager la douleur d'utiliser atom pour atom-typescript .

Il est très idiomatique dans le code coffescript (bien que j'aimerais qu'il ne soit pas aussi populaire car le déterminisme est meilleur qu'un flou ? ). Ouvrez n'importe quel fichier coffescript, en particulier celui qui fonctionne avec le DOM directement comme space-pen (où les fonctions peuvent s'exécuter après la destruction de la vue ou avant que la vue ne soit attachée) et vous trouverez un gazillion ? d'utilisations. par exemple, ce fichier a 16 https://github.com/atom-community/autocomplete-plus/blob/f17659ad4fecbd69855dfaf00c11856572ad26e7/lib/suggestion-list-element.coffee

Encore une fois, je n'aime pas avoir besoin de cela, mais c'est l'état de JavaScript, et je préfère ? qu'un million if( && fest ) { then }

Mais j'en ai vraiment vraiment besoin pour garder mon code lisible. Il est également très courant d'en avoir besoin lorsque vous attendez qu'un XHR se termine et que angular exécute sa boucle de digestion.

Bon maintenant j'ai lu le fil et je vois pourquoi nous attendons. Je comprends _soupir_.

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

coffeescript fait quelques optimisations, par exemple stocke les résultats d'accès intermédiaires :

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

(Je pense fortement que la vérification undefined n'est pas nécessaire pour le tapuscrit : car nous devrions avoir un init var vérifié par le tapuscrit)

+1

Dans les nouvelles d'aujourd'hui, Dart obtient un support officiel pour cela : https://github.com/gbracha/nullAwareOperators/blob/master/proposal.md

Caractéristique très importante.

Peut-être une idée farfelue, mais le codegen de cette fonctionnalité pourrait être réalisé très facilement sans effets secondaires si tout le monde décidait qu'il serait acceptable de gérer la fonctionnalité avec un accès à la propriété à clé :

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

Pourrait compiler en

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

Une fonction __chain devrait être émise comme __extends . La fonction __chain pourrait simplement parcourir le tableau arguments , renvoyant null lorsque le membre suivant n'est pas instanceof Object ou ne contient pas le nom du membre. Les appels de fonction peuvent être gérés en passant un tableau en tant que paramètre (et en utilisant .apply() sous les couvertures), donc ...

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

Pourrait compiler en

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

Cela garderait également le JS généré raisonnablement idiomatique, même pour les longues chaînes.

A peaufiner évidemment... mais peut-être qu'il y a quelque chose ici ?

Si aaa?.bbb?.ccc? renvoie la valeur de a.b.c si tous les accessoires existent et qu'il s'agit d'une fonction, alors impossible

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

compiler pour

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

?

@metaweta : Votre solution ne vérifie que void 0 ... cela ne va-t-il pas à l'encontre de l'objectif de la fonctionnalité ?

Et ça:

var result = one?.two?.three;

Génère :

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

Je suis presque sûr que cela gère tous les cas. Les appels de fonction nécessiteraient probablement une vérification instanceof Function .

(Léger inconvénient ici des variables locales inattendues émises ... pourrait peut-être être enveloppé dans un IIFE)

@kevinb7 : Que se passe-t-il si ccc n'est pas une fonction ? Avec le code que vous avez décrit, __chain devrait toujours renvoyer une fonction valide, sinon une TypeError serait émise.

@Back-io Lorsqu'une propriété est absente, une recherche renvoie undefined === void 0. Votre solution échoue pour rechercher des propriétés de valeurs fausses comme une chaîne vide et zéro.

@metaweta : Non, ce n'est pas : http://jsfiddle.net/25LppbL6/

De plus, j'imagine que l'équipe TS n'est pas folle d'utiliser l'égalité lâche en raison du fait que les linters de certaines personnes mettent en garde contre cela.

@Back-io Oui, c'est le cas : http://jsfiddle.net/25LppbL6/2/

@Back-io En ce qui concerne null, je ne suis pas sûr de la sémantique prévue de a?.b. Si c'est "Si la propriété b est définie, utilisez-la", alors mon code est presque correct. La seule façon d'obtenir null est si elle est affectée à null, car les recherches de propriétés inexistantes renvoient undefined. Il ne parvient pas à détecter le cas où la propriété existe mais est définie sur undefined. Pour être tout à fait correct, il vérifierait avec Object.hasOwnProperty() au lieu de comparer à void 0 === undefined.

Si la sémantique est "si la propriété b est véridique, utilisez-la", votre code est correct et correspond dans une certaine mesure à l'idiome JS.

Umm ... à moins que quelque chose ne me manque ... les modifications que vous avez apportées au violon me donnent encore plus raison ... var result est toujours undefined dans les 3 cas. Et je ne sais pas quel cas vous essayez de mettre en avant en étendant les prototypes primitifs ...

Je suis assez certain que le comportement de la fonctionnalité serait de court-circuiter avec void 0 au lieu de générer une erreur. (J'aime votre idée ci-dessus selon laquelle il devrait toujours renvoyer void 0 dans le cas d'un membre manquant).

Quelle est la sortie prévue de ''?.toString ?

@kevinb7 : Que se passe-t-il si ccc n'est pas une fonction ? Avec le code que vous avez décrit, __chain devrait toujours renvoyer une fonction valide, sinon une TypeError serait émise.

Bon point.

@metaweta : J'imagine que la plupart des gens s'attendraient à une référence à la fonction toString , donc je vois où vous voulez en venir, cela se décompose quelque peu dans le cas où vous accédez aux membres prototypes de 0, faux, ou ''.

:+1:
Angular 2 a ajouté Elvis Operator à la syntaxe de son modèle

@metaweta :

Quelle est la sortie prévue de ''?.toString ?

Si vous vouliez dire ''?.toString() ce serait :

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

Goûter

On pourrait peut-être faire une proposition d'homme de paille pour ça

@kevinb7 ça existe déjà : http://wiki.ecmascript.org/doku.php?id=strawman :existential_operator

J'ai fait quelques tests rapides pour implémenter cela au-dessus de PropertyAccessExpression comme cas particulier, mais cela n'a pas bien fonctionné car nous avons vraiment besoin ?. soit associatif à droite (au lieu d'associatif à gauche comme . ) sinon l'émetteur devient inutilement complexe.

Il y a un commentaire de BrendenEich ici qui reflète également cela.

J'ai fait quelques tests rapides pour implémenter cela en plus de PropertyAccessExpression comme cas particulier, mais cela n'a pas bien fonctionné car nous en avons vraiment besoin. être associatif à droite (au lieu de associatif à gauche comme .) sinon l'émetteur devient inutilement complexe.

@basarat pouvez-vous s'il vous plaît élaborer sur cela? Un exemple de la différence entre l'associatif droit et l'associatif gauche ?. me serait très utile.

@zlumer

Un exemple de la différence entre associatif droit et associatif gauche ?. me serait très utile.

. est laissé associatif donc l'expression foo?.bar?.baz devient dans AST (si nous traitons ?. la même manière) :

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

L'émission JavaScript nécessaire est

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

C'est juste plus facile de faire cette émission (surtout _récursivement_) si nous avions ce qui suit dans l'AST :

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

Pensez simplement à _comment convertiriez-vous le premier AST en JavaScript_ et les complexités seraient plus claires. J'espère que ça t'aidera :rose:

@zlumer , pour ajouter à ce que @basarat a dit, je vais juste donner l'exemple 1 + 2 + 3 .

Lors de l'analyse, nous devons décider laquelle de ces opérations se produira en premier.

Si + est associatif à gauche, cela sera interprété comme ((1 + 2) + 3) .

Si + est associatif à droite, cela sera interprété comme (1 + (2 + 3)) .

Vous pourriez vous demander si cela ferait réellement une différence. En JavaScript, ce serait le cas ! Prenons l'exemple "hello" + 2 + 3 .

  • Associatif gauche : (("hello" + 2) + 3) => ("hello2" + 3) => "hello23"
  • Associatif à droite : ("hello" + (2 + 3)) => ("hello" + 5) => "hello5"

(Pour mémoire, JavaScript/TypeScript utilise l'associativité gauche pour l'opérateur + .)

@basarat , ma compréhension de ce que @BrendanEich a dit (et il peut me corriger si je me trompe - désolé pour le ping!) n'est _pas_ que ?. est associatif à droite, mais que la propriété des cas spéciaux de CoffeeScript accède à le droit du ?. d'être associatif à droite. Par exemple, il analysera

o.p?.q.r.s

comme

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

au lieu de

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

parce qu'il est plus facile à émettre.

Notre AST doit bien se prêter à une analyse sémantique saine, de sorte que notre procédure d'émission peut se permettre d'être légèrement plus complexe pour répondre à ce besoin.

@basarat @DanielRosenwasser merci pour les explications. Jusqu'à présent, je le comprends, mais je ne suis toujours pas sûr d'une chose.
L'associatif gauche ?. est assez évident et attendu :

foo?.bar?.baz

Devient (environ) :

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

Mais je ne comprends pas du tout comment fonctionnerait un ?. associatif à droite. Pouvez-vous s'il vous plaît donner un exemple?

Mais je ne comprends pas du tout comment ferait un droit-associatif ?. travailler. Pouvez-vous s'il vous plaît fournir un exemple

@zlumer Le comportement d'exécution sera laissé associatif. Je parlais justement de l'AST comme DanielRosenwasser l'a également précisé : is not that ?. is right-associative, but that CoffeeScript special cases property accesses on the right of the ?. to be right-associative .

Notre AST doit bien se prêter à une analyse sémantique saine, de sorte que notre procédure d'émission peut se permettre d'être légèrement plus complexe pour répondre à ce besoin.

@DanielRosenwasser merci pour les commentaires :rose:

@basarat merci, d'un coup tout est devenu clair :smiley:

Similaire au commentaire de février de @basarat , je... _soupir_...

Cependant, si vous y réfléchissez, 99% des cas d'utilisation de ceci consisteront à vérifier par rapport à un pointeur nul vers un objet. Franchement, qui fait x?.b?.c quand x est un number ? Il n'y a tout simplement pas beaucoup de cas d'utilisation réels pour les chaînes _longues_ lorsque nous ne parlons _pas_ d'un objet (à l'exception peut-être de string ). Pour les chaînes courtes, je pense que nous pouvons vivre avec x && x.b ou x === 0 ? null : x.b .

Alors, pouvons-nous, en quelque sorte, dire que ?. ne fonctionne que sur les types d'objets ? Tout autre type génère une erreur de syntaxe. Et interdire les appels de fonction dans la chaîne.

Ensuite, le tout se transcrit en a && a.b && a.b.c .

@schungx Et si un membre de la chaîne est de type "tout" ? Interdire complètement ? Ou simplement laisser passer et espérer le meilleur ?

Eh bien, ma suggestion? Interdire complètement. Inélégant comme l'enfer, je sais... :-)

Mais mon raisonnement :

  1. Ceci est un raccourci, donc si quelqu'un utilise any , utilisez simplement la longue main.
  2. Si quelqu'un utilise TypeScript, il l'utilise très probablement pour le support de frappe, alors j'espère qu'il n'aura pas beaucoup any autour de lui !
  3. any doit vraiment être manipulé avec précaution. Autoriser l'utilisation de ces raccourcis avec un type flexible comme any demande vraiment que des bogues se produisent. À mon avis, any devrait être aussi limité que possible. C'est un peu comme les (void *) de C -- le fait que l'on vous remette une arme nucléaire ne signifie pas que vous devez la déclencher simplement parce que vous le pouvez !

Ce serait un opérateur incroyable !! Surtout pour 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

Cependant j'en propose une plus claire - pour ne pas confondre ? du un ? instructions b : c avec des instructions 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'];

Pour la notation entre crochets, je recommande deux points au lieu d'un seul car il est cohérent avec les autres lorsque des crochets ne sont pas utilisés. Par conséquent, seul le nom de la propriété est statique ou dynamique via des crochets.

Deux points signifient que si son traitement est nul ou indéfini, arrêtez le traitement et supposez que le résultat de l'expression est nul ou indéfini. (car d serait nul ou indéfini).

Deux points le rendent plus clair, plus visible et plus spatial pour que vous compreniez ce qui se passe.

Ce n'est pas non plus jouer avec les chiffres - comme ce n'est pas le cas, par exemple

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

A propos des numéros deux options : Votre appel lequel peut être adopté, mais je recommande le premier pour la compatibilité avec les règles existantes !

  1. Devrait échouer comme il le fait maintenant ( 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. Devrait fonctionner car il comprend qu'il ne s'agit pas d'un numéro appelant une propriété à partir de 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

Avec des noms dynamiques :

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

Que pensez-vous les gens?

La syntaxe PS foo?.bar et foo?['bar'] fonctionnerait aussi.

Cependant, l'utilisation à la fois de l'opérateur ? : actuel et de l'opérateur ?. peut être très déroutante sur la même ligne.

par exemple en utilisant ?. et ?['prop']

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

par opposition aux doubles points .. et ..['prop']

var a = { x: { y: 1 } };
var b = condition ? a..x..y : a..y..z;
var c = condition ? a..['x']..['y'] : a..['y']..['z'];
Laquelle vous semble la plus claire ?

Très intéressant. :+1:

À mon humble avis, deux points seront plus déroutants. Il existe des langages où deux points représentent une plage (par exemple 1..4 ) et TypeScript peut ajouter cette fonctionnalité à l'avenir.

Un point d'interrogation a également le sens sémantique d'incertitude ou de conditionnel et deux points n'ont pas le même sens.

@schungx Assez juste, mais cela aiderait pour les possibilités étranges comme celle-ci : a?['b'] ou ce a?() .

+1 ?

a?['b'] et a?() se comportent bien dans coffeescript, et ils me paraissent bien.

Mais encore une fois, je pourrais juste être aveugle au coffeescript.

+1 Ruby vient d'implémenter l'opérateur existentiel https://twitter.com/mikepack_/status/657229703443451904. Typescript en a également besoin, quelle que soit la syntaxe spécifique.

Ce serait rendre le code plus propre 👍

+1 Besoin de ça !

S'il vous plaît, implémentez?. opérateur, comme le fait C#

+1 ça faisait longtemps que ça me manquait

+1
si moche à écrire : uneVariable && uneVariable.unMembre
quand vous pourriez écrire : someVariable?.someMember

+1, ce serait génial.... (fonctionnalité la plus recherchée pour moi)

+1, c'est une bonne idée !
Seulement, si l'objet est compliqué, l'expression sera pleine de ?. après chaque propriété (var result=myValue?.a?.b?.c?.d?.e;) quand j'ai besoin de recevoir une valeur de la dernière (var result=?myValue.abcde;).

+1 - C'est sans doute l'une des plus grandes fonctionnalités de CoffeeScript et c'est de loin la fonctionnalité TypeScript la plus souhaitée par mon équipe après avoir converti une grande partie de notre code de CS en TS.

+1 cependant, c'est trop complexe:

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

J'aime ça:

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

Le type x?.y?.z est toujours le type du champ z . Bien sûr, le type doit être nullable et la valeur réelle peut être null. S'il n'est pas nul, il doit être du type du champ z .

+1 Cela irait bien avec la vision de Typescript de faciliter le développement de projets JS complexes à grande échelle.

Des mises à jour à ce sujet ? S'agit-il d'un cas où la communauté vote pour cette fonctionnalité pour qu'elle soit prise en compte ? Ou cela a-t-il été envisagé, mais il y a des défis d'ingénierie ?

Aucune mise à jour jusqu'à présent car l'introduction d'une nouvelle syntaxe au niveau de l'expression est dangereuse sans une sorte de proposition du comité ECMAScript.

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

Voici une discussion plus actuelle sur les opérateurs existentiels (beaucoup de réflexions, mais ne ressemble pas à beaucoup d'action):

où dois-je écrire "+1" pour aider à l'amener à ES ?

@msklvsk ESDiscuter

Fermant ceci pour l'instant. Puisqu'il n'y a rien de spécifique à TypeScript qui nécessiterait cela au niveau de l'expression, ce genre de changement important d'opérateur devrait se produire au comité de spécification ES plutôt qu'ici.

Le déclencheur général pour réévaluer cela serait une proposition ES concrète atteignant l'étape suivante, ou un consensus général du comité ES selon lequel cette fonctionnalité ne se produirait pas avant longtemps (afin que nous puissions définir notre propre sémantique et être raisonnablement sûrs qu'ils "gagneraient").

la vie craint

Suppression autonome :+1:s. Veuillez utiliser la fonctionnalité de réactions GitHub ou envoyer des fleurs et des bonbons à votre représentant TC39 le plus proche.

Une fois que je m'y suis habitué dans coffeescript et Swift, il n'y a pas de retour en arrière. TS est mort pour moi tel qu'il est actuellement.

@algesten Je peux être d'accord sur swift si l'on considère le langage lui-même, pas sûr du support à long terme coffescript (j'utilise CoffeScript dans des projets de production). Nous pouvons convenir d'être sûrs des tendances de l'analyse linguistique en juin 2016 comme celle -ci où nous pouvons clairement voir ce qui se passe pour coffescript récemment, tandis que TypeScript a connu la croissance la plus rapide au cours des dernières années :

TypeScript : en dehors de Go ou de Swift, le langage qui connaît la croissance la plus rapide ces dernières années est TypeScript. Le sur-ensemble JavaScript soutenu par Microsoft et la fondation Angular 2 ont réalisé des gains significatifs pour le deuxième trimestre consécutif, passant du n ° 31 au n ° 26. Il s'agissait du plus grand changement dans toutes les langues du Top 30 et du deuxième saut le plus important dans l'ensemble (Standard ML, 7 places). Au n ° 26, en fait, TypeScript est maintenant à égalité avec Erlang, une place derrière Powershell et quatre derrière CoffeeScript, qui est juste en dehors du Top 20. La question à laquelle le langage est confronté n'est pas de savoir s'il peut se développer, mais s'il a l'élan pour percer le Top 20 dans les deux à trois prochains trimestres, dépassant les goûts de CoffeeScript et Lua dans le processus.

Jusqu'en 2014, les tendances coffescript étaient plus que positives comme vous pouvez le voir ici , c'est à ce moment que le déclin a commencé.

Avec la nouvelle vérification strict null (undefined) de Typescript 2.0, c'est un must, car sinon vous ne pouvez pas utiliser le chaînage de fonctions !

Cela devrait être dans la prochaine version d'ECMAScript. Considérant que cela serait encore plus utile dans le JavaScript vanille que TypeScript et considérant que l'implémentation serait naturellement une vérification pour undefined ou null par opposition à une vérification de la vérité, il devrait être trivial pour TC39 d'ajouter.

L'implémentation simple et qui serait idiomatique en JavaScript, consisterait simplement à court-circuiter lors de la rencontre de null ou undefined, et de renvoyer undefined.

@bterlson est-ce que cela a du sens? Quelles sont les chances qu'une telle proposition soit acceptée ?

L'un des grands avantages du tapuscrit est que "l'avenir vous est donné aujourd'hui". C'est l'une des fonctionnalités qui m'a surpris et qui ne sont pas déjà là.

J'espère qu'il sera ajouté bientôt car le chaînage de fonctions est un idiome populaire et la vérification stricte de null ne fonctionnera plus à moins que le ?. l'opérateur est ajouté.

TS 2 merveilleuse vérification nulle en a fait un incontournable!

En lisant ce fil, je suis un peu surpris de voir que cela n'attire pas plus l'attention des responsables.

Dans un monde idéal, TypeScript devrait ouvrir la voie à ES et non l'inverse. Sérieusement, où en serait TypeScript maintenant si l'équipe TS aurait toujours attendu qu'ESx propose et finalise une fonctionnalité ou une syntaxe ?

Cette syntaxe est vraiment un "must have", comme d'autres l'ont souligné. Il a même reçu de bonnes propositions dans ce fil jusqu'à présent. Je pense que la mise en œuvre doit correspondre à ces attentes.

  • En général, une expression a?.b devrait être valide au moment de la compilation si et seulement si a.b est valide.
  • Il ne doit évaluer chaque expression de la chaîne qu'une seule fois.
  • Il doit s'agir d'un court-circuit.
  • Si l'exécution atteint une expression intermédiaire avec la null ou undefined , cette valeur doit être la valeur de retour.

Selon vous, quelles sont les parties qui peuvent conduire à des désaccords lorsque ES le précisera ?

Pour a?.b je ne vois aucun conflit avec la syntaxe existante (et future ?). Si l'analyseur trouve le jeton ?. , il peut le traiter comme un "opérateur de navigation sûr" (avec des attentes telles que décrites par @cervengoc).

Les conflits de syntaxe surviennent uniquement lorsque vous autorisez a?(b) et a?[b] , car ceux-ci pourraient également être interprétés comme le début d'une expression d'opérateur ternaire ?: . Mais pour commencer, je pense que ceux-ci pourraient être mis de côté et ne supporter que la syntaxe a?.b ferait déjà plaisir à beaucoup de développeurs !

Dans un monde idéal, TypeScript devrait ouvrir la voie à ES et non l'inverse.

En termes de syntaxe au niveau de l'expression, nous ne sommes absolument pas d'accord. Il y a un comité qui dirige une norme pour une raison - pas pour que des actions ponctuelles d'un joueur puissent décider unilatéralement de l'avenir de JavaScript.

Cette syntaxe est vraiment un "must have", comme d'autres l'ont souligné.

Si c'est un must pour TypeScript, c'est aussi un must pour JavaScript ! Encore une fois, faites part de vos préoccupations au comité ECMAScript .

Selon vous, quelles sont les parties qui peuvent conduire à des désaccords lorsque ES le précisera ?

Au minimum, je pense qu'il y aura un désaccord quant à savoir si la syntaxe court-circuite à null ou undefined lors de la rencontre de ces valeurs, ou toujours court-circuite à undefined . Il va également y avoir des controverses sur la prise en charge ou non d'une certaine forme de syntaxe entre crochets. Il y a aussi la question de savoir quel est le comportement de a?.b.c . Il y a aussi la question de ?. vs .? vs a.b? . Il y a la question de savoir quel est l'effet de ceci sur l'opérateur delete .

Le fil ES DISCuss à ce sujet compte plus de 100 commentaires. L'ambiguïté ne manque pas ! Il est facile de regarder un exemple isolément et de penser qu'il ne peut pas y avoir des tonnes de cas particuliers. Il y a. C'est probablement pourquoi personne n'a encore défendu cela au TC39 et _aussi_ pourquoi nous ne nous précipitons pas pour ajouter une fonctionnalité qui a beaucoup d'ambiguïté sur la façon dont elle devrait se comporter.

Je m'excuse, je n'ai pas lu le fil mentionné, je vais certainement y jeter un œil pour en savoir plus.

Nous voyons cela un peu différemment. À propos du comité, à mon avis honnête, c'est l'une des principales raisons pour lesquelles JavaScript ne sera jamais _bon_. Juste pour un exemple, bon nombre des logiciels les plus réussis que j'ai vus (comme Total Commander ou IrfanView) réussissent parce qu'ils sont maintenus et conçus par UNE personne, et non par un *comité". Bien sûr, ce n'est pas complètement Mais je suis presque sûr que si, par exemple, vous seul aviez conçu l'ES6 complet, alors le monde serait un meilleur endroit maintenant.

De plus, les ambiguïtés que vous avez mentionnées sont à 99% _théoriques_ et en quelque sorte non pertinentes du côté du développeur. Qui se soucierait de ce qu'il renvoie, null ou undefined ? Choisissez-en un et nous l'utiliserons comme ça.

Dans l'ensemble, vous et ce comité êtes d'un côté différent de la plupart d'entre nous, et les choses de ce côté-là sont généralement plus complexes qu'elles ne le sont réellement. Et cela peut conduire à une certaine contre-productivité, c'est le moins qu'on puisse dire. Ne le prenez pas personnellement, mais selon mon expérience en général, certaines personnes feraient mieux de sortir plus souvent de la salle de conférence et de jeter un œil à du code.

Bien sûr, ne vous offensez pas, ne prenez rien personnellement, j'ai un immense respect pour vous et toute l'équipe TS, car vous avez révolutionné le développement côté client de nombreux développeurs, y compris moi-même, et merci pour tout votre travail. Nous sommes juste un peu déçus par celui-ci, je suppose.

Une dernière pensée. J'ai parcouru le fil ES mentionné, et une chose est tout à fait sûre : ils le compliquent trop. Ils veulent concevoir quelque chose qui soit bon pour chaque scénario.

Personnellement, je serais entièrement satisfait et heureux avec un opérateur d'accès conditionnel aux membres . Vous n'avez pas besoin d'invocation conditionnelle, de signature d'index conditionnel, vous n'avez pas besoin de prendre en charge tous les scénarios fantaisistes qui sont du code JS valide. C'est tout. Mais au lieu de cela, ils resteront probablement assis là et discuteront de la façon de tout faire en même temps, ce qui est un excellent plan, mais nous n'aurons rien à la fin de la journée.

Dans l'ensemble, vous et ce comité êtes d'un côté différent de la plupart d'entre nous, et les choses de ce côté-là sont généralement plus complexes qu'elles ne le sont réellement.

Je ne pense pas que vous reflétiez avec précision le véritable statut de Ryan ou de TC39. Ryan et l'équipe TypeScript ont défini des objectifs de conception très clairs pour TypeScript. L'un des objectifs originaux et toujours très actuels est que TypeScript est un sur-ensemble de JavaScript. Pas la langue que les gens aimeraient que ce soit (par exemple Dart, Haxe). En ce qui concerne la syntaxe, l'équipe TypeScript a appris à ses dépens le coût de sa pré-invention (par exemple, les modules). Nous nous dirigeons aussi tête baissée vers un défi avec les membres privés des classes, où la syntaxe ES proposée est totalement incompatible avec la syntaxe utilisée par TypeScript. Pourquoi? Parce que ce qui peut sembler simple à première vue est impossible à réaliser compte tenu des défis d'exécution d'un langage.

TC39 a "sauvé" JavaScript à mon avis. ES4 a été abandonné, non pas parce qu'il manquait de bonnes idées innovantes, mais parce qu'il casserait Internet. TC39 s'est mis en forme, ils ont partagé et ont été totalement ouverts dans leurs discussions et la façon dont ils prennent des décisions et nous ont livré ES2015, qui ressemble beaucoup à ES4, mais n'a pas cassé Internet. Il est étonnant que nous ayons essentiellement des temps d'exécution JavaScript qui exécutent parfaitement du code d'il y a 10 ans, mais prennent en charge de nombreuses améliorations significatives du langage. ES2016 était l'accalmie avant la tempête. ES2017 a une quantité "raisonnable" de fonctionnalités et de changements et un processus de gouvernance clair qui va dans la bonne direction.

Donc, être du "côté différent" des choses a clairement fonctionné, à mon avis. Ce qui bat l'opportunité des fonctionnalités "indispensables".

@kitsonk Je ne voulais pas dire "côté différent" négativement, et surtout je ne voulais pas dégrader le travail ce qui a été mis dans TypeScript ou ES6. De plus, la meilleure chose dans TypeScript IMO est qu'il avait vraiment et a un objectif de conception clair, et il est bien protégé contre les ravages comme beaucoup d'autres choses open source.

Je voulais juste dire que cette fonctionnalité même est un exemple clair de l'endroit où un groupe de génies finira par trop réfléchir et trop compliquer les choses, au lieu d'aller simplement de la manière la plus simple, et accepter certaines limitations comme ne pas prendre en charge les invocations ou les signatures d'index, etc. Quelqu'un dans ce forum a même suggéré d'utiliser cette syntaxe dans les devoirs, ce qui est un peu fou. Je pense toujours que ce phénomène est contre-productif en ce sens.

Je comprends que de votre côté c'est une douleur que par exemple les membres privés soient devenus incompatibles avec le concept final de l'ES6. Mais d'un autre côté, nous l'avions. Bien avant l'ES6. Et c'est le point principal de notre côté. En gros, nous ne nous soucions pas de savoir comment vous parvenez à émettre le code approprié pour cela, nous l'utilisons simplement avec plaisir. Idem avec les modules, et tout. Nous (ou du moins je) n'ai pas vu ces douleurs dont vous parlez, nous avons toujours été satisfaits des membres privés ou des modules.

Cette fonctionnalité particulière est dans CoffeScript comme je l'ai lu à ce sujet. Pourquoi nous, simples développeurs devons-nous toujours faire des compromis lors du choix d'une plateforme/librairie/plugin, etc. ? Je veux dire toujours . C'est un peu ennuyeux. Nous avons ici un langage formidable, qui a un grand potentiel, qui laisse complètement tous les autres participants derrière (y compris ES !), et qui a révolutionné avec succès une grande partie du développement côté client, et en ce qui concerne cette fonctionnalité "simple" ( Je veux dire au moins la partie accès aux membres), nous entendons dire qu'elle ne sera pas mise en œuvre tant que ES ne s'y sera pas engagé.

Je voulais informer rapidement les gens que cette fonctionnalité est passée de l'étape 0 à l'étape 1 lors de la réunion TC39 d'aujourd'hui.

Commit pertinent : https://github.com/tc39/proposals/commit/cb447642290a55398d483f5b55fb7f973273c75d
Ordre du jour de la réunion : https://github.com/tc39/agendas/blob/master/2017/01.md

Wow! c'est énorme!

Quelques "surprises" que je vois ici (ne disant pas que je ne suis pas d'accord, juste des choses que nous aurions probablement faites différemment si nous l'avions fait plus tôt):

  • null n'est pas produit à partir d'une expression a?.b : lorsque a est null , cela produit undefined la place
  • ~Propagation en points chaînés : a?.b.c.d ne sera pas lancé si les propriétés b et c sont undefined ~ Ryan ne peut pas lire
  • ~Propagation en présence de parenthèses : même (a?.b).c ne sera pas lancé si b n'est pas défini~ Ryan ne sait pas lire
  • ~La propagation se produit même sur les appels de méthode : a?.b.c().d renverra undefined si l'invocation c renvoie null ~ Ryan ne sait pas lire
  • L'opérateur delete est pris en charge
  • La syntaxe des parenthèses a?.[x] est prise en charge
  • La syntaxe d'appel de fonction func?.(...args) est prise en charge, même pour les appels sans méthode (!)

Je m'attends à voir des changements dans ces domaines d'ici l'étape 2.

Je pense que coffeescript a bien compris.

a?.bc est lancé si b n'est pas défini.

a?() et a?[0] sont tous les deux bons.

  • Propagation en points chaînés : a?.bcd ne lancera pas si les propriétés b et c ne sont pas définies
  • Propagation en présence de parenthèses : pair (a?.b).c ne lancera pas si b est indéfini
  • La propagation se produit même sur les appels de méthode : a?.bc().d renverra undefined si l'invocation c renvoie null

Ces points ne me semblent pas exacts. De la proposition :

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, j'ai totalement mal lu. Tu as raison. Mise à jour

@algesten de la proposition originale :

a?.()

b?.[0]

sucré. l'opérateur peut en quelque sorte être comme ?. alors.

Il y a une conversation supplémentaire en cours ici : https://github.com/estree/estree/issues/146

Une citation qui pourrait bien s'appliquer : « Rendre les choses simples faciles et les choses difficiles possibles ». Ainsi peut-être, prenez bien en charge les cas les plus courants, tout en ignorant (au moins initialement) les cas compliqués/rares, alors qu'ils sont toujours autorisés à être "faits manuellement" avec une syntaxe plus longue (existante).

Juste mes deux cents

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

pour:

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

@cedvdb sémantique totalement différente - les exceptions lancées dans les getters ne doivent pas provoquer de fusion

@RyanCavanaugh ouais .. Je n'y ai pas réfléchi.

Est-ce sur le radar pour la mise en œuvre maintenant, ou l'équipe TS attendra-t-elle que la proposition ES aille plus loin ?

C'est sur notre courte liste; nous avons encore quelques questions/préoccupations, mais vous devriez voir du mouvement à ce sujet dans le mois à venir.

Je ne sais pas d'où vient le commentaire de @mhegazy - le nombre de questions ouvertes sur la proposition TC39 est trop important pour que nous puissions faire un travail significatif ici. Plus précisément, les questions sur la manière dont null et undefined interagissent et sur la syntaxe réellement prise en charge doivent être traitées en premier. L'étape 2 est un strict minimum absolu et nous préférerions l'étape 3 compte tenu de l'impact sur le comportement d'exécution.

est-ce que ce code fonctionne simplement?

a == undefined ? expression : undefined

expression signifie ax, a[x], a(x), delete pourrait également être généré ici

alors a?.b?.[c]?.(d) générera

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

semble passer par toute la règle de RyanCavanaugh


si déteste l'opérateur == , il pourrait aussi être a === undefined || a === null

@zh99998 vous _devez_ détester == parce que '' et 0 sont également assimilés. On prétend presque que le comportement d'exécution devrait être une sorte de contrôle sur (typeof value === 'object' || typeof value === 'function' || typeof value === 'symbol') && value !== null , ce qui devient maintenant assez complexe.

Comme @RyanCavanaugh l' a dit, il est peu probable qu'il progresse tant que la proposition du TC39 n'atteindra pas au moins l'étape 2 ou 3.

Je vois que == n'est égal qu'à null et undefined comme
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness

et test réussi dans la console chrome :

'' == undefined
false
0 == undefined
false

@kitsonk undefined ne contraint qu'à null et vice versa. Aucune autre valeur ne contraint à undefined ou à null.

Vous semblez confondre avec de fausses valeurs. 0 et "" sont en effet faux, mais ne seront jamais contraints à null ni à undefined.

== implique la coercition. null == 0 est faux car rien sauf undefined ne peut forcer à null. Il en va de même pour undefined == 0 .

Un autre exemple pourrait être

    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

Vous obtenez l'image.

Je vois beaucoup de tentatives d'utilisation d'opérateurs ternaires, mais toute implémentation faisant référence à la même propriété plusieurs fois peut entraîner des effets secondaires inattendus.

Heureusement, JavaScript a des IIFE, vous pouvez donc stocker le résultat d'un accesseur dans un paramètre de fonction, vous y référer autant que vous le souhaitez et ne jamais l'évaluer plus d'une fois. Dans mon exemple ci-dessous, je crée un lambda coalesce qui peut être appelé plusieurs fois à la place d'une expression contenant des opérateurs ?. .

Une chose dont les implémenteurs de langage devraient se préoccuper est les appels de tableau et de fonction au milieu d'une expression. Je pense que le compilateur pourrait gérer la détection de ces situations et simplement ajouter ces expressions à la fin de l'appel coalesce.

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]

Notez qu'il n'y a pas besoin d'un nom global réel "coalesce". Ce code peut être directement intégré dans n'importe quelle expression. Cela pourrait cependant réduire le ballonnement en lui donnant un nom.

Je ne suis pas trop concerné par la syntaxe utilisée pour l'opérateur ou si les implémenteurs du langage veulent attendre un standard. Je pensais juste montrer une autre approche.

Cela soulève également la nécessité d'un opérateur ?? . En C#, cela remplace toute expression null par ce qui se trouve à droite.

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

Malheureusement, la véracité capture trop de cas extrêmes ( 0 , false , etc.). En travaillant avec un opérateur null coalesce ( ?. ), vous voudriez quelque chose de spécifique à null -ness.

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

@jehugaleahsa , dans votre exemple avec coalesce, il devrait y avoir un moyen d'empêcher les appels de fonction et l'accès des membres de se produire si la vérification avant retournait null. Dans l'exemple x?.f(), f ne doit pas être appelé si x est nul.

@bschlenk Je ne pense pas être d'accord. Je pense que cela devrait échouer avec un message comme null is not a function , mais ce n'est pas à moi, je suppose.

La récente vague de commentaires détaillant les moyens possibles de mettre en œuvre l'opérateur est un peu bizarre.
La mise en œuvre est probablement un problème résolu.

Si vous êtes intéressé, il y a la bibliothèque idx , qui ressemble beaucoup au comportement de l'opérateur ?. , bien qu'elle ignore également de nombreux détails de l'opérateur prévu. Quoi qu'il en soit, leurs spécifications pour la sortie de compilation pourraient intéresser tous ceux qui s'interrogent sur la manière dont ces éléments pourraient être implémentés.

TS pourrait sortir quelque chose comme ça ou il pourrait sortir quelque chose de complètement différent, mais je ne pense pas que ce soit ce que nous attendons ici. Il a été dit à plusieurs reprises ici que TS n'obtiendrait pas l'opérateur tant que la proposition ES n'évoluerait pas dans un sens ou dans l'autre.

C'est la sémantique qui a encore quelques inconnues, listées ici et ici .

Soyez assuré que nous mettrons cela en œuvre correctement et que nous n'avons pas besoin de 100 autres commentaires ici pour comprendre ce que font || et ? ... : ... . Comme @noppa l'a noté, nous attendons juste la finalisation de la spécification ES.

https://github.com/babel/babel/pull/5813 (accompagnant babylon PR ) vient d'être fusionné avec Babel's preset-stage-1 . La spécification est toujours au stade 1, bien sûr, mais cela aidera à la faire avancer.

Peut-être que je me trompe, mais je n'ai pas vu de lien évident vers la proposition tc39 dans ce fil, alors la voici pour les futurs lecteurs : https://github.com/tc39/proposal-optional-chaining

Pour info le chaînage optionnel sera au TC39 la semaine prochaine https://github.com/tc39/agendas/blob/master/2017/07.md

@jehugaleahsa Je pense que vous avez raison et je présenterai ?? au TC39 la semaine prochaine. Vous pouvez suivre la proposition ici : https://github.com/gisenberg/proposal-nullary-coalescing

Je vois que le chaînage optionnel était couvert au TC39... Quel a été le verdict ?
J'espère que c'était suffisant pour faire avancer cela dans Typescript 😉

@markwhitfeld D'après le résumé des notes :
Opérateurs de chaînage optionnels : reste à l'étape 1, reviendra plus tard avec des définitions plus claires pour diverses options et des réponses aux commentaires

Notes complètes ici : https://github.com/rwaldron/tc39-notes/blob/master/es8/2017-07/jul-27.md#13iia -optional-chaining-operator

Il y a encore des questions ouvertes sur la façon dont l'opérateur doit se comporter, il semble donc qu'il ne soit pas encore dans un état où il peut être ajouté à TypeScript.

D'après ces notes, il semble que le comité n'ait aucune idée du fonctionnement des options présentées, j'aurais pensé qu'ils auraient pris connaissance des propositions dont ils prévoyaient de discuter, avant d'en discuter. Je suppose que cela va prendre un peu plus de temps jusqu'à ce que je puisse activer les contrôles nuls stricts.

J'espère vraiment qu'ils opteront pour l'option 2/4 (qui est de toute façon l'état actuel de la proposition).

15 juillet 2014 - 4 septembre 2017, rien encore

@frankfvb vous n'avez clairement pas lu le problème.

Il y a eu beaucoup de discussions qui ont conduit l'équipe principale à croire qu'il serait imprudent de mettre en œuvre à ce stade jusqu'à ce que de nouveaux progrès soient réalisés sur la proposition ECMAScript, ce qui aurait un impact direct sur la fonctionnalité de cette fonctionnalité dans TypeScript.

Depuis la dernière réunion du comité des normes ECMAScript, la proposition reste à l'étape 1 car elle pose des questions très fondamentales sur la manière dont elle serait mise en œuvre. Bien qu'il ne s'agisse pas d'une règle absolue, TypeScript n'implémentera que les propositions de l'étape 3. Il implémente parfois les propositions de l'étape 2 s'ils pensent que cela est d'une importance critique et que l'utilisation potentielle dans TypeScript entraîne l'évolution de la norme.

Je ne sais pas comment des gens plus clairs peuvent être à ce sujet.

Comme je l'ai dit plus tôt , cela fait partie de notre liste restreinte. nous attendons que TC39 parvienne à une sorte de consensus sur la sémantique de l'opérateur. nous détesterions le publier et casser ensuite les utilisateurs.

Ce n'est pas le fil pour ressasser la discussion TC39

Si vous voulez peser dans la proposition, allez la commenter à l'endroit approprié . J'ai aussi des opinions, mais les déposer dans ce fil ne va rien faire.

J'ai créé quelque chose de simple qui répond à mes besoins actuels. Cela ne fonctionnera que sur une chaîne où chaque lien est un nom de propriété, donc l'accès à un élément dans un tableau (par exemple) n'est pas pris en charge.

Implémentation d'un opérateur Elvis très simple dans TypeScript

De plus, si vous avez lodash/underscore, vous pouvez déjà utiliser _.get(Book, 'author.name.firstName') qui fera ce que cela veut

Edit : Apparemment, c'est un mauvais conseil en raison de problèmes de type avec la méthode _.get() . Voir commentaire ci-dessous

@tolgaek , _.get a de mauvaises frappes, même avec ces meilleures frappes ( pas encore fusionnées , à cause des auteurs) le dactylographie ne peut certainement déduire le type de résultat que si la profondeur de l'objet est de 1, dans tous les autres cas c'est any et doit être vérifié au moment de l'exécution

D'un autre côté, avec l'opérateur elvis, le script peut être en mesure de déduire le type de résultat dans des objets de n'importe quelle profondeur, c'est pourquoi j'attends avec impatience l'opérateur elvis

oh je vois, je ne savais pas qu'il y avait un problème de frappe. Merci @BjornMelgaard

@mhegazy cette fonctionnalité ne peut-elle pas être implémentée en premier et marquée comme fonctionnalité expérimentale ? Je pense que les gens ne devraient pas avoir de problème si les spécifications sont modifiées dans la fonctionnalité expérimentale.

Elvis n'est pas amusé à attendre aussi longtemps.

Il a atterri à Babel7. Tapuscrit, nous sommes lents.. Quelqu'un s'il vous plaît, faites que cela se produise.
:)

@gs-akhan le plugin Babel implémente une ancienne version de la proposition d'il y a quelques mois. Il y a eu des changements dans la proposition depuis lors (y compris un changement significatif dans la façon dont l'opérateur est analysé), et il y aura probablement plus de changements avant que la fonctionnalité n'atteigne l'étape 2 (sans parler de l'étape 3), donc tout code écrit avec le babel actuel plugin pourrait se casser lorsque la fonctionnalité réelle est publiée. Babel implémente intentionnellement les fonctionnalités proposées avant qu'elles ne soient stables afin que les auteurs de spécifications et les autres parties intéressées puissent essayer la fonctionnalité telle que proposée. Ce n'est pas parce que Babel a implémenté une fonctionnalité qu'elle peut être implémentée d'une manière qui ne nécessitera pas de modifications majeures à l'avenir.

@alangpierce Cela a du sens. Merci

Je comprends que c'est un opérateur vraiment, vraiment sympa, mais le fait qu'il soit disponible avant que ses règles ne soient aplanies est une arme de pied et nous n'allons pas le faire. Le comportement d'exécution de l'opérateur est toujours en évolution ; si vous écrivez du code aujourd'hui, il pourrait cesser de fonctionner demain d'une manière qui n'est pas immédiatement apparente - peut-être des plantages rares, peut-être une corruption de données, qui sait ? Un peu de patience maintenant vous évitera beaucoup de douleur dans quelques mois.

Je commence à penser que ce ticket devrait être verrouillé (et non fermé) jusqu'à ce que la spécification soit prête.

Quand la spécification sera-t-elle prête ?

@oliverjanik Le projet de spécification actuel peut être trouvé ici . Il y a un point à l'ordre du jour pour faire avancer la proposition à l'étape 2 lors de la prochaine réunion du TC39 (26/09-28/09). Je présenterai ces diapositives à ce moment-là. Pour les personnes qui souhaitent examiner plus tôt et fournir des commentaires, veuillez signaler les problèmes sur le dépôt de la proposition .

Merci beaucoup @gisenberg d'avoir défendu ce problème pour nous ! Je pensais créer un diaporama récapitulatif pour aider à clarifier les options autour de l'opérateur qui pourraient être utilisées lors de la réunion TC39 afin d'éviter toute confusion, mais vous l'avez déjà fait. Super travail!
Peut-être qu'une autre chose qui pourrait être bénéfique pour la conversation TC39 (et le jeu de diapositives) est de regarder la sémantique et la syntaxe de l'opérateur dans d'autres langues. Bien que d'autres langages ne doivent pas nécessairement dicter comment cela devrait fonctionner en Javascript, il serait utile de garder l'opérateur similaire à celui des autres langages afin d'éviter toute confusion.
Bon courage pour la semaine prochaine !!!

Désolé d'être un peu hors sujet une fois de plus, mais j'ai pensé que certaines personnes ici pourraient trouver intéressant que dans Flow, il soit maintenant possible d'ajouter des définitions de type quelque peu fonctionnelles pour des fonctions getter sûres comme _.get .

Exemple : flowtype.org/try

Ce n'est pas le plus beau morceau de code de tous les temps et il ne fait pas correctement la distinction entre null et undefined, mais à part cela, il semble fonctionner assez bien.

AFAIK, la seule chose qui manque à TS pour qu'il fasse la même chose est quelque chose comme ça $NonMaybeType .
Non pas que cela supprimerait le besoin de cet opérateur, bien sûr, j'ai juste pensé que c'était cool.

Cela n'a pas atteint l'étape 2 lors de la dernière réunion du TC39 en raison de préoccupations concernant la cohérence syntaxique concernant l'accès entre parenthèses, points et appels et le comportement sémantique (prévisibilité autour des effets secondaires des expressions à droite d'un undefined / null -opérande évalué) ainsi que des questions ouvertes sur le type d'expressions autorisées à ne pas être utilisées (par exemple, x.?b() lorsque x.b est un number )

(votez 🎉 sur ce commentaire pour jeter des fruits pourris)

Merci de nous en informer. Quelle déception. Peut-être que la portée doit être réduite pour que ce soit plus simple mais toujours utile?

Peut-être que la portée doit être réduite pour que ce soit plus simple mais toujours utile?

C'est le défi auquel TC39 est confronté, qui, bien que nul, je dois admettre que je suis heureux que les gens traversent cela. Il est vraiment difficile pour eux d'introduire une syntaxe de niveau assez complexe et en fait, dans ce cas, le faible typage du langage provoque en fait une quantité importante de cas extrêmes qui doivent être traités, ou vous obtenez du code qui va 💥 qui n'est pas ce n'est bon pour personne. Je ne pense pas que si vous introduisez un opérateur comme celui-ci, vous puissiez réellement réduire sa portée. Il serait plus facile pour les implémenteurs de couvrir 90 % des cas, mais je ne pense pas que ¯\_(ツ)_/¯ soit un code valide pour les 10 % restants.

Les gars, plus de 3 ans plus tard, je dirais qu'il est temps de dire "va te faire foutre" au comité et de le faire à notre manière, quel que soit l'idiome de TypeScript. Cette fonctionnalité ne peut pas fonctionner correctement sans typage statique de toute façon.

Faites une implémentation TypeScript avec une syntaxe qui est explicitement incompatible avec la proposition TC39. Une fois qu'ES obtient un opérateur de navigation sécurisée, TypeScript aura deux options : une avec une sémantique de merde compatible avec ES et une qui est liée au système de type. Cela signifie que vous ne pouvez pas utiliser l'opérateur TS safe-nav avec n'importe quel "type", et c'est très bien.

@notsnotso Typescript n'est pas censé casser JS, c'est à cela que sert Coffeescript.

Peut-être qu'une bonne solution consiste à :

  • mise en oeuvre très simple ? opérateur pour les développeurs impatients, en tant que fonctionnalité expérimentale (comme le décorateur), avec avertissement - il cassera votre code à l'avenir
  • attendez encore 3 ans lorsque le standart sera écrit, implémentez-le en tant que fonctionnalité non expérimentale. Ecrire tutoriel, ce qui pourrait être cassé. Même, avec le typage statique, il est possible d'écrire des avertissements lorsque les gens compileront du code avec une nouvelle implémentation d'opérateur.
    "faites-le à notre manière, tout ce qui est idiomatique pour TypeScript" n'est pas un cas, car dans 3 ans, les gens seront confrontés à un problème, que ts elvis ne fonctionne pas de la même manière que dans js.

Je ne suis pas surpris que cela ne se soit pas passé, pour être honnête. Dans mon original
post, j'ai souligné l'ambiguïté concernant l'indexation, les appels de fonction, etc.
Honnêtement, plus je pense à ?. , plus j'ai l'impression que ce n'est pas le cas
appartiennent à JavaScript, puisqu'il a undefined .

Je préférerais de loin un utilitaire plus généraliste qui résoudrait ce problème
et plus. Une pensée que j'avais était quelque chose comme un try/catch en ligne
expression ( let x = try a.b.c else 0 ) en conjonction avec un opérateur qui
vérifié pour "nully" (par exemple, x ?? 1) plutôt que "falsey" (par exemple, x || 1).
Donc, vous les combineriez comme ceci : try a.b.c ?? 0 else 0 . C'est verbeux, oui,
mais il dit essentiellement : Essayez d'évaluer abc et si le résultat est null ou
undefined , renvoie 0. Si a ou b vaut undefined et qu'une exception est levée,
attrapez-le et renvoyez un 0.

Une alternative serait de rendre la clause else facultative, par défaut à
undefined . Ensuite, vous pouvez écrire l'expression sous la forme : let x= (try a.b.c) ?? 0 . C'est sacrément compact, évite l'ambiguïté et offre un plus
solution polyvalente qui peut résoudre d'autres problèmes.

Je ne dis pas que nous devrions pousser pour cela à la place ; tout ce que je dis est là
sont des alternatives à ?. et nous devrions vraiment explorer nos options jusqu'à ce que nous
trouvez-en un qui correspond bien au langage JavaScript.

Le jeudi 5 octobre 2017 à 7h51, Dmitry Radkovskiy [email protected]
a écrit:

@notsnotso Typescript n'est pas censé casser JS, c'est ce que
Coffeescript est fait pour.


Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/Microsoft/TypeScript/issues/16#issuecomment-334441781 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/ABTgPilbZfuKc2egdBrYfdTHHeDl3F6Sks5spMLLgaJpZM4CNapf
.

@zlumer belle blague. Cela dit, une fonctionnalité spécifique à TS ne casserait pas Javascript.

@jehugaleahsa J'aime votre proposition, et on la trouve dans d'autres langues. Je pense que cela fonctionnerait très bien pour TS.

Je dirai que je ne comprends pas vraiment la forte nécessité d'attendre qu'ECMAScript accepte l'opérateur. TypeScript a ajouté des classes, des modules, des lambdas, bien avant qu'ils ne se retrouvent dans ECMAScript. En fait, l'un des objectifs déclarés de TypeScript était/est de piloter des fonctionnalités JS expérimentales. TypeScript fournissant sa propre implémentation aiderait sans aucun doute à éclairer ces discussions au sein du comité.

Vous avez déjà été prêts à apporter des changements de rupture lorsque le comité a finalement pris une direction différente, je ne vois pas vraiment pourquoi cette fonctionnalité est si différente.

async/wait a également été introduit dans TypeScript à un stade précoce.

Cela dit, une fonctionnalité spécifique à TS ne casserait pas Javascript.

Il n'y aura pas quelque chose comme "fonctionnalité spécifique à TS", veuillez vérifier les objectifs de conception de TypeScript pour plus d'informations.

TypeScript arrive avant que ES n'emprunte un chemin lumineux, il pourrait y en avoir déjà,ils sont juste conservés pour la compatibilité.

TypeScript a ajouté des classes, des modules, des lambdas, bien avant qu'ils ne se retrouvent dans ECMAScript.

Et les modules en particulier sont une énorme débâcle qui ne cause toujours pas de confusion. C'est un exemple que l'équipe TypeScript a utilisé à plusieurs reprises comme exemple de _mistake_ et de sauter le pistolet trop tôt. Nous avons également des champs privés qui se profilent maintenant, ce qui, encore une fois, je suis reconnaissant pour private au cours des 5 dernières années, mais cela ne causera pas de confusion.

Encore une fois, les décorateurs étaient disponibles sous le drapeau, mais maintenant que les décorateurs arrivent à l'étape 3, cela nécessitera une réimplémentation et une rupture de code pour TypeScript. C'est pourquoi ces choses _ne peuvent pas_ être considérées comme probables.

async/wait a également été introduit dans TypeScript à un stade précoce.

Une fois que la proposition ECMAScript a atteint l'étape 3.

Personne ne se comporte mal, mais si cette conversation ne peut aller nulle part, mais en cercles (et s'il y avait un drapeau ? Oui, nous sommes conscients des drapeaux) ou hors sujet (et si TS cesse d'être JS ? Non, cinq ans plus tard, nous ne changeons pas notre esprit là-dessus), nous n'avons pas besoin de l'avoir. Nous disons depuis environ 3 ans maintenant que nous mettrons cela en œuvre exactement lorsque le comité ES verrouillera sa sémantique.

Encore une fois, le dépôt de proposition est https://github.com/tc39/proposal-optional-chaining et vous pouvez y suivre sa progression. Nous travaillerons hors ligne pour essayer d'améliorer les chances de la proposition lors de la prochaine réunion du TC39, car nous voulons vraiment que cela se concrétise également.

Mise à jour : Nous avons atteint l'étape 2 cet après-midi au TC39 !!!

Le chaînage facultatif est l'étape 3

Déverrouiller brièvement celui-ci uniquement à des fins de célébration

Hourra !

Ne spammez pas...

Vous pouvez envoyer un emoji exprimant vos sentiments

Ne spammez pas...

Vous pouvez envoyer un emoji exprimant vos sentiments

De plus, c'est amusant de voir le nombre d'emoji grimper comme ça. Je n'ai jamais vu un commentaire sur un problème gagner autant de popularité aussi vite !

J'ai enregistré une petite vidéo des mises à jour en temps réel https://youtu.be/JLBrgPjeGhc

Est-ce que quelqu'un peut me désabonner de cette chose ?

@DanielRosenwasser Au cas où vous ne plaisanteriez pas, ou pour toute autre personne qui souhaite se désinscrire et ne sait pas comment, vous recherchez ce bouton dans la barre latérale de droite :

image

Sans oublier qu'il y a un lien dans l'e-mail :

image

C'était une blague, je travaille sur la proposition.

@RyanCavanaugh après avoir déverrouillé ce problème :
martian

Vraiment hâte de le voir enfin débarquer ! 🎈 🎉

Je ne peux pas attendre la solution rapide VSCode correspondante 😆

image

Je vais à @ @RyanCavanaugh car il est probablement désabonné de ce fil et je veux être grossier ! (et @DanielRosenwasser pour faire bonne mesure)

@kitsonk Ne sois pas un âne. Les gens sont libres de se désabonner et de ne pas être harcelés.

@kitsonk , Pourquoi RyanCavanaugh ou DanielRosenwasser seraient-ils désabonnés de ce fil ? Ryan a déverrouillé ce problème et Daniel a répondu trois commentaires au-dessus de vous.

Même s'ils étaient désabonnés, il n'est pas nécessaire de causer plus de fatigue de notification en les spammant.

Apparemment, GitHub est un endroit terrible pour l'humour sarcastique, bon sang...

Un grand merci à nos champions du TC39 pour avoir compris les détails désagréables de cette nouvelle fonctionnalité de langage !

thanks

Je pense que @kitsonk plaisantait, tout comme moi. Bien que nous soyons un peu idiots face à l'excitation, ceci est un doux rappel de garder les choses civiles conformément au CoC.

@DanielRosenwasser
Pourrais-je avoir à essayer cela? Ou @rbuckton a encore une autre branche existante pour ça 🙋🏻‍♂️


Ok, j'ai compris https://github.com/microsoft/TypeScript/commits/optionalChainingStage1 🤦🏻‍♂️

Oui, c'est assez obsolète, malheureusement.

Je viens de réaliser que ce sujet a été ouvert il y a 5 ans. :étonné:

@rbuckton

Oui, c'est assez obsolète, malheureusement.

Pourrais-je essayer ça ?

Désolé @jhpratt @MatthiasKunnen J'ai oublié que nous ne partageons pas tous le même contexte sur GitHub. Je rebondis ici depuis longtemps et j'ai passé du temps avec Ryan et Daniel IRL et j'ai brièvement participé à l'événement récent qui a donné lieu à ma blague incomprise. Excuses.

Tout ce numéro montre cependant une archéologie intéressante des principes de conception de TypeScript. Ryan l'a soulevé à un moment où TypeScript _pourrait_ avoir en fait envisagé une syntaxe antérieure à une considération sérieuse dans ECMAScript. C'est à cette époque que TypeScript apprenait en interne quelques leçons de prédiction de la syntaxe ES2015 qui avaient de sérieux impacts sur le langage. L'équipe a décidé de ne pas envisager l'inclusion jusqu'à ce qu'il y ait une proposition TC39 Stage 3.

Bien que @RyanCavanaugh puisse y répondre, et je sais qu'il a été proche de ce qui s'est passé avec la proposition, je soupçonne qu'il aurait été peu probable que ce que l'équipe aurait mis en œuvre en 2014 aurait été compatible à 100% avec la proposition actuelle de l'étape 3 . Donc, bien que ce soit certainement une célébration, soyez également reconnaissant que nous n'ayons pas 5 ans de code TypeScript avec un opérateur de navigation sûr qui ne serait pas entièrement cohérent avec le comportement de la proposition.

🙏

westwing

Est-ce le moment de retirer le label Waiting for TC39 ? 🤔

Est-ce le moment de retirer le label Waiting for TC39 ? 🤔

Et ajoutez ship-it

wowowow

Finalement. Littéralement, je posais des questions sur le chaînage facultatif, je me demandais quand ce serait l'étape 3, et bam ! Merci à tous ceux qui ont travaillé pour le faire passer!

Comment mettre ce fil en sourdine ? :)

@opnksyn Si vous ne vous souciez pas de l'excitation du spam, il existe une fonctionnalité pour être averti lorsque ce problème est fermé. Cela empêchera tous les commentaires d'apparaître dans les notifications comme celle que vous venez de faire 😄

image

image

Une solution d'émission déjà définie ?
Quelque chose comme ça pourrait être intéressant :

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

Je préfère ce que fait Babel car cela évite de créer des portées de fonction inutiles :

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

Je préfère ce que fait Babel car cela évite de créer des portées de fonction inutiles :

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

Je suis d'accord, @ExE-Boss. Je pense qu'éviter de créer des portées de fonctions inutiles est idéal (même si cela rend le code compilé un peu moche)

Les performances et le respect de la spécification ES devraient définitivement l'emporter sur la lisibilité lorsqu'il s'agit de code compilé.

Y a-t-il une raison pour laquelle le code compilé par Babel se compare à la fois à null et void 0 avec un triple égal au lieu d'un simple == null ?

Y a-t-il une raison pour laquelle le code compilé par Babel se compare à la fois à null et void 0 avec un triple égal au lieu d'un simple == null ?

@proteria Je viens de jeter un coup d'œil au code de chaînage optionnel pour __Babel__ ; il semble que si vous passez l'option loose et que vous la réglez sur une valeur de vérité, cela ne produit pas les contrôles d'égalité stricts

C'est à cause de document.all (ou pour être pédant, le slot interne [[IsHTMLDDA]] ), une bizarrerie qui reçoit un traitement spécial dans le langage pour une compatibilité descendante.

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

Dans la proposition de chaînage optionnel

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

mais document.all == null ? void 0 : document.all.foo renverrait incorrectement void 0 . En mode lâche, ce détail de la spécification est ignoré pour la simplicité/les performances/la taille du code généré, car la plupart des gens n'ont de toute façon pas à gérer document.all .

Le cas document.all pourrait sûrement être spécial ? Cela ne devrait pas nécessiter beaucoup de code supplémentaire, juste quelques lignes pour vérifier l'objet et la propriété.

Sauf que document.all peut être affecté à une variable, et le suivi de son utilisation nécessite un système de type, c'est pourquoi Babel affiche par défaut :

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

Je suis au courant de ça. Babel n'a pas de système de typage, contrairement à TypeScript. Ce n'est peut-être pas aussi simple que je l'ai dit, mais j'imagine qu'il existe déjà du code pour certaines situations qui est capable de suivre l'utilisation.

En fait, vous n'avez pas besoin d'un système de type pour suivre les variables document.all , car le comportement spécial est en fait sur HTMLAllCollection , et non document.all .

Donc, vous devriez juste pouvoir faire un instanceof HTMLAllCollection , et vous serez en or.

Ouais mais... pourquoi as-tu fait instanceof alors que tu peux juste faire === null || === void 0 ? C'est sûrement plus simple.

Bien sûr - je faisais juste remarquer que vous n'avez pas besoin d'un système de type pour suivre document.all :)

Personnellement, je suis tenté de dire qu'il suffit de le casser et de voir qui se plaint, mais c'est dans les spécifications, il est donc plus facile de s'en tenir à cela.

@noppa Il peut être effectué au moment de la compilation. Si foo instanceof HTMLAllCollection est true , émettez foo === null || foo === void 0 , sinon nous pouvons _en toute sécurité_ émettre foo == null .

@G-Rath Qu'on le veuille ou non, obsolète ne signifie pas que cela ne devrait pas fonctionner. TypeScript doit rester compatible avec JavaScript.

@jhpratt Mais cela va actuellement à l'encontre des non-objectifs de conception de TypeScript .

De plus, vous devrez toujours faire foo === null || foo === void 0 pour tout ce à quoi HTMLAllCollection pourrait être attribué, par exemple. any ou object , donc je ne pense pas que ça en vaille vraiment la peine.

Je suppose que vous faites référence au non-objectif (5)

Ajouter ou s'appuyer sur les informations de type d'exécution dans les programmes, ou émettre un code différent en fonction des résultats du système de type. Au lieu de cela, encouragez les modèles de programmation qui ne nécessitent pas de métadonnées d'exécution.

Bien que je convienne que cela émettrait certainement un code différent en fonction du type, c'est uniquement pour réduire la taille du code. Bien que, comme vous l'avez souligné, ce n'est pas aussi simple que de vérifier HTMLAllCollection .

Pour être juste, TS _a_ rejeté un minificateur potentiel qui utilise des informations de type, et ceci est (en quelque sorte) lié — la principale raison d'émettre == null est de réduire la taille du code en fonction des informations de type.

Si cela _n'est pas_ implémenté, ce serait formidable si l'équipe lang ajoutait une option à tsconfig similaire à l'option "loose" de Babel.

Après une vérification rapide, terser convertit automatiquement foo === null || foo === undefined en foo == null , ce qui n'est pas sûr en raison de ce cas limite.

Si cela n'est pas implémenté, ce serait formidable si l'équipe lang ajoutait une option à tsconfig similaire à l'option "loose" de Babel.

De même, beaucoup d'entre nous utilisent TypeScript pour les outils de construction et pour les applications mobiles, dont aucun n'a à se soucier des contraintes du navigateur !

En fait, nous utilisons à la fois TS et Babel ensemble, donc peut-être que l'une de ces options devrait être de passer l'opérateur à Babel/runtime sous-jacent !

@fbartho

En fait, nous utilisons à la fois TS et Babel ensemble, donc peut-être que l'une de ces options devrait être de passer l'opérateur à Babel/runtime sous-jacent !

Je ne comprends pas ce commentaire. Vous n'avez pas besoin d'options supplémentaires pour passer l'opérateur à Babel ; si vous avez configuré TypeScript pour Babel, vous avez déjà noEmit: true qui transmet déjà _tout_ à Babel.

L'implémentation TypeScript de @ Zarel Babel manque plusieurs fonctionnalités sur lesquelles notre base de code s'appuyait déjà, y compris les espaces de noms et les énumérations constantes. Nous utilisons TSC avec l'émission activée et appliquons Babel comme deuxième transformation. (Nous travaillons sur la suppression des espaces de noms, mais il n'est pas clair si nous pourrons un jour nous débarrasser de toutes les fonctionnalités incompatibles)

Les personnes venant sur ce fil de discussion devraient commencer à l' annonce de l'étape 3 précédente et lire les commentaires à partir de là (blâmez GitHub pour avoir caché des tonnes de contenu utilisateur sans moyen simple de tout charger)

Grande fonctionnalité - "chaînage en option" / "navigation sûre". Surtout en mode strict TypeScript. Génial d'entendre que cela sera bientôt mis en œuvre. ❤️

Cela m'a amené ici et j'espère qu'il sera soutenu. Juste un cas d'utilisation :

Attendu dans TypeScript 3.7.

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

VS

Actuellement dans TypeScript 3.5.

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

Cela fonctionnera-t-il sans aucune erreur ? Ou est-ce toujours un TypeError: Cannot read property 'setAttribute' of null. ? L' ? . devrait être annuler d'autres chaînes après null / undefined.

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

J'attends la suite :
Si l'élément html n'existe pas (null). La console doit enregistrer One et Two , et la méthode setAttribute n'est pas tentée d'être invoquée. (Aucune erreur).
Est-ce que j'ai bien compris ?

@domske FYI, ce n'est pas strictement une fonctionnalité TS ; c'est une fonctionnalité JS.

Selon la proposition du TC39, la syntaxe sera :

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

La discussion a recommencé à tourner en rond, nous sommes donc revenus à l'état verrouillé.

Je supplie vraiment toute personne tentée de laisser un commentaire dans un fil GitHub de plus de 100 commentaires de s'engager vraiment à lire tous les commentaires précédents en premier. Votre question et la réponse y seront probablement trouvées !

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

remojansen picture remojansen  ·  3Commentaires

siddjain picture siddjain  ·  3Commentaires

dlaberge picture dlaberge  ·  3Commentaires

weswigham picture weswigham  ·  3Commentaires

blendsdk picture blendsdk  ·  3Commentaires