Introduccion a Typescript
Conceptos básicos
Typescript es una extensión de Javascript que añade tipos estáticos opcionales al lenguaje.
Partiendo de esta definición, es importante destacar que no viene por defecto en la instalación de cualquier runtime de JS, como NodeJS, y es necesario instalarlo por separado.
Las ventajas de usar Typescript (TS), principalmente, son que nos permite detectar errores en el código mientras desarrollamos o transformamos de TS a JS (compilación con TSC), volviendo más eficiente el proceso de desarrollo y haciendo más robusto el código que programemos.
Cuando programamos en TS podemos usar código JS. Como mencioné anteriormente, todo código de TS necesita ser convertido a JS para que pueda ser ejecutado. La herramienta que se encarga de llevar a cabo este proceso es el compilador de tyepscript (TSC).
Principales características
- Uso de interfaces y tipos de datos,
- Desarrollo orientado a objetos (OOP): TypeScript mejora el soporte para la programación orientada a objetos en JavaScript, con características como clases, herencia, y modificadores de acceso.
Instalación
Para instalar Typescript se recomienda hacerlo dentro del entorno de NodeJS y utilizar cualquier gestor de paquetes compatible, tales como NPM o YARN.
Una vez cumpliendo los requerimientos previos, podemos ejecutar los siguientes comandos para inicializar un nuevo proyecto
yarn init
// Nos pedirá la siguiente información
// yarn init v1.22.10
// question name (typescript): TypeScriptTest
// question version (1.0.0):
// question description: Post
// question entry point (index.js):
// question repository url:
// question author: Diego
// question license (MIT):
// question private:
// success Saved package.json
// ✨ Done in 106.84s.
yarn add typescript
Inicializar la configuración de Typescript
npx tsc --init --rootdir src --outdir dist
Ahora podemos crear un nuevo archivo llamado index.ts
dentro de la carpeta src
y ejecutemos en la terminal el siguiente comando para que esté compilando el código mientras programamos:
npx tsc --watch
Usando el editor de tu preferencia (se recomienda VSCode) podemos empezar a escribir código TS
let message: string = "testing my first TS code";
console.log(message);
"use strict";
let message = "testing my first TS code";
console.log(message);
Declarando variables
En TypeScript, las variables se pueden declarar de varias formas, utilizando let, const o var, junto con anotaciones de tipo opcionales.
1. Declaración básica sin tipo explícito
TypeScript puede inferir el tipo automáticamente:
let mensaje = "Hola mundo"; // TypeScript infiere que es string
let edad = 25; // TypeScript infiere que es number
2. Declaración con anotaciones de tipo
Podemos especificar el tipo explícitamente:
let nombre: string = "Juan";
let activo: boolean = true;
let precio: number = 19.99;
3. Tipos de datos en TypeScript
Tipos primitivos
let texto: string = "Hola";
let entero: number = 42;
let decimal: number = 3.14;
let esValido: boolean = false;
Arreglos
let numeros: number[] = [1, 2, 3, 4];
let palabras: string[] = ["uno", "dos", "tres"];
// O Array<T>
let valores: Array<number> = [10, 20, 30];
Tuplas (arrays con tipos fijos)
let tupla: [string, number] = ["Edad", 30];
Uso de any
(permite cualquier tipo, pero se recomienda evitarlo)
let variable: any = 5;
variable = "Ahora soy un string"; // No hay error
Uso de unknown
let desconocido: unknown = "Hola";
desconocido = 42; // No hay error, pero no se puede usar sin verificación de tipo
// Para usarlo, hay que hacer una comprobación de tipo:
if (typeof desconocido === "string") {
console.log(desconocido.toUpperCase());
}
Tipos avanzados
- Unión de tipos
|
let identificador: string | number;
identificador = "ABC123";
identificador = 123; // Ambas asignaciones son válidas
- Literales (valores fijos)
let estado: "activo" | "inactivo";
estado = "activo"; // ✅ Válido
estado = "inactivo"; // ✅ Válido
estado = "pendiente"; // ❌ Error
- Objetos con tipos
let usuario: { nombre: string, edad: number } = {
nombre: "Carlos",
edad: 25,
};
Funciones
En la siguiente funcion se especifica la funcion sumar, toma dos argumentos del tipo number y, despues de los dos puntos se especifica el tipo de dato que regresará,
function sumar(x: number, y: number): number {}
Clases
class Animal {
private name: string;
constructor(name) {
this.name = name;
}
move(distanceInMeters: number): void {
console.log(`${this.name} moved ${distanceinMeters}`);
}
}
Generics
En TypeScript, los Generics son una característica que permite crear componentes (como funciones, clases o interfaces) que pueden trabajar con diferentes tipos de datos, pero de manera segura, sin perder la información sobre el tipo con el que se está trabajando.
La idea principal de los generics es permitir que una función o clase sea reutilizable para diferentes tipos de datos sin tener que escribir múltiples versiones para cada tipo específico.
¿Cómo funcionan?
En lugar de especificar un tipo concreto para los parámetros o valores de retorno, se utiliza un tipo genérico, que es un marcador de posición que se define cuando se llama o se instancia el componente. De esta manera, el tipo se determinará dinámicamente en el momento de la ejecución.
Sintaxis básica
La sintaxis para declarar un tipo genérico es utilizando el símbolo de corchetes angulares (< >), seguido de un parámetro de tipo, que usualmente se representa con una letra como T, U, K, etc.
class Queue<T> {
data = [];
insert(item: T) {
this.data.unshift(item);
}
take(): T {
return this.data.pop();
}
}
let valores = [1, 2, 3, 4, 5, 6];
const queue = new Queue<number>();
valores.forEach((element) => {
queue.insert(element);
});
console.log(queue.take());
console.log(queue.take());
console.log(queue.take());
console.log(queue);
NodeJS y Express en Typescript
En TypeScript, cuando trabajas con Node.js y Express, necesitas tener acceso a las definiciones de tipos para que el compilador pueda entender las funciones, objetos y módulos específicos de estas tecnologías. Para lograr esto, se utilizan los tipos (types) que son paquetes adicionales que contienen definiciones de tipos que TypeScript puede usar para hacer su trabajo.
1- install types/node para acceder a los elementos integrados de Node.js
Cuando usas Node.js en un proyecto TypeScript, necesitas las definiciones de tipos para poder trabajar con las funcionalidades que Node.js ofrece, como fs (sistema de archivos), http, path, entre otros módulos internos. Esas funcionalidades no se conocen automáticamente en TypeScript a menos que se instalen los tipos de Node.js.
Cómo instalar los tipos de Node.js:
npm install —save-dev @types/node
- @types/node es el paquete que contiene las definiciones de tipos para Node.js.
- Se instala como una dependencia de desarrollo (—save-dev) porque solo es necesario durante el tiempo de desarrollo para que TypeScript entienda los tipos, pero no es necesario en tiempo de ejecución.
Con esta instalación, TypeScript sabrá cómo trabajar con las APIs de Node.js, y podrás hacer uso de módulos como fs, http, path, entre otros, con la correcta verificación de tipos.
Ejemplo:
import * as fs from ‘fs’;
fs.readFile(‘archivo.txt’, ‘utf-8’, (err, data) => {
if (err) {
console.error(‘Error al leer el archivo:’, err);
return;
}
console.log(‘Contenido del archivo:’, data);
});
2- install types/express para usar Express
Cuando trabajas con Express (un framework para Node.js) en TypeScript, también necesitas las definiciones de tipos para acceder a las características de Express de manera segura y con autocompletado en tu editor.
Cómo instalar los tipos de Express:
npm install —save-dev @types/express
- @types/express es el paquete que contiene las definiciones de tipos para Express.
- También se instala como una dependencia de desarrollo (—save-dev), ya que TypeScript necesita esta información solo durante la compilación.
Con esta instalación, TypeScript podrá reconocer y tipar correctamente las funciones y objetos de Express, como Request, Response, NextFunction, y otros.
Ejemplo:
import express, { Request, Response } from ‘express’;
const app = express();
app.get(‘/‘, (req: Request, res: Response) => {
res.send(‘¡Hola, mundo!’);
});
app.listen(3000, () => {
console.log(‘Servidor en el puerto 3000’);
});
Aquí, Request y Response son los tipos proporcionados por @types/express para los objetos req y res que Express pasa a las funciones de manejo de rutas. TypeScript usará estos tipos para asegurarse de que estás accediendo a las propiedades correctas y de manera segura.
Ambos paquetes son esenciales cuando trabajas con TypeScript en un entorno Node.js + Express, ya que proporcionan la información de tipos necesaria para un desarrollo más eficiente y libre de errores.
Async Await
En JavaScript, async y await son herramientas que facilitan el manejo de código asíncrono. La palabra clave async se utiliza para declarar una función que siempre devolverá una promesa, mientras que await se usa dentro de estas funciones para esperar la resolución de una promesa antes de continuar con la ejecución del código.
Lo que significa “runs on the top of Promise” es que async y await están construidos sobre las promesas. Cuando usas await, le estás diciendo a JavaScript que espere (de manera no bloqueante) hasta que una promesa se resuelva (o se rechace), y solo entonces continuará con la ejecución de la función.
Por lo tanto, async y await hacen que el manejo de promesas sea más fácil y legible, pero en el fondo, siguen utilizando promesas para gestionar la asincronía.
const delay = (ms: number) => new Promise((res) => setTimeout(res, ms));
const mainAsync = async () => {
await delay(1000);
console.log("1s");
};