Capítulo 1. De JavaScript a TypeScript

Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com

JavaScript hoy

Compatible con navegadores de hace décadas

La belleza de la web

Antes de hablar de TypeScript, tenemos que entender de dónde viene: ¡de JavaScript!

Historia de JavaScript

JavaScript fue diseñado en 10 días por Brendan Eich en Netscape en 1995 para que fuera accesible y fácil de usar en los sitios web. Desde entonces, los desarrolladores se han burlado de sus peculiaridades y deficiencias percibidas. En la siguiente sección trataré algunas de ellas.

Sin embargo, JavaScript ha evolucionado enormemente desde 1995. Su comité directivo, TC39, ha publicado nuevas versiones de ECMAScript -la especificación del lenguaje en la que se basa JavaScript- cada año desde 2015, con nuevas características que lo equiparan a otros lenguajes modernos. Es impresionante que, incluso con las nuevas versiones periódicas del lenguaje, JavaScript haya conseguido mantener la compatibilidad con versiones anteriores durante décadas en distintos entornos, como navegadores, aplicaciones integradas y tiempos de ejecución de servidor.

Hoy en día, JavaScript es un lenguaje maravillosamente flexible con muchos puntos fuertes. Hay que apreciar que, aunque JavaScript tiene sus peculiaridades, también ha contribuido a permitir el increíble crecimiento de las aplicaciones web y de Internet.

Muéstrame el lenguaje de programación perfecto y te mostraré un lenguaje sin usuarios.

Anders Hejlsberg, TSConf 2019

Las trampas de Vanilla JavaScript

Los desarrolladores a menudo se refieren al uso de JavaScript sin ninguna extensión significativa del lenguaje o marcos de trabajo como "vainilla": refiriéndose a que es el sabor familiar y original. Pronto explicaré por qué TypeScript añade justo el sabor adecuado para superar estos grandes escollos particulares, pero es útil entender por qué pueden ser dolorosos. Todas estas debilidades se vuelven más pronunciadas cuanto más grande y duradero es un proyecto.

Libertad costosa

La mayor queja de muchos desarrolladores de con JavaScript es, por desgracia, una de sus características clave: JavaScript no impone prácticamente ninguna restricción en la forma de estructurar el código. ¡Esa libertad hace que sea muy divertido empezar un proyecto en JavaScript!

Sin embargo, a medida que vas teniendo más y más archivos, se hace evidente cómo esa libertad puede ser perjudicial. Toma el siguiente fragmento, presentado fuera de contexto de alguna aplicación ficticia de pintura:

function paintPainting(painter, painting) {
  return painter
    .prepare()
    .paint(painting, painter.ownMaterials)
    .finish();
}

Leyendo ese código sin ningún contexto, sólo puedes tener vagas ideas sobre cómo llamar a la función paintPainting. Tal vez, si has trabajado en la base de código circundante, recuerdes que painter debería ser lo devuelto por alguna función getPainter. Incluso podrías hacer una suposición afortunada de que painting es una cadena.

Pero aunque esas suposiciones sean correctas, cambios posteriores en el código pueden invalidarlas. Quizá se cambie painting de cadena a otro tipo de datos, o quizá se cambie el nombre de uno o varios métodos del pintor.

Otros lenguajes pueden negarse a ejecutar código si su compilador determina que es probable que se bloquee, pero no ocurre lo mismo con los lenguajes de tipado dinámico, que ejecutan código sin comprobar primero si es probable que se bloquee, como JavaScript.

La libertad de código que hace que JavaScript sea tan divertido se convierte en una verdadera molestia cuando quieres seguridad al ejecutar tu código.

Documentación suelta

No existe nada en en la especificación del lenguaje JavaScript para formalizar la descripción de lo que deben ser los parámetros de las funciones, los retornos de las funciones, las variables u otras construcciones del código. Muchos desarrolladores han adoptado un estándar llamado JSDoc para describir funciones y variables mediante comentarios en bloque. El estándar JSDoc describe cómo se pueden escribir comentarios de documentación colocados directamente encima de construcciones como funciones y variables, con un formato estándar. He aquí un ejemplo, de nuevo sacado de contexto:

