Typescript: Sugestão: "operador de navegação segura", ou seja, x?.y

Criado em 15 jul. 2014  ¬∑  205Coment√°rios  ¬∑  Fonte: microsoft/TypeScript

Status atual

  • A proposta TC39 est√° agora na fase 3 (ūüéČūüéČūüéČūüéČūüéČ)
  • A implementa√ß√£o est√° em andamento
  • Voc√™ pode esperar esse recurso no TypeScript 3.7
  • Atualizaremos aqui quando estiver dispon√≠vel em uma vers√£o noturna
  • Suspens√£o da Chamada Opcional at√© que sua sem√Ęntica seja esclarecida no comit√™

Perguntas abertas

  • Que inv√≥lucro especial, se houver, deve document.all obter?

C# e outras linguagens t√™m a√ß√ļcar de sintaxe para acessar cadeias de propriedades onde null (ou em nosso caso, undefined ) pode ser encontrado em qualquer ponto da hierarquia de objetos.

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'

Precisa de proposta sobre o que exatamente devemos codificar, tendo em mente os efeitos colaterais dos acessadores.


Editado por @DanielRosenwasser 27 de fevereiro de 2018: Esta proposta também é chamada de operador "propagação nula".

Committed ES Next Suggestion Update Docs on Next Release

Coment√°rios muito √ļteis

O encadeamento opcional é o Estágio 3

Desbloqueando brevemente este apenas para fins comemorativos

Todos 205 coment√°rios

Ent√£o, no primeiro exemplo, podemos emitir da seguinte forma:

x && xy && xyz && xyzfoo

Mas então teríamos que de alguma forma fazer com que x, y, z e foo fossem avaliados no máximo uma vez.

Você também não pode fazer && em muitos casos porque a veracidade se torna um problema para os primitivos.

Por exemplo:

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

d√° "" .

Portanto, voc√™ precisa fazer algumas compara√ß√Ķes expl√≠citas com null usando == para o caso geral, a menos que aproveitemos o sistema de tipos (o que seria muito legal nos ver fazer).

Poder√≠amos emitir uma fun√ß√£o monadic-bind (n√£o muito bonita para a sa√≠da JS) ou usar alguma transforma√ß√£o em operadores tern√°rios (mais pr√≥ximo do equivalente t√≠pico de JS). Eu sou claramente um pouco tendencioso para o √ļltimo.

:+1:

Idealmente, ter√≠amos ES7 (ou ES8 ou ES9 ou ...) implementando isso primeiro, pois provavelmente haveria algum desacordo sobre a sem√Ęntica exata sobre usar ou n√£o 0 / "" como primitivos falsos para os prop√≥sitos de qualquer operador aqui.

:+1: Eu gostaria de ver o TypeScript receber isso primeiro sem ter que esperar pelo ESxx.

O fato de que operadores de seguran√ßa nula simples e insanamente √ļteis como "?." e "?:" N√ÉO EST√ÉO na especifica√ß√£o do ES6 significa que as pessoas que montam a especifica√ß√£o do ES6 deveriam estar com a cabe√ßa baixa de vergonha. Isso √© uma coisa t√£o simples e √≥bvia que n√£o incorpor√°-la seria francamente insano. H√° uma raz√£o pela qual a maioria das linguagens modernas suporta isso: elas s√£o indispens√°veis.

Eu percebo que isso seria um desvio da especifica√ß√£o atual (j√° que a especifica√ß√£o atual √© t√£o m√≠ope a ponto de omitir isso). Mas √© t√£o ridiculamente √ļtil que acho que esse √ļnico desvio seria justificado. A grande maioria (VAST) dos desenvolvedores de TS n√£o seria afetada por pequenas altera√ß√Ķes na implementa√ß√£o, se ou quando isso finalmente for adicionado a uma especifica√ß√£o de ES. Os enormes benef√≠cios que isso ofereceria valem o potencial impacto futuro para uma pequena fra√ß√£o de desenvolvedores. E dado o processo de especifica√ß√£o ES ridiculamente lento, isso nem importaria por v√°rios anos (no m√≠nimo).

concordo totalmente com o brain428

@ brian428 o problema aqui é que esse operador pode ser implementado no ES7, portanto, se o texto datilografado for com uma especificação que acabe sendo diferente da final do ES7, ninguém ficará feliz.

o problema aqui é que esse operador pode ser implementado no ES7, então se o typescript for com uma especificação que acaba sendo diferente da final do ES7, ninguém ficará feliz.

Acho que √© uma abordagem mais positiva para o TypeScript implementar recursos que podem _potencialmente _ (ou n√£o) chegar a uma vers√£o futura do ES, porque ser√° um teste √ļtil para influenciar a dire√ß√£o do ES.

Aqui est√° um exemplo de discuss√£o ES sendo influenciada pelo TypeScript :

A op√ß√£o TypeScript... para declarar e inicializar por meio de um prefixo privado em um dos par√Ęmetros do construtor seria √ļtil para muitos desenvolvedores

Al√©m disso, certamente √© poss√≠vel que o ES adote um recurso que j√° est√° presente no TypeScript, mas com sem√Ęntica diferente (por exemplo, sobre como os m√≥dulos funcionam).

certamente √© poss√≠vel que o ES adote um recurso que j√° est√° presente no TypeScript, mas com sem√Ęntica diferente

Devo observar que consideramos amplamente este o pior cen√°rio poss√≠vel. N√≥s realmente quer√≠amos que os m√≥dulos no ES6 fossem finalizados antes de declararmos o TypeScript 1.0, mas os atrasos no cronograma do comit√™ impediram isso. Isso √© algo a ser evitado, n√£o repetido. Gostar√≠amos muito de encontrar recursos que tenham ~0% de chance de chegar ao ES7+ (por exemplo, anota√ß√Ķes de tipo), ou ~100% de chance de chegar com sem√Ęntica facilmente definida (por exemplo, onde a seta gorda era dois anos atr√°s). Novos operadores provavelmente cair√£o no meio estranho.

Na pior das hipóteses, se o ES7 for diferente, um sinalizador do compilador poderia suportar a implementação do TS legado, oferecendo assim um período de carência? Isso, juntamente com uma documentação de migração clara, deve oferecer aos desenvolvedores uma rota direta para qualquer novo padrão.

Em √ļltima an√°lise, o uso de qualquer recurso ‚Äď embora incrivelmente √ļtil ‚Äď n√£o √© essencial para os desenvolvedores. O TS deve deixar as poss√≠veis implica√ß√Ķes futuras de seu uso bem claras desde o primeiro dia. N√£o goste da ideia de uma refatora√ß√£o gerenciada em potencial, n√£o a use. Talvez um sinalizador de compilador opt-in para impor esta mensagem?

O TS n√£o deveria enlouquecer querendo influenciar o ES, mas em pequenos casos isolados como esse, seria uma pena se o TS se esquivasse completamente.

Talvez pudéssemos montar uma proposta de espantalho para isso e então ter uma implementação de referência por trás de um sinalizador --harmony (ou algo assim). Dessa forma, podemos impulsionar o desenvolvimento ES7 desse recurso.

Para evitar efeitos colaterais devido a pesquisas repetidas, o compilador ter√° que gerar vari√°veis ‚Äč‚Äčtempor√°rias:

