¿Qué es TypeScript? Guía completa del superset de JavaScript

¿Te ha pasado que después de horas debuggeando encuentras que el error era porque pasaste un string donde esperabas un number? A mí me pasó mil veces hasta que descubrí TypeScript. Te voy a contar por qué este "JavaScript con súper poderes" se convirtió en mi herramienta favorita y cómo puede cambiar tu forma de programar.
TypeScript: JavaScript que piensa antes de actuar
TypeScript es como tener un asistente súper inteligente que revisa tu código JavaScript y te dice "ey, creo que aquí hay un problema" antes de que tu app explote en producción. Es un superset desarrollado por Microsoft que le añade tipos estáticos opcionales a JavaScript.
Y ojo, cuando digo "superset" no estoy usando palabrería técnica fancy. Significa algo súper práctico: todo tu código JavaScript funciona perfectamente en TypeScript. Es como una actualización, no un reemplazo.
Lo que hace que TypeScript sea genial:
Lo más cool de TypeScript es su sistema de tipado estático. Puedes decirle exactamente qué tipo de datos espera una función - si son números, strings, objetos con propiedades específicas. Es como poner etiquetas claras en todo tu código.
Otra cosa increíble es que TypeScript se compila a JavaScript puro. Esto significa que cualquier lugar donde funcione JavaScript (navegadores, Node.js, etc.) también va a funcionar tu código TypeScript compilado. Zero drama de compatibilidad.
El ecosistema de herramientas mejorado es otro punto que me voló la mente. Tu editor se vuelve súper inteligente - autocompletado preciso, refactoring seguro, errores marcados en tiempo real. Es como tener un copiloto experto mientras programas.
Y por supuesto, TypeScript es completamente moderno. Soporta todas las características nuevas de JavaScript y ECMAScript, así que no te quedas atrás con la evolución del lenguaje.
La historia detrás del framework (y por qué me parece brillante)
¿Por qué Microsoft creó TypeScript?
En 2012, Microsoft estaba enfrentando los mismos problemas que todos hemos sufrido con JavaScript. Anders Hejlsberg (el mismo que creó C# y Delphi) lideró el proyecto para resolver estos dolores de cabeza.
El primer gran problema era esa falta de tipos estáticos que nos vuelve locos. ¿Cuántas veces has tenido un bug que solo aparece en producción porque asumiste que una variable era un array y resultó siendo null?
La escalabilidad se había vuelto un nightmare. Proyectos grandes de JavaScript se convertían en código imposible de entender y mantener. Sin tipos explícitos, era como navegar a ciegas.
Las herramientas de desarrollo también eran súper limitadas. Nada de autocompletado inteligente, refactoring era manual y propenso a errores. Una tortura comparado con lenguajes tipados.
Finalmente, la colaboración en equipos era caótica. Sin contratos claros entre diferentes partes del código, era súper difícil trabajar en equipo sin pisarse los pies constantemente.
El viaje hasta hoy:
Todo empezó en 2012 con TypeScript 0.8. Microsoft dijo "tenemos este experimento", y la verdad es que cambió el juego para siempre.
2014 fue el año clave con TypeScript 1.0 - la primera versión estable. Aquí es cuando la gente empezó a tomarlo en serio para proyectos reales.
En 2016, TypeScript 2.0 trajo tipos no-null y literales. Esto fue game-changing porque atacó una de las fuentes más comunes de bugs: los temidos null y undefined.
TypeScript 3.0 en 2018 introdujo tipos de proyecto y tuplas mejoradas. Ideal para proyectos súper complejos y monorepos gigantes.
La versión 4.0 de 2020 nos dio tuplas variadic y template literal types. Features súper avanzadas que permiten expresar patrones de tipos súper complejos.
Y 2023 trajo TypeScript 5.0 con decoradores estables y el operador satisfies. Por fin características que habían estado "casi listas" durante años se volvieron oficiales.
Por qué me enamoré de TypeScript
1. Caza errores como un ninja
// JavaScript - Error en tiempo de ejecución
function sumar(a, b) {
return a + b;
}
console.log(sumar(5, "10")); // "510" (concatenación inesperada)
// TypeScript - Error en tiempo de compilación
function sumar(a: number, b: number): number {
return a + b;
}
console.log(sumar(5, "10")); // Error: Argument of type 'string' is not assignable to parameter of type 'number'
2. Autocompletado que te lee la mente
interface Usuario {
id: number;
nombre: string;
email: string;
activo: boolean;
}
function procesarUsuario(usuario: Usuario) {
// El IDE conoce todas las propiedades disponibles
console.log(usuario.nombre); // Autocompletado perfecto
console.log(usuario.edad); // Error: Property 'edad' does not exist
}
3. Refactoring sin miedo
// Cambiar el nombre de una propiedad automáticamente
// actualiza todas las referencias en todo el proyecto
interface Producto {
id: number;
nombre: string; // Renombrar a 'titulo' actualiza todo
precio: number;
}
4. Documentación que no miente
// Los tipos sirven como documentación
function obtenerUsuarios(
filtros: {
activo?: boolean;
rol?: 'admin' | 'usuario' | 'invitado';
fechaCreacion?: Date;
}
): Promise<Usuario[]> {
// Implementación
}
5. Escalabilidad que sí funciona
// Contratos claros entre módulos
export interface APIResponse<T> {
data: T;
success: boolean;
message?: string;
errors?: string[];
}
export interface UsuarioService {
obtenerUsuario(id: number): Promise<APIResponse<Usuario>>;
crearUsuario(datos: Omit<Usuario, 'id'>): Promise<APIResponse<Usuario>>;
}
Lo que no me gusta tanto (seamos honestos)
1. La curva de aprendizaje puede ser empinada
Si vienes de JavaScript puro, TypeScript puede sentirse abrumador al principio. Hay conceptos nuevos que dominar: interfaces, tipos de unión, intersección, genéricos. Es como aprender un dialecto nuevo de un idioma que ya conoces.
La sintaxis adicional puede hacer que tu código se sienta más verboso al principio. Especificar tipos para todo puede parecer mucho trabajo extra cuando estás acostumbrado a la libertad de JavaScript.
Los conceptos avanzados como genéricos son donde muchos se atascan. Si nunca has trabajado con lenguajes tipados, features como conditional types o mapped types pueden hacerte sentir como si estuvieras leyendo chino.
2. Configuración inicial (el dolor necesario)
// tsconfig.json - Configuración requerida
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
3. El paso extra de compilación
A diferencia de JavaScript que ejecutas directamente, TypeScript necesita compilarse primero. Esto añade un paso extra a tu workflow que puede sentirse lento, especialmente cuando estás acostumbrado a la inmediatez de JS.
En proyectos grandes, la compilación puede tomar minutos. Nada como esperar 5 minutos para que compile tu proyecto cuando quieres hacer un cambio rápido.
Además, tu setup de build se complica. Necesitas configurar herramientas como Webpack, Rollup o Vite específicamente para TypeScript. Más config, más cosas que pueden fallar.
4. La pesadilla de los tipos de librerías
Muchas librerías de JavaScript no vienen con tipos incluidos, así que necesitas instalar paquetes @types adicionales. Es como comprar los accesorios por separado.
// Algunas librerías necesitan tipos adicionales
npm install @types/node @types/express @types/lodash
Esto crea una experiencia inconsistente donde algunas librerías tienen tipos perfectos, otras los tienen a medias, y algunas definitivamente no los tienen. Es frustrante cuando encuentras la librería perfecta pero no tiene tipos.
5. TypeScript no es magia
Lo importante es entender que TypeScript no previene todos los errores. El sistema de tipos se enfoca en la estructura del código, pero no puede detectar si tu algoritmo está mal o si tu lógica de negocio es incorrecta.
// TypeScript no previene errores de lógica
function dividir(a: number, b: number): number {
return a / b; // No previene división por cero
}
Puedes desarrollar una falsa sensación de seguridad pensando que si compila, está perfecto. Pero todavía necesitas tests, validación de entrada y todas las buenas prácticas de siempre.
Código real (donde TypeScript brilla)
Ejemplo 1: Los tipos básicos que más uso
// Tipos primitivos
let nombre: string = "Carlos";
let edad: number = 30;
let activo: boolean = true;
// Arrays
let numeros: number[] = [1, 2, 3, 4];
let nombres: Array<string> = ["Ana", "Luis", "María"];
// Objetos
let persona: {
nombre: string;
edad: number;
email?: string; // Opcional
} = {
nombre: "Carlos",
edad: 30
};
// Funciones
function saludar(nombre: string): string {
return `Hola, ${nombre}!`;
}
// Función con parámetros opcionales
function crearUsuario(
nombre: string,
email: string,
edad?: number
): Usuario {
return {
id: Date.now(),
nombre,
email,
edad: edad || 18,
activo: true
};
}
Ejemplo 2: Interfaces y types (mis herramientas favoritas)
// Interface para objetos
interface Producto {
id: number;
nombre: string;
precio: number;
categoria: string;
disponible: boolean;
}
// Type para uniones
type EstadoPedido = 'pendiente' | 'procesando' | 'enviado' | 'entregado';
// Interface extendida
interface ProductoConDescuento extends Producto {
descuento: number;
precioFinal: number;
}
// Interface para funciones
interface CalculadoraPrecios {
(precio: number, descuento: number): number;
}
const calcularPrecioFinal: CalculadoraPrecios = (precio, descuento) => {
return precio - (precio * descuento / 100);
};
// Usando las interfaces
const producto: Producto = {
id: 1,
nombre: "Laptop",
precio: 1200,
categoria: "Electrónicos",
disponible: true
};
const pedido: {
id: number;
productos: Producto[];
estado: EstadoPedido;
total: number;
} = {
id: 1,
productos: [producto],
estado: 'pendiente',
total: 1200
};
Ejemplo 3: Genéricos (al principio me daban miedo, ahora los amo)
// Función genérica
function obtenerPrimero<T>(array: T[]): T | undefined {
return array[0];
}
// Uso con diferentes tipos
const primerNumero = obtenerPrimero([1, 2, 3]); // number | undefined
const primerNombre = obtenerPrimero(["Ana", "Luis"]); // string | undefined
// Clase genérica
class Cola<T> {
private elementos: T[] = [];
agregar(elemento: T): void {
this.elementos.push(elemento);
}
obtener(): T | undefined {
return this.elementos.shift();
}
obtenerTodos(): T[] {
return [...this.elementos];
}
estaVacia(): boolean {
return this.elementos.length === 0;
}
}
// Uso de la clase genérica
const colaNumeros = new Cola<number>();
colaNumeros.agregar(1);
colaNumeros.agregar(2);
const colaNombres = new Cola<string>();
colaNombres.agregar("Carlos");
colaNombres.agregar("Ana");
// Interface genérica para API
interface APIResponse<T> {
data: T;
success: boolean;
message?: string;
timestamp: Date;
}
// Función que usa la interface genérica
async function obtenerDatos<T>(url: string): Promise<APIResponse<T>> {
const response = await fetch(url);
const data = await response.json();
return {
data,
success: response.ok,
message: response.ok ? 'Success' : 'Error',
timestamp: new Date()
};
}
// Uso con tipos específicos
const usuarios = await obtenerDatos<Usuario[]>('/api/usuarios');
const producto = await obtenerDatos<Producto>('/api/productos/1');
Ejemplo 4: Clases y herencia (programación orientada a objetos que funciona)
// Clase base
abstract class Animal {
protected nombre: string;
protected edad: number;
constructor(nombre: string, edad: number) {
this.nombre = nombre;
this.edad = edad;
}
// Método abstracto
abstract hacerSonido(): string;
// Método concreto
obtenerInfo(): string {
return `${this.nombre} tiene ${this.edad} años`;
}
}
// Clase derivada
class Perro extends Animal {
private raza: string;
constructor(nombre: string, edad: number, raza: string) {
super(nombre, edad);
this.raza = raza;
}
hacerSonido(): string {
return "Guau guau";
}
obtenerRaza(): string {
return this.raza;
}
// Override del método padre
obtenerInfo(): string {
return `${super.obtenerInfo()} y es un ${this.raza}`;
}
}
// Uso de las clases
const miPerro = new Perro("Max", 3, "Labrador");
console.log(miPerro.obtenerInfo()); // "Max tiene 3 años y es un Labrador"
console.log(miPerro.hacerSonido()); // "Guau guau"
Ejemplo 5: Utility Types (las herramientas que me facilitan la vida)
// Tipos utilitarios incorporados
interface Usuario {
id: number;
nombre: string;
email: string;
password: string;
rol: 'admin' | 'usuario';
activo: boolean;
}
// Partial - Hace todas las propiedades opcionales
type ActualizarUsuario = Partial<Usuario>;
// Pick - Selecciona propiedades específicas
type UsuarioPublico = Pick<Usuario, 'id' | 'nombre' | 'email'>;
// Omit - Excluye propiedades específicas
type CrearUsuario = Omit<Usuario, 'id'>;
// Record - Crea un tipo con claves específicas
type RolesPermisos = Record<Usuario['rol'], string[]>;
// Ejemplos de uso
const actualizarDatos: ActualizarUsuario = {
nombre: "Carlos Actualizado"
// Solo necesitamos las propiedades que queremos actualizar
};
const usuarioParaMostrar: UsuarioPublico = {
id: 1,
nombre: "Carlos",
email: "carlos@example.com"
// Sin password ni información sensible
};
const nuevoUsuario: CrearUsuario = {
nombre: "Ana",
email: "ana@example.com",
password: "123456",
rol: "usuario",
activo: true
// No necesitamos ID porque se genera automáticamente
};
const permisos: RolesPermisos = {
admin: ['crear', 'leer', 'actualizar', 'eliminar'],
usuario: ['leer', 'actualizar']
};
TypeScript vs JavaScript: la batalla honesta
Característica | TypeScript | JavaScript |
---|---|---|
Tipado | Estático (opcional) | Dinámico |
Detección de errores | Tiempo de compilación | Tiempo de ejecución |
Autocompletado | Excelente | Limitado |
Refactoring | Seguro y automático | Manual y propenso a errores |
Documentación | Tipos como documentación | Comentarios y docs externas |
Compatibilidad | Compila a JS estándar | Ejecuta directamente |
Curva de aprendizaje | Media | Baja |
Velocidad desarrollo | Menor inicial, mayor a largo plazo | Rápido inicial |
Configuración y herramientas (la parte práctica)
Configuración básica que funciona
# Crear proyecto TypeScript
mkdir mi-proyecto-ts
cd mi-proyecto-ts
# Inicializar npm
npm init -y
# Instalar TypeScript
npm install -D typescript @types/node
# Crear archivo de configuración
npx tsc --init
# Instalar ts-node para desarrollo
npm install -D ts-node nodemon
Mi tsconfig.json que siempre funciona
{
"compilerOptions": {
// Configuración de salida
"target": "ES2020",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
// Verificaciones estrictas
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
// Configuración de módulos
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
// Configuración adicional
"resolveJsonModule": true,
"declaration": true,
"sourceMap": true,
"removeComments": true,
"noEmitOnError": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist"
]
}
Scripts de package.json que uso siempre
{
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "ts-node src/index.ts",
"dev:watch": "nodemon --exec ts-node src/index.ts",
"type-check": "tsc --noEmit",
"clean": "rm -rf dist"
}
}
Herramientas y ecosistema que recomiendo
Editores que brillan con TypeScript:
Visual Studio Code es el rey indiscutido para TypeScript. Como ambos son de Microsoft, la integración es perfecta. Prácticamente no necesitas configurar nada para tener una experiencia increíble.
WebStorm de JetBrains es mi segunda opción, especialmente si ya estás en el ecosistema de sus herramientas. El análisis de código y refactoring son top-tier.
Sublime Text funciona bien con plugins, ideal si prefieres algo más ligero pero potente.
Vim y Neovim también pueden trabajar con TypeScript vía LSP. Para los puristas que no queremos dejar nuestro editor favorito.
Linters y formateadores que no pueden faltar:
# ESLint con TypeScript
npm install -D @typescript-eslint/eslint-plugin @typescript-eslint/parser
# Prettier
npm install -D prettier
# Configuración .eslintrc.js
module.exports = {
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
extends: [
'eslint:recommended',
'@typescript-eslint/recommended'
]
};
Testing que funciona:
# Jest con TypeScript
npm install -D jest @types/jest ts-jest
# Configuración jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
roots: ['<rootDir>/src'],
testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'],
transform: {
'^.+\\.ts$': 'ts-jest'
}
};
Cuándo SÍ usar TypeScript (y cuándo mejor no)
✅ TypeScript brilla en estos casos:
En proyectos grandes donde trabajan múltiples equipos, TypeScript es un salvavidas. Los tipos actúan como contratos claros entre diferentes partes del sistema, reduciendo malentendidos y bugs.
Para aplicaciones críticas donde los errores cuestan caro, TypeScript ayuda a detectar problemas antes de llegar a producción. En sistemas financieros, médicos o de infraestructura, esta seguridad extra vale oro.
Si estás construyendo APIs y librerías para otros developers, los tipos de TypeScript son documentación viva. Clarifica exactamente cómo usar tus funciones sin necesidad de leer docs extensas.
Los equipos distribuidos se benefician enormemente porque los tipos comunican intenciones sin necesidad de estar constantemente preguntando "¿qué esperaba esta función?"
Para refactoring frecuente, TypeScript hace cambios seguros y automáticos. El compilador puede detectar automáticamente qué se ve afectado por un cambio.
En desarrollo a largo plazo, la mantenibilidad que ofrece TypeScript es invaluable. Proyectos que evolucionarán durante años se benefician enormemente de la claridad estructural.
❌ Mejor usa JavaScript puro en estos casos:
Para scripts simples que automatizan tareas puntuales, TypeScript puede ser overkill. Si es algo de 50 líneas que usas ocasionalmente, JavaScript directo es más rápido.
En prototipado rápido donde necesitas iterar súper rápido, la velocidad de JavaScript puro puede ser más valiosa que la seguridad de tipos.
Proyectos pequeños con un solo desarrollador pueden no justificar el setup y overhead de TypeScript. El tiempo de configuración puede ser mayor que el beneficio.
Con equipos nuevos en tipado estático, la curva de aprendizaje puede ser contraproducente inicialmente. Mejor empezar con JavaScript y migrar gradualmente.
Bajo deadlines súper ajustados, el tiempo adicional de setup y compilación puede ser crítico. A veces la velocidad inicial es más importante que la seguridad a largo plazo.
Frameworks donde TypeScript es rey
Frontend que ama TypeScript:
// React con TypeScript
import React, { useState } from 'react';
interface Props {
titulo: string;
onClic?: () => void;
}
const Boton: React.FC<Props> = ({ titulo, onClic }) => {
return <button onClick={onClic}>{titulo}</button>;
};
// Vue con TypeScript
import { defineComponent, ref } from 'vue';
export default defineComponent({
name: 'Contador',
setup() {
const contador = ref<number>(0);
const incrementar = (): void => {
contador.value++;
};
return {
contador,
incrementar
};
}
});
Backend donde TypeScript domina:
// Express con TypeScript
import express, { Request, Response } from 'express';
const app = express();
interface Usuario {
id: number;
nombre: string;
email: string;
}
app.get('/usuarios/:id', (req: Request, res: Response) => {
const id = parseInt(req.params.id);
// Lógica para obtener usuario
const usuario: Usuario = {
id,
nombre: 'Carlos',
email: 'carlos@example.com'
};
res.json(usuario);
});
// NestJS - Framework TypeScript-first
import { Controller, Get, Param } from '@nestjs/common';
@Controller('usuarios')
export class UsuariosController {
@Get(':id')
obtenerUsuario(@Param('id') id: string): Usuario {
return {
id: parseInt(id),
nombre: 'Carlos',
email: 'carlos@example.com'
};
}
}
Migración de JavaScript: mi estrategia que funciona
El plan gradual que recomiendo:
1. Preparación (sin romper nada)
# Instalar TypeScript
npm install -D typescript @types/node
# Crear tsconfig.json
npx tsc --init
2. Configuración permisiva (para empezar sin dolor)
{
"compilerOptions": {
"allowJs": true,
"checkJs": false,
"strict": false,
"noImplicitAny": false
}
}
3. Migración archivo por archivo (la clave del éxito)
// Paso 1: Renombrar .js a .ts
// archivo.js -> archivo.ts
// Paso 2: Agregar tipos básicos
function sumar(a: number, b: number): number {
return a + b;
}
// Paso 3: Definir interfaces
interface Usuario {
id: number;
nombre: string;
}
4. Configuración más estricta (cuando ya te sientes cómodo)
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true
}
}
El futuro que viene (y me emociona)
Lo que está pasando ahora:
TypeScript se está enfocando en tipos más expresivos con features como template literal types y conditional types. Esto permite expresar relaciones súper complejas que antes eran imposibles.
La inferencia de tipos mejora constantemente. El compilador se vuelve más inteligente para deducir tipos automáticamente, reduciendo la necesidad de anotaciones manuales.
Las optimizaciones de performance son constantes. Compilación más rápida y menos uso de memoria, especialmente importante para proyectos grandes.
La integración con herramientas modernas como Vite, Webpack y Rollup mejora constantemente, haciendo que usar TypeScript sea cada vez más fluido.
Mi predicción para 2024-2025:
Viene mejor soporte para decoradores que finalmente se están estabilizando. Esto será genial para frameworks como Angular y NestJS.
Espero tipos más precisos para DOM, mejorando la experiencia de desarrollo frontend con mejor tipado para APIs del navegador.
Las optimizaciones de rendimiento seguirán siendo prioridad, con mejoras en tiempo de compilación que harán que trabajar con proyectos grandes sea menos frustrante.
Y por supuesto, mejor integración con el ecosistema de build moderno seguirá evolucionando.
Mi reflexión después de años usando TypeScript
TypeScript ha sido una de las mejores decisiones que tomé en mi carrera como developer. Es esa herramienta que una vez que la adoptas, no puedes imaginar trabajar sin ella.
Lo que realmente me cambió la vida:
La detección temprana de errores es el beneficio más tangible. No puedo contar las horas que me he ahorrado debuggeando gracias a detectar errores en tiempo de compilación en lugar de en producción.
La experiencia de desarrollo mejoró radicalmente. El autocompletado inteligente y el refactoring seguro hacen que programar sea mucho más fluido y confiable.
El código más mantenible que resulta de tener tipos claros y contratos explícitos. Regresar a código de hace 6 meses ya no es una pesadilla de "¿qué diablos esperaba esta función?"
La escalabilidad real para proyectos grandes. Los tipos actúan como un lenguaje común entre diferentes partes del sistema y diferentes miembros del equipo.
La compatibilidad total con JavaScript que permite migración gradual sin reescribir todo desde cero.
Lo que debes considerar:
La curva de aprendizaje sí requiere tiempo y paciencia. Pero como con cualquier herramienta poderosa, la inversión inicial vale la pena.
La configuración inicial requiere más setup que JavaScript puro, pero una vez configurado, se convierte en parte natural del workflow.
El tiempo de compilación puede ser notable en proyectos grandes, pero las herramientas mejoran constantemente y los beneficios superan este costo.
TypeScript es especialmente valioso para proyectos de larga duración donde el ROI en configuración inicial se amortiza con tiempo, equipos grandes que se benefician de contratos claros, aplicaciones críticas donde los errores son costosos, y desarrolladores que buscan herramientas más sofisticadas.
Mi recomendación personal:
Si trabajas en proyectos JavaScript de mediana a gran escala, o si buscas mejorar la calidad y mantenibilidad de tu código, TypeScript es una inversión que definitivamente vale la pena. Su adopción por gigantes como Microsoft, Google, Slack y muchas otras confirma su valor real.
La transición puede ser gradual, lo que significa que puedes empezar a obtener beneficios inmediatos sin necesidad de reescribir todo tu código existente. En mi experiencia, una vez que pruebas TypeScript en un proyecto real, es muy difícil regresar a JavaScript puro.
¿Ya has probado TypeScript? ¿Qué ha sido lo que más te ha costado o lo que más te ha gustado? Me encantaría escuchar tu experiencia con esta herramienta que tanto ha cambiado mi forma de programar.
Comentarios
Posts relacionados

Map vs forEach en JavaScript: Cuándo y Cómo Utilizarlos
Diferencias entre map y forEach en JavaScript, con ejemplos prácticos y casos de uso

Eliminar el Primer Carácter en JavaScript: Guía Rápida
Aprende diferentes métodos para eliminar el primer carácter de un string en JavaScript, como substring() y slice(), con ejemplos prácticos y comparativas.