/**
 * Performs a painter painting a particular painting.
 *
 * @param {Painter} painter
 * @param {string} painting
 * @returns {boolean} Whether the painter painted the painting.
 */
function paintPainting(painter, painting) { /* ... */ }

JSDoc tiene problemas clave que a menudo hacen que no sea agradable utilizarlo en una gran base de código:

  • Nada impide que las descripciones JSDoc se equivoquen de código.

  • Incluso si tus descripciones JSDoc eran correctas anteriormente, durante la refactorización del código puede ser difícil encontrar todos los comentarios JSDoc ahora inválidos relacionados con tus cambios.

  • La descripción de objetos complejos es pesada y prolija, y requiere varios comentarios independientes para definir los tipos y sus relaciones.

Mantener los comentarios de JSDoc en una docena de archivos no lleva demasiado tiempo, pero en cientos o incluso miles de archivos que se actualizan constantemente puede ser una verdadera faena.

Herramientas de desarrollo más débiles

Dado que JavaScript no proporciona formas integradas de identificar tipos, y el código se desvía fácilmente de los comentarios de JSDoc, puede resultar difícil automatizar grandes cambios u obtener información sobre una base de código. Los desarrolladores de JavaScript a menudo se sorprenden al ver funciones en lenguajes tipados como C# y Java que permiten a los desarrolladores realizar renombramientos de miembros de clases o saltar al lugar donde se declaró el tipo de un argumento.

Nota

Puede que protestes porque los IDE modernos, como VS Code, proporcionan algunas herramientas de desarrollo, como refactorizaciones automatizadas de JavaScript. Cierto, pero: utilizan TypeScript o un equivalente bajo el capó para muchas de sus funciones de JavaScript, y esas herramientas de desarrollo no son tan fiables ni tan potentes en la mayoría del código JavaScript como lo son en el código TypeScript bien definido.

¡TypeScript!

TypeScript se creó internamente en Microsoft a principios de la década de 2010 y luego se publicó y se hizo de código abierto en 2012. El jefe de su desarrollo es Anders Hejlsberg, notable por haber dirigido también el desarrollo de los populares lenguajes C# y Turbo Pascal. TypeScript se describe a menudo como un "superconjunto de JavaScript" o "JavaScript con tipos". Pero, ¿qué es TypeScript?

TypeScript son cuatro cosas:

Lenguaje de programación

Un lenguaje que incluye toda la sintaxis existente de JavaScript, además de una nueva sintaxis específica de TypeScript para definir y utilizar tipos

Verificador de tipos

Un programa de que toma un conjunto de archivos escritos en JavaScript y/o TypeScript, desarrolla una comprensión de todas las construcciones (variables, funciones...) creadas, y te avisa si cree que algo está configurado incorrectamente.

Compilador

Un programa que ejecuta el comprobador de tipos, informa de cualquier problema y, a continuación, genera el código JavaScript equivalente.

Servicio lingüístico

Un programa de que utiliza el comprobador de tipos para indicar a editores como VS Code cómo proporcionar utilidades útiles a los desarrolladores

Primeros pasos en el patio de recreo de TypeScript

Ya has leído bastante sobre TypeScript en. ¡Vamos a escribirlo!

El sitio web principal de TypeScript incluye un editor "Playground" en https://www.typescriptlang.org/play. Puedes escribir código en el editor principal y ver muchas de las mismas sugerencias del editor que verías al trabajar con TypeScript localmente en un IDE (Entorno de Desarrollo Integrado) completo.

La mayoría de los fragmentos de este libro son intencionadamente pequeños y lo suficientemente autónomos como para que puedas teclearlos en el Playground y juguetear con ellos por diversión.

TypeScript en acción

Echa un vistazo a este fragmento de código en :

const firstName = "Georgia";
const nameLength = firstName.length();
//                           ~~~~~~
// This expression is not callable.