($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 use uma membrana de memorização baseada em Proxy .

De um ponto de vista categ√≥rico, essa √© apenas a m√īnada talvez aplicada √† pesquisa de propriedades, portanto, √© um recurso muito natural para uma linguagem em que todas as pesquisas de propriedades podem retornar indefinidas. Eu ficaria surpreso se o ES7 adotasse qualquer sem√Ęntica diferente da descrita pelo c√≥digo acima.

A quest√£o do codeplex teve um grande n√ļmero de votos (61)

Eu realmente preciso disso para aliviar a dor de usar atom para atom-typescript .

√Č muito idiom√°tico em c√≥digo coffescript (embora eu gostaria que n√£o fosse t√£o popular quanto o determinismo √© melhor do que um ? fudgy). Abra qualquer arquivo coffescript, especialmente um que funcione com o DOM diretamente como space-pen (onde as fun√ß√Ķes podem ser executadas ap√≥s a exibi√ß√£o ser destru√≠da ou antes da exibi√ß√£o ser anexada) e voc√™ encontrar√° um zilh√£o de ? usos. por exemplo, este arquivo tem 16 https://github.com/atom-community/autocomplete-plus/blob/f17659ad4fecbd69855dfaf00c11856572ad26e7/lib/suggestion-list-element.coffee

Novamente, eu não gosto que eu precise disso, mas é o estado do JavaScript, e eu prefiro ? do que um milhão de if( && fest ) { then }

Mas eu realmente preciso dele para manter meu código legível. Também é muito comum _precisar_ disso quando você está esperando que um XHR seja concluído e o angular execute seu loop de resumo.

Ok, agora eu li o tópico e vejo por que estamos esperando. Eu entendo _suspiro_.

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

coffeescript faz algumas otimiza√ß√Ķes, por exemplo , armazena resultados de acesso intermedi√°rio :

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

(Eu sinto fortemente que a verificação undefined é desnecessária para o texto datilografado: como devemos ter um var init digitado pelo texto datilografado)

+1

Nas notícias de hoje, o Dart está recebendo suporte oficial para ele: https://github.com/gbracha/nullAwareOperators/blob/master/proposal.md

Característica muito importante.

Possivelmente uma ideia inusitada, mas a geração de código para esse recurso poderia ser feita muito facilmente sem efeitos colaterais se todos decidissem que não haveria problema em lidar com o recurso com acesso à propriedade com chave:

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

Poderia compilar para

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

Uma fun√ß√£o __chain teria que ser emitida semelhante a __extends . A fun√ß√£o __chain poderia apenas iterar pelo array arguments , retornando null quando o pr√≥ximo membro n√£o for instanceof Object ou n√£o contiver o nome do membro. As chamadas de fun√ß√£o podem ser tratadas passando uma matriz como par√Ęmetro (e usando .apply() nos bastidores), ent√£o ...

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

Poderia compilar para

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

Isso também manteria o JS gerado razoavelmente idiomático, mesmo para cadeias longas.

Precisa de refinamento obviamente... mas talvez haja algo aqui?

Se aaa?.bbb?.ccc? retornar o valor de a.b.c se todas as props existirem e for uma função, então não poderia

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

compilar para

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

?

@metaweta : Sua solução está verificando apenas void 0 ... isso não anula o objetivo do recurso?

O que dizer disso:

var result = one?.two?.three;

Gera:

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

Tenho certeza que isso lida com todos os casos. Chamadas de função provavelmente precisariam de uma verificação instanceof Function .

(Pequena desvantagem aqui de vari√°veis ‚Äč‚Äčlocais inesperadas sendo emitidas ... pode ser envolvido em um IIFE talvez)

@kevinb7 : O que acontece se ccc não for uma função? Com o código que você descreveu, __chain sempre teria que retornar uma função válida, ou um TypeError seria emitido.

@Back-io Quando uma propriedade está ausente, uma pesquisa retorna undefined === void 0. Sua solução falha ao pesquisar propriedades de valores falsey como string vazia e zero.

@metaweta : N√£o, n√£o: http://jsfiddle.net/25LppbL6/

Além disso, eu imagino que a equipe TS não é louca por usar igualdade solta devido ao fato de que os linters de algumas pessoas alertam contra isso.

@Back-io Sim, tem: http://jsfiddle.net/25LppbL6/2/

@Back-io Em rela√ß√£o a null, n√£o tenho certeza de qual √© a sem√Ęntica pretendida de a?.b. Se for "Se a propriedade b estiver definida, use-a", meu c√≥digo est√° quase correto. A √ļnica maneira de obter null √© se for atribu√≠do como null, porque as pesquisas de propriedades inexistentes retornam indefinidas. Ele n√£o detecta o caso em que a propriedade existe, mas est√° definida como indefinida. Para estar completamente correto, ele verificaria com Object.hasOwnProperty() em vez de comparar com void 0 === undefined.

Se a sem√Ęntica for "se a propriedade b for verdadeira, ent√£o use-a", seu c√≥digo est√° bem e, at√© certo ponto, corresponde ao idioma JS.

Umm ... a menos que eu esteja perdendo alguma coisa ... as altera√ß√Ķes que voc√™ fez no violino apenas provam que estou certo ... var result ainda √© undefined em todos os 3 casos. E n√£o tenho certeza de qual caso voc√™ est√° tentando apresentar estendendo os prot√≥tipos primitivos ...

Estou bastante certo de que o comportamento do recurso seria um curto-circuito com void 0 em vez de gerar um erro. (Gosto da sua ideia acima de que deve sempre retornar void 0 no caso de um membro ausente).

Qual é a saída pretendida de ''?.toString ?

@kevinb7 : O que acontece se ccc não for uma função? Com o código que você descreveu, __chain sempre teria que retornar uma função válida, ou um TypeError seria emitido.

Bom ponto.

@metaweta : Eu imagino que a maioria das pessoas esperaria uma referência à função toString , então eu vejo onde seu ponto, ele quebra um pouco no caso em que você está acessando os membros protótipo de 0, false, ou ''.

:+1:
Angular 2 adicionou Elvis Operator à sua sintaxe de modelo

@metaweta :

Qual é a saída pretendida de ''?.toString?

Se você quis dizer ''?.toString() seria:

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

Amostra

Talvez pudéssemos montar uma proposta espantalho para isso

@kevinb7 j√° existe: http://wiki.ecmascript.org/doku.php?id=strawman:existential_operator

Fiz alguns testes rápidos para implementar isso em cima de PropertyAccessExpression como seu caso especial, mas não funcionou bem, pois realmente precisamos que ?. seja associativo à direita (em vez de associativo à esquerda como . ), caso contrário, o emissor se torna desnecessariamente complexo.

Há um comentário de BrendenEich aqui que reflete isso também.

Eu fiz alguns testes rápidos para implementar isso em cima de PropertyAccessExpression como seu caso especial, mas não funcionou bem como realmente precisamos?. ser associativo à direita (em vez de associativo à esquerda como .), caso contrário, o emissor se torna desnecessariamente complexo.

@basarat voc√™ pode por favor elaborar sobre isso? Um exemplo da diferen√ßa entre associativo direito e associativo esquerdo ?. seria muito √ļtil para mim.

@zlumer

Um exemplo da diferen√ßa entre associativo direito e associativo esquerdo ?. seria muito √ļtil para mim.

. é associativo à esquerda, então a expressão foo?.bar?.baz se torna em AST (se tratarmos ?. da mesma forma):

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

A emissão JavaScript necessária é

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

√Č apenas mais f√°cil fazer essa emiss√£o (especialmente _recursivamente_) se tiv√©ssemos o seguinte no AST:

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

Basta pensar em _como você converteria o primeiro AST para JavaScript_ e as complexidades seriam mais claras. Espero ter ajudado :rose:

@zlumer , para adicionar ao que @basarat disse, vou apenas colocar o exemplo 1 + 2 + 3 .

Ao analisar, temos que decidir qual dessas opera√ß√Ķes acontecer√° primeiro.

Se + for associativo à esquerda, isso será interpretado como ((1 + 2) + 3) .

Se + for associativo à direita, isso será interpretado como (1 + (2 + 3)) .

Você pode questionar se isso realmente faria a diferença. Em JavaScript seria! Considere o exemplo "hello" + 2 + 3 .

  • Associativo √† esquerda: (("hello" + 2) + 3) => ("hello2" + 3) => "hello23"
  • Associativa √† direita: ("hello" + (2 + 3)) => ("hello" + 5) => "hello5"

(Para registro, JavaScript/TypeScript usam associatividade à esquerda para o operador + .)

@basarat , meu entendimento do que @BrendanEich disse (e ele pode me corrigir se eu estiver errado - desculpe pelo ping!) é _não_ que ?. é associativo à direita, mas que a propriedade de casos especiais CoffeeScript acessa em o direito de ?. ser associativo à direita. Por exemplo, ele analisará

o.p?.q.r.s

Como

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

ao invés de

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

porque é mais fácil de emitir.

Nosso AST precisa prestar bem √† an√°lise sem√Ęntica s√£, ent√£o nosso procedimento de emiss√£o pode ser um pouco mais complexo para atender a essa necessidade.

@basarat @DanielRosenwasser obrigado pelas explica√ß√Ķes. At√© agora eu entendo, mas ainda n√£o tenho certeza sobre uma coisa.
O associativo à esquerda ?. é bastante óbvio e esperado:

foo?.bar?.baz

Torna-se (aprox.):

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

Mas eu não entendo como uma associativa direita ?. funcionaria. Por favor, você pode fornecer um exemplo?

Mas eu não entendo nada como uma associativa direita?. trabalhar. Você pode fornecer um exemplo

@zlumer O comportamento do tempo de execução será associativo à esquerda. Eu estava falando sobre o AST como DanielRosenwasser também esclareceu: is not that ?. is right-associative, but that CoffeeScript special cases property accesses on the right of the ?. to be right-associative .

Nosso AST precisa prestar bem √† an√°lise sem√Ęntica s√£, ent√£o nosso procedimento de emiss√£o pode ser um pouco mais complexo para atender a essa necessidade.

@DanielRosenwasser obrigado pelo feedback :rose:

@basarat obrigado, de repente tudo ficou claro :smiley:

Semelhante ao coment√°rio de fevereiro de @basarat , eu.... _suspiro_...

No entanto, se você pensar sobre isso, 99% dos casos de uso disso serão para verificar um ponteiro nulo para um objeto. Falando francamente, quem faz x?.b?.c quando x é um number ? Simplesmente não há muitos casos de uso na vida real para cadeias _longas_ quando _não_ estamos falando sobre um objeto (com a possível exceção de string ). Para correntes curtas, acho que podemos viver com x && x.b ou x === 0 ? null : x.b .

Então, podemos dizer que ?. só funciona em tipos de objetos? Qualquer outro tipo gera um erro de sintaxe. E não permitir chamadas de função no lado da cadeia.

Ent√£o a coisa toda transcreve para a && a.b && a.b.c .

@schungx E se um membro da cadeia for do tipo "qualquer"? Desautorizar completamente? Ou apenas deix√°-lo passar e esperar o melhor?

Bem, minha sugest√£o? Desautorize completamente. Deselegante pra caramba, eu sei... :-)

