Anúncio do TypeScript 3.3 RC

Hoje, temos o prazer de anunciar a disponibilidade do nosso candidato a lançamento (RC) do TypeScript 3.3. Nossa esperança é coletar feedback e questões iniciais para garantir que nosso lançamento final seja fácil de usar e usar imediatamente.

Original no blog

Para começar a usar o RC, você pode acessá- lo através do NuGet ou usar o npm com o seguinte comando:


npm install -g typescript@rc 

Você também pode obter suporte do editor



O TypeScript 3.3 deve ser uma versão tranqüila a ser adotada e não contém alterações significativas. Vamos explorar o que há de novo no 3.3.


Comportamento aprimorado para chamar tipos de união


Quando o TypeScript possui um tipo de união A | B A | B , permite acessar todas as propriedades comuns a A e B (ou seja, a interseção de membros).


 interface A { aProp: string; commonProp: string; } interface B { bProp: number; commonProp: number } type Union = A | B; declare let x: Union; x.aProp; // error - 'B' doesn't have the property 'aProp' x.bProp; // error - 'A' doesn't have the property 'bProp' x.commonProp; // okay! Both 'A' and 'B' have a property named `commonProp`. 

Esse comportamento deve parecer intuitivo - você só pode obter uma propriedade de um tipo de união se for conhecida em todos os tipos de união.


Que tal, em vez de acessar propriedades, estamos lidando com tipos de chamada? Bem, quando todo tipo tem exatamente uma assinatura com parâmetros idênticos, as coisas simplesmente funcionam e você pode chamar esses tipos.


 type CallableA = (x: boolean) => string; type CallableB = (x: boolean) => number; type CallableUnion = CallableA | CallableB; declare let f: CallableUnion; let x = f(true); // Okay! Returns a 'string | number'. 

No entanto, essa restrição às vezes era muito restritiva.


 type Fruit = "apple" | "orange"; type Color = "red" | "orange"; type FruitEater = (fruit: Fruit) => number; // eats and ranks the fruit type ColorConsumer = (color: Color) => string; // consumes and describes the colors declare let f: FruitEater | ColorConsumer; // Cannot invoke an expression whose type lacks a call signature. // Type 'FruitEater | ColorConsumer' has no compatible call signatures.ts(2349) f("orange"); 

Exemplo bobo e mensagem de erro ruim à parte, FruitEater e ColorConsumer s devem poder pegar a string "orange" e retornar um number ou uma string .


No TypeScript 3.3, isso não é mais um erro.


 type Fruit = "apple" | "orange"; type Color = "red" | "orange"; type FruitEater = (fruit: Fruit) => number; // eats and ranks the fruit type ColorConsumer = (color: Color) => string; // consumes and describes the colors declare let f: FruitEater | ColorConsumer; f("orange"); // It works! Returns a 'number | string'. f("apple"); // error - Argument of type '"apple"' is not assignable to parameter of type '"orange"'. f("red"); // error - Argument of type '"red"' is not assignable to parameter of type '"orange"'. 

No TypeScript 3.3, os parâmetros dessas assinaturas são cruzados para criar uma nova assinatura. No exemplo acima, os parâmetros fruit e color são cruzados para um novo parâmetro do tipo Fruit & Color . Fruit & Color é realmente o mesmo que ("apple" | "orange") & ("red" | "orange") que é equivalente a ("apple" & "red") | ("apple" & "orange") | ("orange" & "red") | ("orange" & "orange") ("apple" & "red") | ("apple" & "orange") | ("orange" & "red") | ("orange" & "orange") ("apple" & "red") | ("apple" & "orange") | ("orange" & "red") | ("orange" & "orange") . Cada uma dessas interseções impossíveis evapora, e ficamos com "orange" & "orange" que são apenas "orange" .


Ainda existem algumas restrições. Esse novo comportamento só entra em ação quando no máximo um tipo na união tem várias sobrecargas e no máximo um tipo na união possui uma assinatura genérica. Isso significa métodos no number[] | string[] number[] | string[] como o map (que é genérico) ainda não poderá ser chamado.


Por outro lado, métodos como o forEach agora podem ser noImplicitAny , mas sob noImplicitAny , pode haver alguns problemas.


 interface Dog { kind: "pupper" dogProp: any; } interface Cat { kind: "kittyface" catProp: any; } const catOrDogArray: Dog[] | Cat[] = []; catOrDogArray.forEach(animal => { // ~~~~~~ error! // Parameter 'animal' implicitly has an 'any' type. }); 

Embora continuemos a melhorar a experiência aqui, isso é estritamente mais capaz no TypeScript 3.3, e a adição de uma anotação de tipo explícita funcionará.


 interface Dog { kind: "pupper" dogProp: any; } interface Cat { kind: "kittyface" catProp: any; } const catOrDogArray: Dog[] | Cat[] = []; catOrDogArray.forEach((animal: Dog | Cat) => { if (animal.kind === "pupper") { animal.dogProp; // ... } else if (animal.kind === "kittyface") { animal.catProp; // ... } }); 

Observação incremental de arquivos para projetos compostos em --build --watch


No TypeScript 3.0, introduzimos um novo recurso para estruturar builds chamado "projetos compostos". Parte do objetivo aqui era garantir que os usuários pudessem dividir grandes projetos em partes menores, construídas rapidamente e preservando a estrutura do projeto, sem comprometer a experiência TypeScript existente. Graças a projetos compostos, o TypeScript pode usar o modo --build para recompilar apenas o conjunto de projetos e dependências. Você pode pensar nisso como otimizar as compilações entre projetos.


No entanto, por volta do ano passado, nossa equipe também distribuiu --watch otimizadas do modo --watch por meio de uma nova API incremental de "construtores". Da mesma forma, a idéia inteira é que esse modo verifique e reemita apenas arquivos alterados ou arquivos cujas dependências possam afetar a verificação de tipo. Você pode pensar nisso como otimizar as compilações intraprojeto.


Talvez, ironicamente, a construção de projetos compostos usando --build --watch na verdade não utilizasse essa infraestrutura. Uma atualização em um projeto no modo --build --watch forçaria uma compilação completa desse projeto, em vez de determinar quais arquivos nesse projeto foram afetados.


No TypeScript 3.3, o sinalizador --watch do modo --build também aproveita a --watch incremental de arquivos. Isso pode significar construções significativamente mais rápidas em --build --watch . Em nossos testes, essa funcionalidade resultou em uma redução de 50% a 75% nos tempos de construção dos tempos originais --build --watch . Você pode ler mais sobre a solicitação de recebimento original da alteração para ver números específicos, mas acreditamos que a maioria dos usuários compostos do projeto verá ganhos significativos aqui.


O que vem a seguir?


Além do 3.3, você pode ficar de olho em nossa página do Roteiro para qualquer trabalho futuro.


Mas, no momento, estamos ansiosos para ouvir sobre sua experiência com o RC, então experimente agora e deixe-nos saber seus pensamentos!


- Daniel Rosenwasser e a equipe TypeScript

Source: https://habr.com/ru/post/pt437652/


All Articles