Anuncio de TypeScript 3.3 RC

Hoy nos complace anunciar la disponibilidad de nuestro candidato de versión (RC) de TypeScript 3.3. Nuestra esperanza es recopilar comentarios y problemas iniciales para garantizar que nuestro lanzamiento final sea fácil de recoger y usar de inmediato.

Original en blog

Para comenzar a usar el RC, puede obtenerlo a través de NuGet o usar npm con el siguiente comando:


npm install -g typescript@rc 

También puede obtener soporte del editor por



TypeScript 3.3 debería ser una versión fácil de adoptar y no contiene cambios importantes. Exploremos las novedades en 3.3.


Comportamiento mejorado para llamar a tipos de unión


Cuando TypeScript tiene una unión tipo A | B A | B , le permite acceder a todas las propiedades comunes a A y B (es decir, la intersección de miembros).


 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`. 

Este comportamiento debe parecer intuitivo: solo puede obtener una propiedad de un tipo de unión si se sabe que está en cada tipo de unión.


¿Qué pasa, en lugar de acceder a las propiedades, estamos tratando con tipos de llamadas? Bueno, cuando cada tipo tiene exactamente una firma con parámetros idénticos, las cosas simplemente funcionan y puede llamar a estos 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'. 

Sin embargo, esta restricción fue a veces, bueno, demasiado restrictiva.


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

Dejando a un lado el ejemplo tonto y el mensaje de error deficiente, tanto FruitEater como ColorConsumer deberían poder tomar la cadena "orange" y devolver un number o una string .


En TypeScript 3.3, esto ya no es un error.


 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"'. 

En TypeScript 3.3, los parámetros de estas firmas se cruzan para crear una nueva firma. En el ejemplo anterior, los parámetros fruit y color se cruzan entre sí con un nuevo parámetro de tipo Fruit & Color . Fruit & Color es realmente lo mismo que ("apple" | "orange") & ("red" | "orange") que es 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 una de esas intersecciones imposibles se evapora, y nos queda con "orange" & "orange" que es simplemente "orange" .


Sin embargo, todavía hay algunas restricciones. Este nuevo comportamiento solo se activa cuando, como máximo, un tipo en la unión tiene múltiples sobrecargas, y como máximo un tipo en la unión tiene una firma genérica. Eso significa métodos en el number[] | string[] number[] | string[] como map (que es genérico) todavía no será invocable.


Por otro lado, los métodos como forEach ahora serán invocables, pero bajo noImplicitAny puede haber algunos 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. }); 

Si bien continuaremos mejorando la experiencia aquí, esto es estrictamente más capaz en TypeScript 3.3, y agregar una anotación de tipo explícito 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; // ... } }); 

--build --watch incremental de archivos para proyectos compuestos en --build --watch


En TypeScript 3.0, presentamos una nueva característica para estructurar compilaciones llamada "proyectos compuestos". Parte del objetivo aquí era garantizar que los usuarios pudieran dividir los proyectos grandes en partes más pequeñas que se construyen rápidamente y preservan la estructura del proyecto, sin comprometer la experiencia existente de TypeScript. Gracias a los proyectos compuestos, TypeScript puede usar el modo --build para recompilar solo el conjunto de proyectos y dependencias. Puede pensar en esto como la optimización de compilaciones entre proyectos.


Sin embargo, alrededor del año pasado, nuestro equipo también envió --watch optimizadas en modo de --watch través de una nueva API incremental de "constructor". En una línea similar, la idea es que este modo solo vuelve a verificar y vuelve a emitir archivos modificados o archivos cuyas dependencias pueden afectar la verificación de tipos. Puede pensar en esto como la optimización de las compilaciones dentro del proyecto.


Quizás, irónicamente, construir proyectos compuestos usando --build --watch realidad no usó esta infraestructura. Una actualización en un proyecto en el modo --build --watch forzaría una compilación completa de ese proyecto, en lugar de determinar qué archivos dentro de ese proyecto se vieron afectados.


En TypeScript 3.3, el --build modo de --watch aprovecha la observación incremental de archivos. Eso puede significar construcciones significativamente más rápidas en --build --watch . En nuestras pruebas, esta funcionalidad ha dado como resultado una reducción del 50% al 75% en los tiempos de construcción de los tiempos originales de --build --watch . Puede leer más sobre la solicitud de extracción original para el cambio para ver números específicos, pero creemos que la mayoría de los usuarios de proyectos compuestos verán ganancias significativas aquí.


Que sigue


Más allá de 3.3, puede estar atento a nuestra página de Hoja de ruta para cualquier trabajo futuro.


Pero en este momento esperamos escuchar su experiencia con el RC, ¡así que pruébelo ahora y díganos qué piensa!


- Daniel Rosenwasser y el equipo de TypeScript

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


All Articles