Mas meu raciocínio:

  1. Esta é uma mão curta, então se alguém estiver usando any , use apenas uma mão longa.
  2. Se alguém está usando o TypeScript, provavelmente ele está usando para o suporte de digitação, então espero que ele não tenha muitos any por aí!
  3. any realmente deve ser manuseado com cuidado. Permitir o uso de tais short-hands com um tipo flex√≠vel como any √© realmente pedir que os bugs aconte√ßam. Na minha opini√£o, any deve ser o mais limitado poss√≠vel. √Č como o (void *) do C - o fato de voc√™ receber uma arma nuclear n√£o significa que voc√™ deve ativ√°-la apenas porque pode!

Isso seria incrível operador!! Especialmente para 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

No entanto, proponho uma mais clara ‚Äď para n√£o confundir? do um? b : c instru√ß√Ķes com a?.b instru√ß√Ķes:

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

Para a nota√ß√£o de colchetes, recomendo dois pontos em vez de um √ļnico, pois √© consistente com os outros quando n√£o s√£o usados ‚Äč‚Äčcolchetes. Portanto, apenas o nome da propriedade √© est√°tico ou din√Ęmico por meio de colchetes.

Dois pontos, significa que se for nulo ou indefinido, interrompe o processamento e assume que o resultado da expressão é nulo ou indefinido. (como d seria nulo ou indefinido).

Dois pontos tornam-no mais claro, mais visível e mais espacial para que você entenda o que está acontecendo.

Isso n√£o est√° mexendo com n√ļmeros tamb√©m - como n√£o √© o mesmo caso, por exemplo

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