El código está escrito en sintaxis JavaScript normal -todavía no he introducido la sintaxis específica de TypeScript-. Si ejecutaras el comprobador de tipos de TypeScript en este código, utilizaría su conocimiento de que la propiedad length de una cadena es un número -no una función- para darte la queja que se muestra en el comentario.

Si pegaras ese código en el campo de juego o en un editor, el servicio lingüístico te diría que apareciera un pequeño garabato rojo bajo length indicando el disgusto de TypeScript con tu código. Si pasaras el ratón por encima del código garabateado, obtendrías el texto de la queja(Figura 1-1).

TypeScript reporting the 'length' property of a firstName string is not callable.
Figura 1-1. TypeScript informa de un error sobre la longitud de la cadena que no se puede llamar

Que te avisen de estos sencillos errores en tu editor mientras los escribes es mucho más agradable que esperar a que se ejecute una determinada línea de código y arroje un error. Si intentaras ejecutar ese código en JavaScript, ¡se bloquearía !

Libertad mediante la restricción

TypeScript nos permite especificar qué tipos de valores se pueden proporcionar para parámetros y variables. Algunos desarrolladores consideran que tener que escribir explícitamente en tu código cómo se supone que funcionan determinadas áreas es restrictivo al principio.

Pero yo diría que estar "restringido" de esta forma es en realidad algo bueno. Al restringir nuestro código para que sólo pueda utilizarse de las formas que especifiques, TypeScript puede darte la seguridad de que los cambios en un área de código no romperán otras áreas de código que lo utilicen.

Si, por ejemplo, cambias el número de parámetros necesarios para una función, TypeScript te avisará si olvidas actualizar un lugar que llame a la función.

En el siguiente ejemplo, sayMyName ha pasado de recibir dos parámetros a recibir un parámetro, pero la llamada a este parámetro con dos cadenas no se ha actualizado, por lo que está provocando una queja de TypeScript:

// Previously: sayMyName(firstName, lastName) { ...
function sayMyName(fullName) {
  console.log(`You acting kind of shady, ain't callin' me ${fullName}`);
}

sayMyName("Beyoncé", "Knowles");
//                   ~~~~~~~~~
// Expected 1 argument, but got 2.

Ese código se ejecutaría sin fallar en JavaScript, pero su salida sería diferente de la esperada (no incluiría "Knowles"):

You acting kind of shady, ain't callin' me Beyoncé

Llamar a funciones con un número incorrecto de argumentos es exactamente el tipo de libertad miope de JavaScript que TypeScript restringe.

Documentación precisa

Veamos en una versión adaptada a TypeScript de la función paintPainting de antes. Aunque todavía no he repasado los detalles de la sintaxis de TypeScript para documentar tipos, el siguiente fragmento de código da una idea de la gran precisión con la que TypeScript puede documentar código:

interface Painter {
  finish(): boolean;
  ownMaterials: Material[];
  paint(painting: string, materials: Material[]): boolean;
}

function paintPainting(painter: Painter, painting: string): boolean { /* ... */ }

Un desarrollador de TypeScript que leyera este código por primera vez podría entender que painter tiene al menos tres propiedades, dos de las cuales son métodos. Al incorporar sintaxis para describir las "formas" de los objetos, TypeScript proporciona un excelente sistema reforzado para describir el aspecto de los objetos.

Herramientas de desarrollo más potentes

Las tipografías de TypeScript permiten a editores como VS Code obtener una visión mucho más profunda de tu código y utilizarla para mostrarte sugerencias inteligentes mientras escribes. Estas sugerencias pueden ser increíblemente útiles para el desarrollo.

Si ya has utilizado VS Code para escribir JavaScript, te habrás dado cuenta de que te sugiere "autocompletados" cuando escribes código con tipos de objetos incorporados, como las cadenas. Si, por ejemplo, empiezas a escribir el miembro de algo que se sabe que es una cadena, TypeScript puede sugerirte todos los miembros de las cadenas(Figura 1-2).