Sobre os n√ļmeros duas op√ß√Ķes: Sua chamada qual pode ser adotada, mas recomendo a primeira para compatibilidade com as regras existentes!

  1. Deve falhar como agora ( 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. Deve funcionar, pois entende que n√£o √© um n√ļmero ligando para uma propriedade 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

Com nomes din√Ęmicos:

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

O que você acha pessoas?

A sintaxe PS foo?.bar e foo?['bar'] também funcionaria.

No entanto, usar o operador ? : e ?. pode ser muito confuso na mesma linha.

por exemplo, usando ?. e ?['prop']

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

ao contr√°rio de pontos duplos .. e ..['prop']

var a = { x: { y: 1 } };
var b = condition ? a..x..y : a..y..z;
var c = condition ? a..['x']..['y'] : a..['y']..['z'];
Qual deles parece mais claro para você?

Muito interessante. :+1:

IMHO, dois pontos ser√£o mais confusos. Existem linguagens em que dois pontos representam um intervalo (por exemplo 1..4 ) e o TypeScript pode adicionar esse recurso no futuro.

Um ponto de interroga√ß√£o tamb√©m tem o significado sem√Ęntico de incerteza ou condicional e dois pontos n√£o transmitem o mesmo significado.

@schungx Justo, mas ajudaria nas possibilidades estranhas como esta: a?['b'] or this a?() .

+1 ?

a?['b'] e a?() se comportam bem em coffeescript, e parecem bons para mim.

Mas, novamente, eu posso ser cego para o coffeescript.

+1 Ruby acabou de implementar o operador existencial https://twitter.com/mikepack_/status/657229703443451904. O Typescript também precisa disso, independentemente da sintaxe específica.

Isso seria tornar o c√≥digo mais limpo ūüĎć

+1 Precisa disso!

Por favor, implenente?. operador, como C# faz

+1 faz tempo que sinto falta disso

+1
t√£o feio de escrever: someVariable && someVariable.someMember
quando você poderia escrever: someVariable?.someMember

+1, isso seria ótimo .... (recurso mais procurado para mim)

+1, é uma boa ideia!
S√≥ que, se o objeto for complicado, a express√£o estar√° cheia de ?. ap√≥s cada propriedade (var result=myValue?.a?.b?.c?.d?.e;) quando precisar receber um valor da √ļltima (var result=?myValue.abcde;).

+1 - Este √© sem d√ļvida um dos maiores recursos do CoffeeScript e √© de longe o recurso TypeScript mais desejado pela minha equipe depois de converter grande parte do nosso c√≥digo de CS para TS.

+1 no entanto, isso é muito complexo:

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

Eu gosto deste:

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

O tipo de x?.y?.z é sempre o tipo do campo z . Claro que o tipo deve ser anulável e o valor real pode ser nulo. Se não for nulo, deve ser do tipo do campo z .

+1 Isso combinaria bem com a vis√£o da Typescript de facilitar o desenvolvimento de projetos JS complexos de grande escala.

Alguma atualiza√ß√£o sobre isso? √Č o caso da comunidade votar neste recurso para que ele seja considerado? Ou foi considerado, mas existem alguns desafios de engenharia?

Nenhuma atualização até agora porque a introdução de uma nova sintaxe em nível de expressão é perigosa sem algum tipo de proposta do comitê ECMAScript.

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

Aqui está uma discussão mais atual sobre operadores existenciais (muitos pensamentos, mas não parece muita ação):

onde devo escrever "+1" para ajudar a trazê-lo para o ES?

@msklvsk ESDiscuss

Fechando isso por enquanto. Como n√£o h√° realmente nada espec√≠fico do TypeScript que exija isso no n√≠vel da express√£o, esse tipo de grande mudan√ßa de operador deve acontecer no comit√™ de especifica√ß√Ķes do ES e n√£o aqui.

As armadilhas gerais para reavaliar isso seriam uma proposta ES concreta chegando ao pr√≥ximo est√°gio, ou um consenso geral do comit√™ ES de que esse recurso n√£o aconteceria por um longo tempo (para que pud√©ssemos definir nossa pr√≥pria sem√Ęntica e ser razoavelmente certeza de que iriam "ganhar").

a vida é uma droga

Excluindo aut√īnomo :+1:s. Use o recurso de rea√ß√Ķes do GitHub ou envie flores e doces para o representante TC39 mais pr√≥ximo.

Uma vez que me acostumei com coffeescript e Swift, n√£o h√° como voltar atr√°s. TS est√° morto para mim como est√° atualmente.

@algesten Eu posso concordar com swift se considerarmos a linguagem em si, n√£o tenho certeza sobre o suporte coffescript longo prazo (eu uso CoffeScript em projetos de produ√ß√£o). Podemos concordar em ter certeza das tend√™ncias de an√°lise de linguagem em junho de 2016, onde podemos ver claramente o que est√° acontecendo com coffescript recentemente, enquanto TypeScript teve o crescimento mais r√°pido nos √ļltimos anos:

TypeScript: Fora do Go ou Swift, a linguagem de crescimento mais r√°pido que observamos nos √ļltimos anos √© o TypeScript. O superconjunto JavaScript apoiado pela Microsoft e a funda√ß√£o Angular 2 obtiveram ganhos significativos pelo segundo trimestre consecutivo, saltando de 31¬ļ para 26¬ļ. Essa foi a maior mudan√ßa em qualquer idioma do Top 30 e o segundo maior salto geral (Standard ML, 7 lugares). Na 26¬™ posi√ß√£o, na verdade, o TypeScript agora est√° empatado com Erlang, um lugar atr√°s do Powershell e quatro atr√°s do CoffeeScript, que est√° fora do Top 20. A quest√£o que a linguagem enfrenta n√£o √© se ela pode crescer, mas se tem o impulso para quebrar o Top 20 nos pr√≥ximos dois a tr√™s trimestres, superando nomes como CoffeeScript e Lua no processo.

Até 2014, as tendências coffescript eram mais do que positivas, como você pode ver aqui , foi quando o declínio começou.

Com a nova verifica√ß√£o nula (indefinida) estrita do typescript 2.0, √© uma obriga√ß√£o, porque, caso contr√°rio, voc√™ n√£o pode usar o encadeamento de fun√ß√Ķes!

Isso deve estar na pr√≥xima vers√£o do ECMAScript. Considerando que isso seria ainda mais √ļtil no JavaScript vanilla do que no TypeScript e considerando que a implementa√ß√£o seria naturalmente uma verifica√ß√£o de indefinido ou nulo em oposi√ß√£o a uma verifica√ß√£o de verdade, deve ser trivial para o TC39 adicionar.

A implementação simples e que seria idiomática em JavaScript, seria simplesmente fazer um curto-circuito ao encontrar null ou undefined e retornar undefined.

@bterlson isso faz sentido? Quais s√£o as chances de tal proposta ser aceita?

Um dos grandes benefícios do texto datilografado é "o futuro é dado a você hoje". Esta é uma das características que me surpreendeu que ainda não estão lá.

Espero que ele seja adicionado em breve, pois o encadeamento de fun√ß√Ķes √© um idioma popular e a verifica√ß√£o nula estrita n√£o funciona mais, a menos que o ?. operador √© adicionado.

TS 2 maravilhosa verificação nula tornou-se um bom ter que ter!

Lendo este tópico, estou meio surpreso como isso não recebe mais atenção dos mantenedores.

Em um mundo ideal, o TypeScript deveria liderar o ES e não o contrário. Sério, onde estaria o TypeScript agora se a equipe de TS sempre esperasse que o ESx propusesse e finalizasse um recurso ou uma sintaxe?

Esta sintaxe é realmente um "must have", como outros apontaram. Ele até recebeu algumas boas propostas neste segmento até agora. Acho que a implementação deve corresponder a essas expectativas.

  • Em geral, uma express√£o a?.b deve ser v√°lida em tempo de compila√ß√£o se e somente se a.b for v√°lido.
  • Ele deve avaliar cada express√£o na cadeia apenas uma vez.
  • Deve estar em curto-circuito.
  • Se a execu√ß√£o atingir uma express√£o intermedi√°ria com null ou undefined , esse valor deve ser o valor de retorno.

Quais você acha que são as partes que podem levar a divergências quando o ES especificar?

Para a?.b não vejo nenhum conflito com a sintaxe existente (e futura?). Se o analisador encontrar o token ?. , ele poderá tratá-lo como 'operador de navegação segura' (com as expectativas descritas por @cervengoc).

Conflitos de sintaxe surgem apenas ao permitir a?(b) e a?[b] , pois eles também podem ser interpretados como o início de uma expressão de operador ?: ternária. Mas, para começar, acho que isso poderia ser deixado de lado e suportar apenas a sintaxe a?.b já deixaria muitos desenvolvedores felizes!

Em um mundo ideal, o TypeScript deveria liderar o ES e n√£o o contr√°rio.

Em termos de sintaxe em n√≠vel de express√£o, discordamos absolutamente. H√° um comit√™ conduzindo um padr√£o por uma raz√£o - n√£o para que a√ß√Ķes pontuais de um jogador possam decidir unilateralmente o futuro do JavaScript.

Esta sintaxe é realmente um "must have", como outros apontaram.

Se isso √© obrigat√≥rio para o TypeScript, tamb√©m √© obrigat√≥rio para o JavaScript! Mais uma vez, leve suas preocupa√ß√Ķes ao comit√™ ECMAScript .

Quais você acha que são as partes que podem levar a divergências quando o ES especificar?

No mínimo, acho que haverá desacordo sobre se a sintaxe causa curto-circuito em null ou undefined ao encontrar esses valores, ou sempre em curto-circuito em undefined . Também haverá alguma controvérsia sobre se alguma forma de sintaxe entre colchetes é suportada ou não. Há também a questão de qual é o comportamento de a?.b.c . Há também a questão de ?. vs .? vs a.b? . Há a questão de qual é o efeito disso no operador delete .

O t√≥pico do ES Discuss sobre isso tem mais de 100 coment√°rios. N√£o h√° falta de ambiguidade! √Č f√°cil olhar para um exemplo isoladamente e pensar que n√£o pode haver toneladas de casos de canto. Tem. Provavelmente √© por isso que ningu√©m defendeu isso no TC39 ainda e _tamb√©m_ por que n√£o estamos nos apressando para adicionar um recurso que tem muita ambiguidade sobre como ele deve se comportar.

Peço desculpas, não li o tópico mencionado, com certeza vou dar uma olhada para ver mais.

Vemos isso um pouco diferente. Sobre o comit√™, na minha opini√£o honesta, essa √© uma das maiores raz√Ķes pelas quais JavaScript nunca ser√° _bom_. Apenas para um exemplo, muitos dos softwares de maior sucesso que eu j√° vi (como Total Commander ou IrfanView) s√£o bem sucedidos porque s√£o mantidos e projetados por UMA pessoa, e n√£o por um *comit√™". exemplo correto, mas tenho quase certeza, que se, por exemplo, voc√™ sozinho tivesse projetado o ES6 completo, ent√£o o mundo seria um lugar melhor agora.

Além disso, as ambiguidades que você mencionou são 99% _teóricas_ e meio irrelevantes do lado do desenvolvedor. Quem se importaria com o que retorna, null ou undefined ? Basta escolher um, e vamos usá-lo assim.

Em suma, você e esse comitê estão de um lado diferente da maioria de nós, e as coisas desse lado geralmente são mais complexas do que realmente são. E isso pode levar a alguma contraprodutividade, para dizer o mínimo. Não leve para o lado pessoal, mas de acordo com minha experiência em geral, algumas pessoas seriam melhores sair da sala de conferência com mais frequência e dar uma olhada em algum código.

Claro, sem ofensa, não leve nada para o lado pessoal, tenho um enorme respeito por você e toda a equipe TS, porque você revolucionou o desenvolvimento do lado do cliente de muitos desenvolvedores, inclusive eu, e obrigado por todo o seu trabalho. Estamos um pouco decepcionados com este específico, eu acho.

Um √ļltimo pensamento. Eu percorri o t√≥pico ES mencionado, e uma coisa √© completamente certa: eles est√£o complicando demais. Eles querem projetar algo que seja bom para todos os cen√°rios.

Eu pessoalmente ficaria completamente satisfeito e feliz com um operador de acesso condicional para membros . Não precisa de invocação condicional, assinatura de índice condicional, não precisa dar suporte a todos os cenários sofisticados que são códigos JS válidos. Isso é tudo. Mas, em vez disso, eles provavelmente continuarão sentados lá e discutirão como fazer tudo de uma vez, o que é um ótimo plano, mas não teremos nada no final do dia.

Em suma, você e esse comitê estão de um lado diferente da maioria de nós, e as coisas desse lado geralmente são mais complexas do que realmente são.

Eu não acho que você esteja refletindo o verdadeiro status de Ryan ou TC39 com precisão. Ryan e a equipe do TypeScript estabeleceram metas de design muito claras para o TypeScript. Um dos objetivos originais e ainda muito atuais é que o TypeScript seja um superconjunto de JavaScript. Não é o idioma que as pessoas gostariam que fosse (por exemplo, Dart, Haxe). Quando se trata de sintaxe, a equipe do TypeScript aprendeu da maneira mais difícil o custo de pré-inventá-lo (por exemplo, módulos). Também estamos entrando de cabeça em um desafio com membros privados de classes, onde a sintaxe ES proposta é totalmente incompatível com a sintaxe que o TypeScript usa. Por quê? Porque o que pode parecer descomplicado na superfície é impossível de alcançar devido aos desafios de tempo de execução de uma linguagem.

O TC39 "salvou" o JavaScript na minha opini√£o. O ES4 foi abandonado, n√£o por falta de ideias boas e inovadoras, mas porque quebraria a internet. O TC39 entrou em forma, compartilhou e foi totalmente aberto em suas discuss√Ķes e como toma decis√Ķes e nos entregou o ES2015, que √© muito parecido com o ES4, mas n√£o quebrou a internet. √Č incr√≠vel que tenhamos essencialmente tempos de execu√ß√£o de JavaScript que executam c√≥digo de 10 anos atr√°s muito bem, mas suportam muitas melhorias significativas na linguagem. ES2016 foi a calmaria antes da tempestade. O ES2017 tem uma quantidade "razo√°vel" de funcionalidades e mudan√ßas e um processo de governan√ßa claro que aponta na dire√ß√£o certa.

Então, estar do "lado diferente" das coisas claramente funcionou, na minha opinião. O que supera a conveniência dos recursos "obrigatórios".

@kitsonk Eu não quis dizer "lado diferente" negativamente e, especialmente, não quis degradar o trabalho que foi colocado no TypeScript ou ES6. Além do mais, a melhor coisa no TypeScript IMO é que ele realmente tinha e tem um objetivo de design claro, e está bem protegido contra se tornar um caos como muitas outras coisas de código aberto.

Eu s√≥ queria dizer que esse recurso √© um exemplo claro de onde um grupo de pessoas geniais acabar√° pensando demais e complicando demais as coisas, em vez de apenas seguir o caminho f√°cil e simples, e aceitar algumas limita√ß√Ķes, como n√£o suportar invoca√ß√Ķes ou assinaturas de √≠ndice, etc. .Algu√©m naquele f√≥rum at√© sugeriu usar essa sintaxe nas atribui√ß√Ķes, o que √© meio louco. Ainda acho que esse fen√īmeno √© contraproducente nesse sentido.

Eu entendo que do seu lado é uma dor que, por exemplo, membros privados tenham se tornado incompatíveis com o conceito final do ES6. Mas, por outro lado, nós TIVEMOS. Muito antes do ES6. E esse é o ponto principal do nosso lado. Grosso modo, não nos importamos como você consegue emitir o código apropriado para isso, estamos apenas usando-o com prazer. Mesmo com módulos, e tudo. Nós (ou pelo menos eu) não vimos essas dores do que você está falando, sempre ficamos felizes com membros ou módulos privados.

Esse recurso espec√≠fico est√° no CoffeScript enquanto leio sobre ele. Por que n√≥s, desenvolvedores simples, sempre temos que fazer concess√Ķes ao escolher uma plataforma/biblioteca/plugin, etc.? Quero dizer sempre . Isso √© meio irritante. Aqui temos uma grande linguagem, que tem um grande potencial, que deixa completamente para tr√°s todos os outros participantes (incluindo ES!), e que revolucionou com sucesso uma grande parte do desenvolvimento do lado do cliente, e quando se trata desse recurso "simples" ( Quero dizer, pelo menos a parte de acesso ao membro), ouvimos que n√£o ser√° implementado at√© que ES se comprometa com isso.

Eu queria avisar rapidamente que esse recurso passou do est√°gio 0 para o est√°gio 1 na reuni√£o do TC39 de hoje.

Confirmação relevante: https://github.com/tc39/proposals/commit/cb447642290a55398d483f5b55fb7f973273c75d
Agenda da reuni√£o: https://github.com/tc39/agendas/blob/master/2017/01.md

Uau! Aquilo é enorme!

Algumas "surpresas" que vejo aqui (não estou dizendo que discordo, apenas coisas que provavelmente teríamos feito diferente se tivéssemos feito isso antes):

  • null n√£o √© produzido a partir de uma express√£o a?.b : quando a √© null isso produz undefined
  • ~ Propaga√ß√£o em pontos encadeados: a?.b.c.d n√£o ser√° lan√ßado se as propriedades b e c forem undefined ~ Ryan n√£o puder ler
  • ~Propaga√ß√£o na presen√ßa de par√™nteses : mesmo (a?.b).c n√£o ser√° lan√ßado se b for indefinido~ Ryan n√£o consegue ler
  • ~A propaga√ß√£o ocorre mesmo em chamadas de m√©todo: a?.b.c().d retornar√° undefined se a invoca√ß√£o c retornar null ~ Ryan n√£o puder ler
  • O operador delete √© suportado
  • A sintaxe de colchetes a?.[x] √© suportada
  • A sintaxe de chamada de fun√ß√£o func?.(...args) √© suportada, mesmo para chamadas que n√£o sejam de m√©todo (!)

Eu esperaria ver mudanças nessas áreas entre agora e o estágio 2.

Acho que o coffeescript acertou.

a?.bc lança se b é indefinido.

a?() e a?[0] s√£o ambos bons.

  • Propaga√ß√£o em pontos encadeados: a?.bcd n√£o ser√° lan√ßado se as propriedades b e c forem indefinidas
  • Propaga√ß√£o na presen√ßa de par√™nteses: mesmo (a?.b).c n√£o ser√° lan√ßado se b for indefinido
  • A propaga√ß√£o ocorre mesmo em chamadas de m√©todos: a?.bc().d retornar√° undefined se a invoca√ß√£o c retornar null

Esses pontos n√£o me parecem precisos. Da proposta:

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

Uau, eu interpretei isso totalmente errado. Você está certo. Atualizando

@algesten da proposta original:

a?.()

b?.[0]

doce. o operador pode ser considerado ?. ent√£o.

H√° algumas conversas adicionais acontecendo aqui: https://github.com/estree/estree/issues/146

Uma cita√ß√£o que se aplica bem: ¬ęTorne as coisas simples f√°ceis e as dif√≠ceis poss√≠veis ¬Ľ. Assim, talvez, suporte bem os casos mais comuns, enquanto ignora (pelo menos inicialmente) os casos complicados/raros, enquanto eles ainda podem ser "feitos manualmente" com sintaxe mais longa (existente).

Apenas meus dois centavos

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

para:

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

@cedvdb sem√Ęntica totalmente diferente - exce√ß√Ķes lan√ßadas em getters n√£o devem causar coalesc√™ncia

@RyanCavanaugh sim .. Eu n√£o pensei nisso.

Isso está no radar para implementação agora, ou a equipe de TS esperará que a proposta de ES avance?

Est√° na nossa lista curta; ainda temos algumas perguntas/preocupa√ß√Ķes, mas voc√™ deve ver um movimento sobre isso no pr√≥ximo m√™s.

N√£o tenho certeza de onde veio o coment√°rio de @mhegazy - o n√ļmero de perguntas em aberto sobre a proposta TC39 √© muito grande para que possamos fazer um trabalho significativo aqui. Especificamente, quest√Ķes sobre como null e undefined interagem e qual sintaxe √© realmente suportada precisam ser abordadas primeiro. O est√°gio 2 √© o m√≠nimo absoluto e preferimos o est√°gio 3 devido ao impacto no comportamento do tempo de execu√ß√£o.

este código simplesmente funciona?

a == undefined ? expression : undefined

expression significa ax, a[x], a(x), delete também pode ser gerado aqui

ent√£o a?.b?.[c]?.(d) ir√° gerar

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

parece vai passar por toda a regra de RyanCavanaugh


se odeia o operador == , também pode ser a === undefined || a === null

@zh99998 você _tem_ que odiar == porque '' e 0 também são equiparados. Quase se argumenta que o comportamento do tempo de execução deve ser algum tipo de verificação em (typeof value === 'object' || typeof value === 'function' || typeof value === 'symbol') && value !== null , que agora está ficando bastante complexo.

Como @RyanCavanaugh disse, é improvável que progrida até que a proposta TC39 progrida para pelo menos o estágio 2 ou 3.

Vejo == igual null e undefined como
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness

e teste passado no console chrome:

'' == undefined
false
0 == undefined
false

@kitsonk undefined apenas coage para null e vice-versa. Nenhum outro valor coage para indefinido ou nulo.

Você parece estar confuso com valores falsos. 0 e "" são realmente falsos, mas nunca coagirão a nulo nem indefinido.

== implica coerção. null == 0 é falso porque nada, exceto indefinido, pode forçar a nulo. O mesmo vale para undefined == 0 .

Outro exemplo poderia ser

    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

Você começa a imagem.

Vejo muitas tentativas usando operadores ternários, mas qualquer implementação que se refira à mesma propriedade várias vezes pode resultar em efeitos colaterais inesperados.

Felizmente, JavaScript tem IIFEs, ent√£o voc√™ pode armazenar o resultado de um acessador em um par√Ęmetro de fun√ß√£o, consult√°-lo o quanto quiser e nunca avali√°-lo mais de uma vez. No meu exemplo abaixo, crio um lambda coalesce que pode ser chamado v√°rias vezes no lugar de uma express√£o contendo operadores ?. .

Uma coisa com a qual os implementadores de linguagem precisariam se preocupar s√£o chamadas de array e fun√ß√£o no meio de uma express√£o. Acho que o compilador poderia lidar com a detec√ß√£o dessas situa√ß√Ķes e simplesmente anexar essas express√Ķes ao final da chamada 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]

Observe que não há necessidade de um global real chamado "coalesce". Esse código pode ser embutido diretamente em qualquer expressão. Pode reduzir o inchaço dando-lhe um nome, no entanto.

N√£o estou muito preocupado com a sintaxe usada para o operador ou se os implementadores da linguagem querem esperar por um padr√£o. Apenas pensei em mostrar outra abordagem.

Isso também traz a necessidade de um operador ?? . Em C#, isso substitui qualquer expressão null pelo que estiver à direita.

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

Infelizmente, a veracidade captura muitos casos extremos ( 0 , false , etc.). Trabalhando com um operador nulo coalesce ( ?. ), você desejaria algo específico para null -ness.

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

@jehugaleahsa , no seu exemplo com coalesce, teria que haver uma maneira de impedir que chamadas de função e acesso a membros acontecessem se a verificação anterior retornasse nula. No exemplo x?.f(), f não deve ser chamado se x for nulo.

@bschlenk Acho que n√£o concordo. Acho que deve falhar com uma mensagem como null is not a function , mas isso n√£o depende de mim, eu acho.

O recente aumento nos comentários detalhando possíveis maneiras de implementar o operador é um pouco estranho.
A implementação é provavelmente um problema resolvido.

Se voc√™ estiver interessado, h√° a biblioteca idx , que se assemelha muito ao comportamento do operador ?. , embora tamb√©m ignore muitos detalhes do operador planejado. De qualquer forma, suas especifica√ß√Ķes para a sa√≠da de compila√ß√£o podem ser de interesse para quem se pergunta sobre as maneiras pelas quais essas coisas podem ser implementadas.

O TS pode produzir algo assim ou pode produzir algo completamente diferente, mas não acho que seja isso que estamos esperando aqui. Já foi dito muitas vezes aqui que o TS não conseguirá o operador até que a proposta do ES se mova para uma direção ou para outra.

√Č a sem√Ęntica que ainda tem algumas inc√≥gnitas, listadas aqui e aqui .

Tenha certeza de que estaremos implementando isso corretamente e não precisamos de mais 100 comentários aqui para descobrir o que || e ? ... : ... fazem. Como @noppa observou, estamos apenas aguardando a finalização da especificação ES.

https://github.com/babel/babel/pull/5813 (acompanhando o PR da babil√īnia) acabou de ser incorporado ao preset-stage-1 da Babel. A especifica√ß√£o ainda est√° no est√°gio 1, √© claro, mas isso ajudar√° a avan√ßar.

Talvez eu esteja errado, mas não vi nenhum link óbvio para a proposta tc39 neste tópico, então aqui está para os futuros leitores: https://github.com/tc39/proposal-optional-chaining

O encadeamento opcional FYI estará no TC39 na próxima semana https://github.com/tc39/agendas/blob/master/2017/07.md

@jehugaleahsa Acho que você está certo e estarei apresentando ?? no TC39 na próxima semana. Você pode acompanhar a proposta aqui: https://github.com/gisenberg/proposal-nullary-coalescing

Vejo que o encadeamento opcional foi coberto no TC39... Qual foi o veredicto?
Espero que tenha sido o suficiente para avan√ßar isso no Typescript ūüėČ

@markwhitfeld Do resumo das notas :
Operadores de encadeamento opcionais: permanece no est√°gio 1, voltar√° mais tarde com defini√ß√Ķes mais claras para v√°rias op√ß√Ķes e respostas aos coment√°rios