TypeScript suggesting a dropdown of properties starting with 'se' as members of a string.
Figura 1-2. TypeScript proporciona sugerencias de autocompletado en JavaScript para una cadena

Cuando añades el comprobador de tipos de TypeScript para comprender el código, puede darte estas útiles sugerencias incluso para el código que has escrito. Al escribir painter. en la función paintPainting, TypeScript tomaría su conocimiento de que el parámetro painter es del tipo Painter y el tipo Painter tiene los siguientes miembros(Figura 1-3).

TypeScript suggesting a dropdown of properties starting with 'se' as members of a string.
Figura 1-3. TypeScript proporciona sugerencias de autocompletado en JavaScript para una cadena

Snazzy! Cubriré una plétora de otras funciones útiles del editor en el Capítulo 12, "Uso de las funciones del IDE".

Sintaxis de compilación

El compilador de TypeScript nos permite introducir la sintaxis de TypeScript, hacer que se compruebe su tipo y obtener el equivalente de JavaScript emitido. Por comodidad, el compilador también puede tomar la sintaxis moderna de JavaScript y compilarla en sus equivalentes más antiguos de ECMAScript.

Si pegaras este código TypeScript en el Playground:

const artist = "Augusta Savage";
console.log({ artist });

El Playground te mostraría en la parte derecha de la pantalla que ésta sería la salida equivalente de JavaScript por el compilador(Figura 1-4).

TypeScript Playground compiling TypeScript code into equivalent JavaScript.
Figura 1-4. TypeScript Playground compilando código TypeScript en JavaScript equivalente

TypeScript Playground es una gran herramienta para mostrar cómo TypeScript de origen se convierte en JavaScript de salida.

Nota