Notas completas aqui: https://github.com/rwaldron/tc39-notes/blob/master/es8/2017-07/jul-27.md#13iia -optional-chaining-operator

Ainda h√° quest√Ķes em aberto sobre como o operador deve se comportar, ent√£o parece que ainda n√£o est√° em um estado em que possa ser adicionado ao TypeScript.

A partir dessas notas, parece que o comit√™ n√£o tem ideia de como as op√ß√Ķes apresentadas funcionam, eu pensei que eles teriam aproveitado para conhecer as propostas que estavam planejando discutir, antes de discuti-las. Acho que vai demorar um pouco mais at√© que eu possa habilitar verifica√ß√Ķes nulas estritas.

Eu espero muito que eles vão com a opção 2/4 (que é o estado atual da proposta de qualquer maneira).

15 de julho de 2014 - 4 de setembro de 2017, nada ainda

@frankfvb você claramente não leu o problema.

Houve muita discussão que levou a equipe principal a acreditar que seria imprudente implementar neste momento até que haja mais progresso na proposta ECMAScript que impactaria diretamente a funcionalidade desse recurso no TypeScript.

Desde a √ļltima reuni√£o do comit√™ de padr√Ķes ECMAScript, a proposta permanece na Fase 1 , pois tem algumas quest√Ķes muito fundamentais sobre como seria implementada. Embora n√£o seja uma regra r√≠gida e r√°pida, o TypeScript implementar√° apenas as propostas do Est√°gio 3. √Äs vezes, ele implementa propostas do Est√°gio 2 se eles acreditam que √© de import√Ęncia cr√≠tica e potencialmente o uso no TypeScript impulsiona a evolu√ß√£o do padr√£o.

N√£o tenho certeza de como as pessoas mais claras podem ser sobre isso.

Como eu disse anteriormente , isso est√° na nossa lista curta. estamos esperando que o TC39 chegue a algum tipo de consenso sobre a sem√Ęntica do operador. n√≥s odiar√≠amos lan√ßar isso e depois quebrar os usu√°rios.

Este não é o tópico para refazer a discussão do TC39

Se quiser ponderar na proposta, v√° coment√°-la no local apropriado . Eu tamb√©m tenho opini√Ķes, mas coloc√°-las neste t√≥pico n√£o vai fazer nada.

Criei algo simples que atende às minhas necessidades atuais. Ele só funcionará em uma cadeia em que cada link é um nome de propriedade, portanto, o acesso a um elemento em uma matriz (por exemplo) não é suportado.

Implementando um operador Elvis realmente simples no TypeScript

Além disso, se você tiver lodash/underscore, já pode usar _.get(Book, 'author.name.firstName') que fará o que isso quer

Edit: Aparentemente, este é um mau conselho por causa de problemas de tipo com o método _.get() . Veja o comentário abaixo

@tolgaek , _.get tem digita√ß√Ķes ruins, mesmo com essas tipagens melhores ( ainda n√£o mescladas , por causa dos autores) o typescript pode definitivamente deduzir o tipo de resultado apenas se a profundidade do objeto for 1, em todos os outros casos √© any e deve ser verificado em tempo de execu√ß√£o

Por outro lado, com o operador elvis, o texto datilografado pode ser capaz de inferir o tipo de resultado em objetos com qualquer profundidade, é por isso que estou ansioso pelo operador elvis

oh entendo, eu não sabia que havia problema de digitação. Obrigado @BjornMelgaard

@mhegazy esse recurso n√£o pode ser implementado primeiro e marcado como recurso experimental? Eu acho que as pessoas n√£o devem ter problemas se houver altera√ß√Ķes nas especifica√ß√Ķes do recurso experimental.

Elvis n√£o se diverte esperando tanto tempo.

Aterrissou em Babel7. Texto datilografado, estamos lentos. Alguém, por favor, faça isso acontecer.
:)

@gs-akhan o plugin Babel implementa uma vers√£o antiga da proposta de alguns meses atr√°s. Houve mudan√ßas na proposta desde ent√£o (incluindo uma mudan√ßa significativa na forma como o operador √© analisado), e provavelmente haver√° mais mudan√ßas antes que o recurso atinja o est√°gio 2 (muito menos o est√°gio 3), portanto, qualquer c√≥digo escrito com o babel atual plugin pode quebrar quando o recurso real for lan√ßado. O Babel implementa intencionalmente os recursos propostos antes que eles fiquem est√°veis ‚Äč‚Äčpara que os autores das especifica√ß√Ķes e outras partes interessadas possam experimentar o recurso conforme proposto. S√≥ porque o Babel implementou um recurso n√£o significa que ele possa ser implementado de uma forma que n√£o exija mudan√ßas importantes no futuro.

@alangpierce Isso faz sentido. Obrigado

Entendo que este é um operador muito, muito bom, mas tê-lo disponível antes que suas regras sejam resolvidas é uma arma de fogo e não vamos fazer isso. O comportamento de tempo de execução do operador ainda está em fluxo; se você escrever código hoje, ele pode parar de funcionar amanhã de maneiras que não são imediatamente aparentes - talvez falhas raras, talvez corrupção de dados, quem sabe? Um pouco de paciência agora vai lhe poupar muita dor daqui a alguns meses.

Começando a pensar que este ticket deve ser bloqueado (não fechado) até que a especificação esteja pronta.

Quando a especificação estará pronta?

@oliverjanik A especificação de rascunho atual pode ser encontrada aqui . Há um item de agenda para avançar a proposta para o estágio 2 na próxima reunião do TC39 (26/09 a 28/09). Eu estarei apresentando esses slides naquele momento. Para pessoas que gostariam de revisar antecipadamente e fornecer feedback, registre problemas no repositório de propostas .

Muito obrigado @gisenberg por defender essa quest√£o para n√≥s! Eu estava pensando em montar um conjunto de slides resumido para ajudar a esclarecer as op√ß√Ķes em torno do operador que poderiam ser usadas na reuni√£o do TC39 para evitar confus√£o, mas voc√™ j√° fez isso. Otimo trabalho!
Talvez apenas uma outra coisa que possa ser ben√©fica para a conversa do TC39 (e o conjunto de slides) seja observar a sem√Ęntica e a sintaxe do operador em outros idiomas. Embora outras linguagens n√£o devam necessariamente ditar como deve funcionar em Javascript, seria √ļtil manter o operador semelhante ao de outras linguagens para evitar confus√£o.
Boa sorte para a próxima semana!!!

Desculpe por sair um pouco do t√≥pico mais uma vez, mas imaginei que algumas pessoas aqui poderiam achar interessante que no Flow agora √© poss√≠vel adicionar defini√ß√Ķes de tipo de trabalho para fun√ß√Ķes getter seguras como _.get .

Exemplo: flowtype.org/try

Não é o código mais bonito de todos os tempos e não distingue corretamente entre nulo e indefinido, mas fora isso parece funcionar muito bem.

AFAIK a √ļnica coisa que falta no TS para fazer o mesmo √© algo assim $NonMaybeType .
Não que isso eliminasse a necessidade desse operador, claro, só achei legal.

Isso n√£o atingiu o Est√°gio 2 na √ļltima reuni√£o do TC39 devido a preocupa√ß√Ķes sobre a consist√™ncia sint√°tica em rela√ß√£o ao acesso de colchete vs ponto vs chamada e comportamento sem√Ęntico (previsibilidade em torno dos efeitos colaterais das express√Ķes √† direita de um undefined / null -operando avaliado), bem como perguntas abertas sobre que tipo de express√Ķes podem ser n√£o-op'd (por exemplo x.?b() quando x.b √© um number )

(vote ūüéČ neste coment√°rio para jogar fruta podre)

Obrigado por nos informar. Que chato. Talvez o escopo precise ser reduzido para que seja mais simples, mas ainda √ļtil?

Talvez o escopo precise ser reduzido para que seja mais simples, mas ainda √ļtil?

Este √© o desafio que o TC39 enfrenta, que, embora chato, tenho que admitir que estou feliz que as pessoas estejam passando por isso. √Č muito dif√≠cil para eles introduzirem uma sintaxe de n√≠vel bastante complexa e, de fato, nesse caso, a digita√ß√£o fraca da linguagem est√° causando uma quantidade significativa de casos extremos que precisam ser resolvidos, ou voc√™ obt√©m c√≥digo que vai ūüí• o que √© n√£o √© bom para ningu√©m. Eu n√£o acho que se voc√™ introduzir um operador como esse, voc√™ pode realmente restringir seu escopo. Seria mais f√°cil para os implementadores cobrirem 90% dos casos, mas n√£o acho que ¬Į\_(„ÉĄ)_/¬Į seja um c√≥digo v√°lido para os 10% restantes.

Pessoal, mais de 3 anos depois, eu diria que é hora de dizer "foda-se" para o comitê e fazer do nosso jeito, o que for idiomático para o TypeScript. Esse recurso não pode funcionar corretamente sem digitação estática.

Fa√ßa uma implementa√ß√£o do TypeScript com uma sintaxe que seja explicitamente incompat√≠vel com a proposta do TC39. Depois que o ES obtiver um operador de navega√ß√£o segura, o TypeScript ter√° duas op√ß√Ķes: uma com sem√Ęntica de merda compat√≠vel com ES e outra vinculada ao sistema de tipos. Isso significa que voc√™ n√£o pode usar o operador safe-nav TS com qualquer "tipo", e tudo bem.

@notsnotso Typescript não deve quebrar o JS, é para isso que serve o Coffeescript.

Talvez uma boa solução seja:

  • implementar muito simples? operador para desenvolvedores impacientes, como recurso experimental (como decorador), com aviso - ele quebrar√° seu c√≥digo no futuro
  • espere mais 3 anos quando o padr√£o for escrito, implemente como recurso n√£o experimental. Escreva tutorial, o que poderia ser quebrado. Mesmo, com a tipagem est√°tica, √© poss√≠vel escrever avisos quando as pessoas compilam o c√≥digo com a implementa√ß√£o do novo operador.
    "faça do nosso jeito, o que for idiomático para o TypeScript" não é um caso, porque em 3 anos as pessoas vão se deparar com o problema, que ts elvis não funciona da mesma maneira que em js.

N√£o estou surpreso que isso n√£o tenha acontecido, para ser honesto. No meu original
post, apontei a ambiguidade em relação à indexação, chamadas de função, etc.
Honestamente, quanto mais eu penso em ?. , mais parece que n√£o
pertencem em JavaScript, pois tem undefined .

Eu preferiria um utilitário de propósito mais geral que resolvesse esse problema
e mais. Um pensamento que tive foi algo como uma linha try/catch
express√£o ( let x = try a.b.c else 0 ) em conjunto com um operador que
verificado para "nully" (por exemplo, x ?? 1) em vez de "falsey" (por exemplo, x || 1).
Ent√£o, voc√™ os combinaria assim: try a.b.c ?? 0 else 0 . √Č prolixo, sim,
mas basicamente diz: Tente avaliar abc e se o resultado for null ou
undefined , retorna 0. Se a ou b for undefined e uma exceção for lançada,
peg√°-lo e retornar um 0.

Uma alternativa seria tornar a cl√°usula else opcional, padronizando
undefined . Então você poderia escrever a expressão como: let x= (try a.b.c) ?? 0 . Isso é muito compacto, evita a ambiguidade e fornece uma visão mais
solução de propósito geral que pode resolver outros problemas.

N√£o estou dizendo que devemos pressionar por isso; tudo o que estou dizendo est√° l√°
s√£o alternativas para ?. e devemos realmente explorar nossas op√ß√Ķes at√©
encontre um que se encaixe bem com a linguagem JavaScript.

Na quinta-feira, 5 de outubro de 2017 √†s 7h51, Dmitry Radkovskiy [email protected]
escrevi:

@notsnotso Typescript não deve quebrar JS, é isso que
Coffeescript é para.

‚ÄĒ
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/Microsoft/TypeScript/issues/16#issuecomment-334441781 ,
ou silenciar o thread
https://github.com/notifications/unsubscribe-auth/ABTgPilbZfuKc2egdBrYfdTHHeDl3F6Sks5spMLLgaJpZM4CNapf
.

@zlumer boa piada. Dito isso, um recurso específico do TS não quebraria o Javascript.

@jehugaleahsa Eu gosto da sua proposta, e ela é encontrada em outros idiomas. Eu acho que funcionaria muito bem para o TS.

Eu direi que realmente n√£o entendo a forte necessidade de esperar at√© que o ECMAScript aceite o operador. O TypeScript adicionou classes, m√≥dulos, lambdas, tudo muito antes de chegarem ao ECMAScript. Na verdade, um dos objetivos declarados do TypeScript foi/√© testar recursos JS experimentais. O TypeScript fornecendo sua pr√≥pria implementa√ß√£o sem d√ļvida ajudaria a informar essas discuss√Ķes no comit√™.

Vocês estiveram dispostos a fazer mudanças importantes antes, quando o comitê eventualmente seguir uma direção diferente, eu realmente não vejo por que esse recurso é tão diferente.

async/await também foi introduzido ao TypeScript em um estágio inicial.

Dito isso, um recurso específico do TS não quebraria o Javascript.

N√£o haver√° algo como "recurso espec√≠fico do TS", verifique as metas de design do TypeScript para obter mais informa√ß√Ķes.

O TypeScript chega antes do ES indo para um caminho brilhante, pode haver alguns existentes,eles s√£o mantidos apenas para compatibilidade.

O TypeScript adicionou classes, módulos, lambdas, tudo muito antes de chegarem ao ECMAScript.

E os m√≥dulos em particular s√£o um grande desastre que ainda causa confus√£o sem fim. Esse √© um exemplo que a equipe do TypeScript usou repetidamente como um exemplo de _erro_ e se precipitando cedo demais. Tamb√©m temos campos privados surgindo agora, o que, novamente, tenho sido grato por private nos √ļltimos 5 anos, mas n√£o causar√° confus√£o sem fim.

Novamente, os decoradores est√£o dispon√≠veis sob a bandeira, mas agora que os decoradores est√£o realmente chegando ao Est√°gio 3, ser√° necess√°ria uma reimplementa√ß√£o e quebra de c√≥digo para o TypeScript. √Č por isso que essas coisas _n√£o_ podem ser tomadas como prov√°veis.

async/await também foi introduzido ao TypeScript em um estágio inicial.

Uma vez que a proposta ECMAScript atingiu a Fase 3.

Ningu√©m est√° se comportando mal, mas se essa conversa n√£o puder ir a lugar algum, exceto em c√≠rculos (e se houvesse uma bandeira? Sim, estamos cientes das bandeiras) ou fora do t√≥pico (e se TS deixar de ser JS? N√£o, cinco anos depois, n√£o estamos mudando nossa mente nisso), n√£o precisamos t√™-lo. Dissemos h√° cerca de 3 anos que implementaremos isso exatamente quando o comit√™ ES bloquear sua sem√Ęntica.

Mais uma vez, o repositório da proposta é https://github.com/tc39/proposal-optional-chaining e você pode acompanhar seu progresso lá. Estaremos trabalhando offline para tentar melhorar as chances da proposta na próxima reunião do TC39 porque queremos muito que isso também seja aprovado.

Atualização: Chegamos ao estágio 2 esta tarde no TC39!!!

O encadeamento opcional é o Estágio 3

Desbloqueando brevemente este apenas para fins comemorativos

Viva!

Não faça spam...

Você pode enviar um emoji expressando seus sentimentos

Não faça spam...

Você pode enviar um emoji expressando seus sentimentos

Além disso, é divertido ver a contagem de emojis subir assim. Eu nunca vi um comentário de problema ganhar tanta popularidade tão rápido!

Gravei um pequeno v√≠deo das atualiza√ß√Ķes em tempo real https://youtu.be/JLBrgPjeGhc

Alguém pode me descadastrar dessa coisa?

@DanielRosenwasser Caso você não esteja brincando, ou para qualquer outra pessoa que queira cancelar a inscrição e não saiba como, você está procurando este botão na barra lateral direita:

image

Sem falar que h√° um link no e-mail:

image

Foi uma brincadeira, estou trabalhando na proposta.

@RyanCavanaugh depois de desbloquear este problema:
martian

Muito animado para ver isso finalmente pousar! ūüéą ūüéČ

Mal posso esperar pela corre√ß√£o r√°pida do VSCode correspondente ūüėÜ

image

Estou indo para @ @RyanCavanaugh porque ele provavelmente não está inscrito neste tópico e eu quero ser rude! (e @DanielRosenwasser para uma boa medida)

@kitsonk Não seja burro. As pessoas são livres para cancelar a inscrição e não serem assediadas.

@kitsonk , Por que RyanCavanaugh ou DanielRosenwasser seriam cancelados neste tópico? Ryan desbloqueou este problema e Daniel respondeu três comentários acima de você.

Mesmo que eles tenham sido cancelados, não há necessidade de causar mais fadiga de notificação enviando spam para eles.

Aparentemente o GitHub é um lugar terrível para humor sarcástico, caramba...

Muito obrigado aos nossos campe√Ķes do TC39 por descobrir os detalhes desagrad√°veis ‚Äč‚Äčdesse novo recurso de linguagem!

thanks

Acho que @kitsonk estava apenas brincando, assim como eu meio que estava. Enquanto estamos sendo um pouco bobos com a emoção, este é um lembrete gentil para manter as coisas civis de acordo com o CoC.

@Daniel Rosenwasser
Eu poderia ter que tentar isso? Ou @rbuckton tem mais um ramo para ele ūüôčūüŹĽ‚Äć‚ôāÔłŹ


Ok, entendi https://github.com/microsoft/TypeScript/commits/optionalChainingStage1 ūü§¶ūüŹĽ‚Äć‚ôāÔłŹ

Sim, isso é bastante desatualizado, infelizmente.

Acabei de perceber que esta edi√ß√£o foi aberta h√° 5 anos. :at√īnito:

@rbuckton

Sim, isso é bastante desatualizado, infelizmente.

Eu poderia tentar isso?

Desculpe @jhpratt @MatthiasKunnen , esqueci que nem todos compartilhamos o mesmo contexto no GitHub. Eu tenho saltado por aqui por um longo tempo e passei um tempo com Ryan e Daniel IRL e participei brevemente do evento recente que deu origem à minha piada interna incompreendida. Desculpas.