Muchos proyectos de JavaScript utilizan transpiladores dedicados, como Babel(https://babeljs.io), en lugar del propio de TypeScript para transpilar el código fuente a JavaScript ejecutable. Puedes encontrar una lista de los iniciadores de proyectos más comunes en https://learningtypescript.com/starters.

Empezar localmente

En puedes ejecutar TypeScript en tu ordenador siempre que tengas instalado Node.js. Para instalar la última versión de TypeScript de forma global, ejecuta el siguiente comando:

npm i -g typescript

Ahora, podrás ejecutar TypeScript en la línea de comandos con el comando tsc ( Compilador deTypeScript). Pruébalo con la bandera --version para asegurarte de que está configurado correctamente:

tsc --version

Debería imprimir algo como Version X.Y.Z-cualquiera que sea la versión actual en el momento de instalar TypeScript:

$ tsc --version
Version 4.7.2

Correr localmente

Ahora que TypeScript está instalado, vamos a configurar una carpeta localmente para ejecutar TypeScript en código. Crea una carpeta en algún lugar de tu ordenador y ejecuta este comando para crear un nuevo archivo de configuración tsconfig.json:

tsc --init

Un archivo tsconfig. json declara la configuración que TypeScript utiliza al analizar tu código. La mayoría de las opciones de ese archivo no van a ser relevantes para ti en este libro (¡hay muchos casos de perímetro poco comunes en la programación que el lenguaje debe tener en cuenta! Los trataré en el Capítulo 13, "Opciones de configuración". Lo importante es que ahora puedes ejecutar tsc para decirle a TypeScript que compile todos los archivos de esa carpeta y TypeScript hará referencia a ese tsconfig.json para cualquier opción de configuración.

Prueba a añadir un archivo llamado index.ts con el siguiente contenido:

console.blub("Nothing is worth more than laughter.");

A continuación, ejecuta tsc y proporciónale el nombre de ese archivo index.ts:

tsc index.ts

Deberías obtener un error parecido a:

index.ts:1:9 - error TS2339: Property 'blub' does not exist on type 'Console'.

1 console.blub("Nothing is worth more than laughter.");
          ~~~~

Found 1 error.

Efectivamente, blub no existe en console. ¿En qué estaba pensando?

Antes de que arregles el código para apaciguar a TypeScript, ten en cuenta que tsc ha creado un index.js para ti con contenidos que incluyen el console.blub.

Nota

Este es un concepto importante: aunque hubiera un error de tipo en nuestro código, la sintaxis seguía siendo completamente válida. El compilador de TypeScript seguirá produciendo JavaScript a partir de un archivo de entrada, independientemente de cualquier error de tipo.

Corrige el código en index.ts para llamar a console.log y vuelve a ejecutar tsc. No debería haber ninguna queja en tu terminal, y el archivo index.js debería contener ahora el código de salida actualizado:

console.log("Nothing is worth more than laughter.");
Consejo

Te recomiendo encarecidamente que juegues con los fragmentos del libro mientras los lees, ya sea en el campo de juego o en un editor compatible con TypeScript, es decir, que ejecute el servicio del lenguaje TypeScript por ti. También hay disponibles pequeños ejercicios autocontenidos, así como proyectos más grandes, para ayudarte a practicar lo que has aprendido enhttps://learningtypescript.com.

Funciones del editor

Otro beneficio de al crear un archivo tsconfig.json es que cuando los editores se abren en una carpeta determinada, ahora reconocerán esa carpeta como un proyecto TypeScript. Por ejemplo, si abres VS Code en una carpeta, la configuración que utiliza para analizar tu código TypeScript respetará lo que haya en el tsconfig.json de esa carpeta.

Como ejercicio, repasa los fragmentos de código de este capítulo y escríbelos en tu editor. Deberías ver desplegables que te sugieran terminaciones para los nombres a medida que los escribes, especialmente para miembros como el log en console.

Muy emocionante: ¡estás utilizando el servicio de lenguaje TypeScript para ayudarte a escribir código! Estás en camino de ser un desarrollador TypeScript!

Consejo

VS Code viene con una gran compatibilidad con TypeScript y está construido en TypeScript. No tienes por qué utilizarlo para TypeScript -casi todos los editores modernos tienen una excelente compatibilidad con TypeScript, ya sea incorporada o disponible a través de plugins-, pero te lo recomiendo al menos para probar TypeScript mientras lees este libro. Si utilizas un editor diferente, también te recomiendo que habilites su compatibilidad con TypeScript. Trataré las características del editor más a fondo en el Capítulo 12, "Uso de las características del IDE".

Qué no es TypeScript

Ahora que has visto lo maravilloso que es TypeScript, tengo que advertirte de algunas limitaciones. Cada herramienta destaca en algunas áreas y tiene limitaciones en otras.

Un remedio para el código defectuoso

TypeScript te ayuda a estructurar tu JavaScript, pero aparte de imponer la seguridad de tipos, no impone ninguna opinión sobre cómo debe ser esa estructura.

¡Bien!

TypeScript es un lenguaje que todo el mundo debe poder utilizar, no un marco de trabajo con un público objetivo. Puedes escribir código utilizando cualquier patrón arquitectónico al que estés acostumbrado de JavaScript, y TypeScript lo soportará.

Si alguien trata de decirte que TypeScript te obliga a usar clases, o que hace difícil escribir buen código, o cualquier otra queja de estilo de código que haya por ahí, échale una mirada severa y dile que coja una copia de Learning TypeScript. TypeScript no impone opiniones de estilo de código tales como si usar clases o funciones, ni está asociado con ningún marco de aplicación en particular -Angular, React, etc.- sobre otros.

Extensiones de JavaScript (en su mayoría)

Los objetivos de diseño de TypeScript en lo establecen explícitamente:

  • Alinearse con las propuestas actuales y futuras de ECMAScript

  • Preservar el comportamiento en tiempo de ejecución de todo el código JavaScript

TypeScript no intenta cambiar en absoluto el funcionamiento de JavaScript. Sus creadores se han esforzado mucho por evitar añadir nuevas características de código que se añadan a JavaScript o entren en conflicto con él. Tal tarea es competencia del TC39, el comité técnico que trabaja en el propio ECMAScript.

Hay algunas funciones antiguas en TypeScript que se añadieron hace muchos años para reflejar casos de uso comunes en el código JavaScript. La mayoría de esas funciones son relativamente poco comunes o han caído en desuso, y sólo se tratan brevemente en el Capítulo 14, "Extensiones sintácticas". Recomiendo mantenerse alejado de ellas en la mayoría de los casos.

Nota

A partir de 2022, el TC39 está investigando la posibilidad de añadir una sintaxis para las anotaciones de tipo a JavaScript. Las últimas propuestas hacen que actúen como una forma de comentarios que no afectan al código en tiempo de ejecución y sólo se utilizan para sistemas en tiempo de desarrollo como TypeScript. Pasarán muchos años hasta que se añadan comentarios de tipo o algún equivalente a JavaScript, por lo que no se mencionarán en ningún otro lugar de este libro.

Más lento que JavaScript

A veces en Internet, puedes oír a algunos desarrolladores obstinados quejarse de que TypeScript es más lento que JavaScript en tiempo de ejecución. Esa afirmación es generalmente inexacta y engañosa. Los únicos cambios que TypeScript hace al código son si le pides que compile tu código a versiones anteriores de JavaScript para soportar entornos de tiempo de ejecución más antiguos, como Internet Explorer 11. Muchos frameworks de producción no utilizan el compilador de TypeScript en absoluto, sino que utilizan una herramienta independiente para la transpilación (la parte de la compilación que convierte el código fuente de un lenguaje de programación a otro) y TypeScript sólo para la comprobación de tipos.

El código TypeScript debe ser compilado a JavaScript antes de que la mayoría de los entornos, como los navegadores y Node.js, puedan ejecutarlo. La mayoría de los procesos de compilación están generalmente configurados para que el impacto en el rendimiento sea insignificante, y las funciones más lentas de TypeScript, como el análisis del código en busca de posibles errores, se realizan por separado de la generación de archivos de código de aplicación ejecutables.

Nota

Incluso los proyectos que aparentemente permiten ejecutar código TypeScript directamente, como ts-node y Deno, convierten ellos mismos internamente el código TypeScript a JavaScript antes de ejecutarlo.

Terminado de evolucionar

La web no está ni cerca de terminar de evolucionar, y por lo tanto tampoco lo está TypeScript. El lenguaje TypeScript recibe constantemente correcciones de errores y adiciones de características para adaptarse a las necesidades siempre cambiantes de la comunidad web. Los principios básicos de TypeScript que aprenderás en este libro seguirán siendo más o menos los mismos, pero los mensajes de error, las características más sofisticadas y las integraciones del editor mejorarán con el tiempo.

De hecho, aunque esta edición del libro se publicó con la versión 4.7.2 de TypeScript como la más reciente, en el momento en que empezaste a leerlo, podemos estar seguros de que ya se ha publicado una versión más reciente. Incluso es posible que algunos de los mensajes de error de TypeScript que aparecen en este libro ya estén ¡ desactualizados!

Resumen

En este capítulo, conocerás el contexto de algunas de las principales debilidades de JavaScript, dónde entra en juego TypeScript y cómo empezar a utilizar TypeScript:

  • Breve historia de JavaScript

  • Los escollos de JavaScript: libertad costosa, documentación laxa y herramientas para desarrolladores más débiles

  • Qué es TypeScript: un lenguaje de programación, un comprobador de tipos, un compilador y un servicio de lenguaje

  • Ventajas de TypeScript: libertad mediante restricciones, documentación precisa y herramientas de desarrollo más sólidas

  • Cómo empezar a escribir código TypeScript en TypeScript Playground y localmente en tu ordenador

  • Lo que TypeScript no es: un remedio para el código defectuoso, extensiones de JavaScript (en su mayoría), más lento que JavaScript o terminado de evolucionar

Consejo

Ahora que has terminado de leer este capítulo, practica lo que has aprendido en https://learningtypescript.com/from-javascript-to-typescript.

¿Qué ocurre si detectas errores al ejecutar el compilador de TypeScript?

Será mejor que vayas a catch.

Get Aprender TypeScript now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.