Toda esta edi√ß√£o, por√©m, mostra uma interessante arqueologia dos princ√≠pios de design do TypeScript. Ryan o levantou em um momento em que o TypeScript _poderia_ realmente considerar a sintaxe que antecedeu a considera√ß√£o s√©ria no ECMAScript. Foi nessa √©poca que o TypeScript internamente estava aprendendo algumas li√ß√Ķes de previs√£o da sintaxe do ES2015 que estavam causando s√©rios impactos na linguagem. A equipe decidiu n√£o considerar a inclus√£o at√© que houvesse uma proposta do TC39 Est√°gio 3.

Embora @RyanCavanaugh possa resolver isso, e eu sei que ele esteve perto do que aconteceu com a proposta, suspeito que seria improvável que o que a equipe teria implementado em 2014 fosse 100% compatível com a proposta atual do Estágio 3 . Portanto, embora certamente seja uma celebração, também seja grato por não termos 5 anos de código TypeScript com um operador de navegação seguro que não seria totalmente consistente com o comportamento da proposta.

ūüôŹ

westwing

Este √© o momento de remover o r√≥tulo Waiting for TC39 ? ūü§Ē

Este √© o momento de remover o r√≥tulo Waiting for TC39 ? ūü§Ē

E adicione ship-it

uau uau

Finalmente. Literalmente estava perguntando sobre o encadeamento opcional y'day, imaginando quando ser√° o est√°gio 3, e bam! Obrigado a todos que estavam trabalhando para passar por isso!

Como silenciar este tópico? :)

@opnksyn Se voc√™ n√£o se importa com o entusiasmo do spam, h√° um recurso para ser notificado quando esse problema for encerrado. Isso impedir√° que todos os coment√°rios apare√ßam em notifica√ß√Ķes como a que voc√™ acabou de fazer ūüėĄ

image

image

Alguma solução de emissão já definida?
Algo assim pode ser interessante:

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

Eu prefiro o que o Babel faz, pois evita criar escopos de função desnecessários:

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

Eu prefiro o que o Babel faz, pois evita criar escopos de função desnecessários:

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

Concordo, @ExE-Boss. Eu sinto que evitar a criação de escopos de função desnecessários é o ideal (mesmo que torne o código compilado um pouco feio)

Desempenho e aderência à especificação ES devem definitivamente vencer a legibilidade quando estamos falando de código compilado.

Existe alguma razão para o código compilado pelo Babel se comparar a null e void 0 com triplo igual em vez de um simples == null ?

Existe alguma razão para o código compilado pelo Babel se comparar a null e void 0 com triplo igual em vez de um simples == null ?

@proteria Acabei de dar uma olhada r√°pida no c√≥digo de encadeamento opcional para __Babel__ ; parece que se voc√™ passar a op√ß√£o loose e configur√°-la para um valor verdadeiro, ela n√£o produzir√° as verifica√ß√Ķes de igualdade estritas

Isso √© por causa de document.all (ou para ser pedante, o slot interno [[IsHTMLDDA]] ), uma peculiaridade que recebe tratamento especial na linguagem para compatibilidade com vers√Ķes anteriores.

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

Na proposta de encadeamento opcional

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

mas document.all == null ? void 0 : document.all.foo retornaria incorretamente void 0 . No modo solto, esse detalhe da especificação é descartado por simplicidade/desempenho/tamanho do código gerado, pois a maioria das pessoas não precisa lidar com document.all qualquer maneira.

Certamente o caso document.all poderia ser especial? Não deve exigir muito código extra, apenas algumas linhas para verificar o objeto e a propriedade.

Exceto que document.all pode ser atribuído a uma variável, e rastrear onde ela é usada requer um sistema de tipos, e é por isso que o Babel produz por padrão:

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

Eu estou ciente disso. Babel n√£o tem um sistema de tipos, o TypeScript tem. Talvez n√£o seja t√£o simples como eu fiz parecer, mas imagino que j√° exista c√≥digo para certas situa√ß√Ķes que seja capaz de rastrear o uso.

Na verdade, você não precisa de um sistema de tipos para rastrear variáveis document.all , já que o comportamento especial está em HTMLAllCollection , não document.all .

Então você deve ser capaz de fazer uma verificação instanceof HTMLAllCollection , e você será ouro.

Sim, mas... por que você fez instanceof quando você pode apenas fazer === null || === void 0 ? Certamente isso é mais simples.

Com certeza - eu estava apenas apontando que você não precisa de um sistema de tipos para rastrear document.all :)

Pessoalmente, estou tentado a dizer apenas quebre e veja quem reclama, mas est√° nas especifica√ß√Ķes, ent√£o √© mais f√°cil ficar com isso.

@noppa Pode ser executado em tempo de compilação. Se foo instanceof HTMLAllCollection for true , emit foo === null || foo === void 0 , caso contrário podemos _safely_ emitir foo == null .

@G-Rath Goste ou não, obsoleto não significa que não deva funcionar. O TypeScript deve permanecer compatível com JavaScript.

@jhpratt Mas isso atualmente vai contra os Non‚ÄĎGoals do TypeScript Design .

Além disso, você ainda teria que fazer foo === null || foo === void 0 para qualquer coisa à qual HTMLAllCollection pudesse ser atribuído, por exemplo. any ou object , então acho que não vale a pena.

Presumo que você esteja se referindo ao não-objetivo (5)

Adicione ou confie em informa√ß√Ķes de tipo de tempo de execu√ß√£o em programas ou emita c√≥digo diferente com base nos resultados do sistema de tipos. Em vez disso, incentive padr√Ķes de programa√ß√£o que n√£o exijam metadados de tempo de execu√ß√£o.

Embora eu concorde que isso certamente emitiria um código diferente com base no tipo, é apenas para reduzir o tamanho do código. Embora, como você apontou, não seja tão simples quanto verificar HTMLAllCollection .

Para ser justo, TS _has_ rejeitou um potencial minificador que usa informa√ß√Ķes de tipo, e isso √© (mais ou menos) relacionado - o principal motivo para emitir == null √© reduzir o tamanho do c√≥digo com base nas informa√ß√Ķes de tipo.

Se isso _não for_ implementado, seria ótimo se a equipe lang adicionasse uma opção ao tsconfig semelhante à opção "solta" do Babel.

Depois de verificar rapidamente, o terser converte automaticamente foo === null || foo === undefined em foo == null , o que não é seguro devido a esse caso extremo.

Se isso não for implementado, seria ótimo se a equipe lang adicionasse uma opção ao tsconfig semelhante à opção "solta" do Babel.

Da mesma forma, muitos de n√≥s usam o TypeScript para ferramentas de constru√ß√£o e para aplicativos m√≥veis, nenhum dos quais precisa se preocupar com as restri√ß√Ķes do navegador!

Na verdade, usamos TS e Babel juntos, ent√£o talvez uma dessas op√ß√Ķes seja passar o operador para o Babel/tempo de execu√ß√£o subjacente!

@fbartho

Na verdade, usamos TS e Babel juntos, ent√£o talvez uma dessas op√ß√Ķes seja passar o operador para o Babel/tempo de execu√ß√£o subjacente!

Não entendo este comentário. Você não precisa de nenhuma opção extra para passar o operador para o Babel; se você tiver o TypeScript configurado para o Babel, você já terá noEmit: true que já passa _tudo_ para o Babel.

A implementação do TypeScript do @Zarel Babel está faltando vários recursos nos quais nossa base de código já estava confiando, incluindo namespaces e const enums. Estamos usando TSC com emissão habilitada e aplicando Babel como uma segunda transformação. (Estamos trabalhando para nos livrar dos namespaces, mas não está claro se conseguiremos nos livrar de todos os recursos incompatíveis)

As pessoas que chegam a este t√≥pico devem come√ßar no an√ļncio do est√°gio 3 anterior e ler os coment√°rios a partir da√≠ (culpe o GitHub por ocultar toneladas de conte√ļdo do usu√°rio sem uma maneira direta de carregar tudo)

√ďtimo recurso - "encadeamento opcional" / "navega√ß√£o segura". Especialmente no modo estrito do TypeScript. Impressionante saber que isso ser√° implementado em breve. ‚̧ԳŹ

Isso me trouxe até aqui e espero que seja apoiado. Apenas um caso de uso:

Esperado no TypeScript 3.7.

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

VS

Atualmente no TypeScript 3.5.

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

Funcionará sem erros? Ou ainda é um TypeError: Cannot read property 'setAttribute' of null. ? O ? op. deve ser cancelado outras cadeias após null / undefined.

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

espero o seguinte:
Se o elemento html não existir (null). O console deve registrar One e Two , e o método setAttribute não deve ser invocado. (Sem erros).
Eu entendi isso corretamente?

@domske FYI, isso não é estritamente um recurso TS; é um recurso JS.

De acordo com a proposta do TC39 a sintaxe ser√°:

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

A discussão começou a circular novamente, então voltamos ao estado bloqueado.

Eu realmente imploro a qualquer pessoa tentada a deixar um comentário em um tópico do GitHub com mais de 100 comentários para realmente se comprometer a ler todos os comentários anteriores primeiro. Provavelmente sua pergunta, e a resposta para ela, será encontrada lá!

Esta p√°gina foi √ļtil?
0 / 5 - 0 avalia√ß√Ķes