Introducción a TypeScript
TypeScript es un lenguaje de programación de código abierto desarrollado por Microsoft. Es un superconjunto de JavaScript que, además de ser totalmente compatible con la sintaxis de JavaScript, añade un sistema de tipos estáticos opcional y capacidades de programación orientada a objetos basada en clases.
El código TypeScript se compila finalmente a JavaScript puro, el cual puede ejecutarse en cualquier entorno compatible con JavaScript, incluidos navegadores, Node.js y dispositivos móviles.

¿Por qué es necesario TypeScript?
JavaScript es un lenguaje de tipado dinámico; el tipo de una variable solo se determina en tiempo de ejecución.
Esta flexibilidad funciona muy bien en proyectos pequeños, pero a medida que el proyecto crece, los problemas comienzan a aparecer:
| Escenario problemático | Las dificultades de JavaScript | La solución de TypeScript |
|---|---|---|
| Pasar un tipo incorrecto a un parámetro de función | El error solo aparece en tiempo de ejecución, difícil de detectar con antelación | El error aparece en la compilación, con aviso en tiempo real del IDE |
| Acceder a una propiedad inexistente | devuelveundefined, comportamiento impredecible | El compilador muestra el error directamente y rechaza el código |
| Refactorización de proyectos grandes | Cambias un lugar y no sabes qué podría romperse | El sistema de tipos rastrea automáticamente todas las referencias |
| Colaboración en equipo | Qué parámetros acepta una función y qué devuelve depende únicamente de comentarios o documentación | La firma de tipos es la documentación; el IDE ofrece autocompletado automáticamente |
| Legibilidad del código | Con ver la definición de la función no se puede saber directamente la estructura de datos | Las interfaces y los alias de tipos hacen que la estructura de datos sea clara de un vistazo |
El objetivo esencial de TypeScript no es reemplazar a JavaScript, sino hacer que los proyectos JavaScript a gran escala sean manejables y mantenibles. Es una 'red de seguridad' para JavaScript, no un competidor.
Veamos el ejemplo más intuitivo:
Ejemplo
function greet(name) {
return "Hello, " + name.toUpperCase();
}
greet(123); // Error en tiempo de ejecución: name.toUpperCase is not a function
Ejemplo
function greet(name: string): string {
return "Hello, " + name.toUpperCase();
}
greet(123); // Error de compilación: Argument of type 'number' is not assignable to parameter of type 'string'
greet("ejemplo"); // Correcto: Hello, EJEMPLO
Relación entre TypeScript y JavaScript
La relación entre TypeScript y JavaScript se puede resumir en una frase:TypeScript es un superconjunto de JavaScript, es decir, todo código JavaScript válido es también código TypeScript válido.
Representación de la relación de conjuntos
JavaScript (todo el código JS)
⊂ TypeScript (JS + sistema de tipos + nuevas características)
⊂ Producto de compilación (JavaScript estándar, se puede ejecutar en cualquier entorno)
Comparación de las diferencias clave entre ambos:
| Criterio de comparación | JavaScript | TypeScript |
|---|---|---|
| Sistema de tipos | Tipado dinámico, determinado en tiempo de ejecución | Tipado estático, verificado en tiempo de compilación (opcional) |
| Forma de ejecución | Se ejecuta directamente en el navegador / Node.js | Requiere compilar a JS antes de ejecutarse |
| Momento de detección de errores | Tiempo de ejecución | Tiempo de compilación (detección anticipada) |
| Soporte de IDE | Autocompletado básico | Inferencia de tipos sólida, autocompletado preciso, soporte de refactorización |
| Curva de aprendizaje | Relativamente suave | Requiere aprender también el sistema de tipos |
| Compatibilidad con JS existente | — | Totalmente compatible, migración progresiva posible |
| Extensión de archivo | .js | .tso.tsx(incluye JSX) |
TypeScript admite la 'adopción progresiva': no es necesario reescribir todo el proyecto de una vez. Puedes primero
.jscambiarlo a.ts, y añadir gradualmente tipos a los módulos clave; el código existente continuará funcionando con normalidad.
Características principales
TypeScript introduce un sistema de tipos completo sobre JavaScript; las siguientes son las características principales más utilizadas.
Anotaciones de tipos básicos
Se declara el tipo con dos puntos después de variables, parámetros de función y valores de retorno; esta es la forma más básica de escribir TypeScript.
Ejemplo
let age: number = 25;
let username: string = "ejemplo";
let isActive: boolean = true;
// Tipos de array, dos formas equivalentes
let scores: number[] = [90, 85, 92];
let tags: Array<string> = ["typescript", "javascript"];
// Tupla: array con longitud y tipos fijos
let point: [number, number] = [10, 20];
let entry: [string, number] = ["EJEMPLO", 100];
// Función: tipo de parámetros + tipo de valor de retorno
function add(a: number, b: number): number {
return a + b;
}
// void: función sin valor de retorno
function log(msg: string): void {
console.log(msg);
}
// Parámetro opcional: añadir ? después del nombre del parámetro
function greet(name: string, title?: string): string {
return title ? `${title} ${name}` : name;
}
console.log(greet("EJEMPLO")); // Salida: EJEMPLO
console.log(greet("ejemplo", "Mr.")); // Salida: Mr. ejemplo
Interfaz (Interface)
Las interfaces se usan para describir la 'forma' (Shape) de un objeto y definir qué propiedades y métodos debe tener.
Ejemplo
interface User {
id: number; // Requerido
name: string; // Requerido
email?: string; // Opcional, marcado con ?
readonly role: string; // Solo lectura; no se puede modificar después de asignarlo
}
// El parámetro de función usa el tipo de interfaz
function printUser(user: User): void {
console.log(`ID: ${user.id}, Name: ${user.name}`);
if (user.email) {
console.log(`Email: ${user.email}`);
}
}
const admin: User = {
id: 1,
name: "EJEMPLO",
email: "[email protected]",
role: "admin",
};
printUser(admin);
// Salida: ID: 1, Name: EJEMPLO
// Salida: Email: [email protected]
// admin.role = "user"; // Error: Cannot assign to 'role' because it is a read-only property.
// Herencia de interfaces
interface AdminUser extends User {
permissions: string[];
}
Alias de tipo (Type Alias)
Los alias de tipo se crean con latypepalabra clave, y pueden definir alias para cualquier tipo, incluidas estructuras complejas como uniones e intersecciones de tipos.
Ejemplo
type ID = string | number;
let userId: ID = "abc-123"; // Válido
userId = 456; // También válido
// Tipo literal: restringe la variable a solo valores específicos
type Direction = "up" | "down" | "left" | "right";
type Status = "pending" | "active" | "inactive";
function move(dir: Direction): void {
console.log(`Moving ${dir}`);
}
move("up"); // Correcto
// move("diagonal"); // Error: no está dentro del tipo literal
// Intersección de tipos: combina varios tipos
type WithTimestamp = {
createdAt: Date;
updatedAt: Date;
};
type UserRecord = User & WithTimestamp; // Tiene todas las propiedades de User y WithTimestamp a la vez
// Alias de tipo para funciones
type Transformer<T, U> = (input: T) => U;
const toNumber: Transformer<string, number> = (s) => parseInt(s, 10);
Genéricos (Generics)
Los genéricos permiten escribir componentes reutilizables manteniendo la seguridad de tipos. Puedes entender los genéricos como "variables de tipos": el tipo concreto se pasa al utilizarlo.
Ejemplo
function firstNumber(arr: number[]): number {
return arr[0];
}
// Usando genéricos: T es un parámetro de tipo, se determina en la llamada
function first<T>(arr: T[]): T {
return arr[0];
}
const n = first<number>([1, 2, 3]); // El tipo de n es number
const s = first<string>(["a", "b"]); // El tipo de s es string
const inferred = first([true, false]); // TypeScript infiere automáticamente T como boolean
// Interfaz genérica
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
// Usando una interfaz genérica
const userResponse: ApiResponse<User> = {
data: { id: 1, name: "EJEMPLO", role: "admin" },
status: 200,
message: "success",
};
// Restricción de genéricos: T debe tener una propiedad id
function getById<T extends { id: number }>(items: T[], id: number): T | undefined {
return items.find(item => item.id === id);
}
Enumeración (Enum)
Las enumeraciones se usan para definir un conjunto de constantes con nombre, haciendo que los "números mágicos" o "cadenas mágicas" en el código tengan significado.
Ejemplo
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right, // 3
}
console.log(Direction.Up); // Salida: 0
console.log(Direction[0]); // Salida: "Up" (mapeo inverso)
// Enumeración de cadenas (más recomendada, los valores son más legibles al depurar)
enum Color {
Red = "RED",
Green = "GREEN",
Blue = "BLUE",
}
function paint(color: Color): void {
console.log(`Painting in ${color}`);
}
paint(Color.Red); // Salida: Painting in RED
// paint("red"); // Error: la cadena "red" no es del tipo Color
// Enumeración const: se incluye en línea tras la compilación, reduciendo la sobrecarga en tiempo de ejecución
const enum HttpStatus {
OK = 200,
NotFound = 404,
InternalError = 500,
}
const status: HttpStatus = HttpStatus.OK; // Tras la compilación se reemplaza directamente por el número 200
Inferencia de tipos
TypeScript no requiere anotar manualmente el tipo de cada variable; el compilador lo infiere automáticamente según la asignación.
Ejemplo
let count = 0; // Se infiere como number
let name = "EJEMPLO"; // Se infiere como string
let flag = true; // Se infiere como boolean
// Infiere el tipo de los elementos del array
let numbers = [1, 2, 3]; // Se infiere como number[]
// Infiere el tipo de retorno de la función
function double(n: number) { // El valor de retorno se infiere automáticamente como number
return n * 2;
}
// Inferencia de literales de objeto
const config = {
host: "localhost", // string
port: 3000, // number
debug: false, // boolean
};
// config.port = "3000"; // Error: Type 'string' is not assignable to type 'number'.
Un consejo práctico: los parámetros de las funciones suelen necesitar anotaciones explícitas de tipo (porque quien las llama no puede inferir el tipo a partir de los valores de los argumentos), mientras que las variables locales y los valores de retorno pueden depender de la inferencia en la mayoría de los casos, sin necesidad de anotarlos todos manualmente.
Clases y modificadores de acceso
TypeScript es totalmente compatible con la sintaxis de clases de ES6 y añadepublic、private、protected、readonlycuatro modificadores de acceso.
Ejemplo
readonly name: string; // Solo lectura, no se puede modificar después de la inicialización
private age: number; // Privado, solo se puede acceder dentro de la clase
protected species: string; // Protegido, accesible para las subclases
constructor(name: string, age: number, species: string) {
this.name = name;
this.age = age;
this.species = species;
}
// Método public (por defecto es public, se puede omitir)
public introduce(): string {
return `I'm ${this.name}, a ${this.species}.`;
}
// Getter: llama al método como si se accediera a una propiedad
get info(): string {
return `${this.name} (${this.age} years old)`;
}
}
class Dog extends Animal {
private breed: string;
constructor(name: string, age: number, breed: string) {
super(name, age, "Canis lupus familiaris"); // Llama al constructor de la clase padre
this.breed = breed;
}
// La subclase puede acceder a la propiedad protected
describe(): string {
return `${this.name} is a ${this.species}, breed: ${this.breed}`;
}
}
const dog = new Dog("EJEMPLO", 3, "Labrador");
console.log(dog.introduce()); // Salida: I'm EJEMPLO, a Canis lupus familiaris.
console.log(dog.info); // Salida: EJEMPLO (3 years old)
// console.log(dog.age); // Error: la propiedad privada no se puede acceder desde fuera
Decorador (Decorator)
Los decoradores son una sintaxis de metaprogramación que permite añadir comportamientos adicionales a clases, métodos y propiedades; se usan comúnmente en frameworks como Angular y NestJS.
TypeScript 5.0 ha implementado los decoradores como estándar oficial (propuesta Stage 3), por lo que ya no es necesario activar laexperimentalDecoratorsflag.
Ejemplo
function sealed(constructor: Function) {
Object.seal(constructor); // Prohíbe añadir nuevas propiedades
Object.seal(constructor.prototype);
}
// Decorador de método: se puede usar para registro de logs, verificación de permisos, etc.
function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const original = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`Calling ${propertyKey} with args:`, args);
const result = original.apply(this, args);
console.log(`${propertyKey} returned:`, result);
return result;
};
}
@sealed
class Calculator {
@log
add(a: number, b: number): number {
return a + b;
}
}
const calc = new Calculator();
calc.add(1, 2);
// Salida: Calling add with args: [ 1, 2 ]
// Salida: add returned: 3
Áreas de aplicación
TypeScript, gracias a su total compatibilidad con JavaScript, puede usarse en casi cualquier lugar donde JavaScript pueda ejecutarse, y aporta beneficios adicionales en proyectos grandes.
Desarrollo web frontend
Este es el escenario más común para TypeScript. Los tres frameworks frontend principales ofrecen soporte de primera clase para TypeScript:
| Framework | Soporte de TypeScript | Casos de uso típicos |
|---|---|---|
| Angular | Lenguaje oficial, usa TypeScript por defecto, no se puede omitir | SPA empresariales, sistemas de administración |
| React | Proporcionado oficialmente@types/react, Create React App y Vite incluyen plantillas de TypeScript integradas. | Comercio electrónico, plataformas de contenido, aplicaciones de gestión |
| Vue | El código central de Vue 3 está reescrito en TypeScript, y la Composition API ha mejorado notablemente la compatibilidad con TypeScript. | Proyectos medianos y pequeños, migración progresiva |
| Next.js / Nuxt | Soporte integrado de TypeScript, activado por defecto en proyectos nuevos. | Aplicaciones full-stack SSR/SSG |
Desarrollo backend con Node.js
TypeScript es igualmente popular en el desarrollo backend con Node.js.NestJSEs el framework backend de TypeScript más popular, utiliza una arquitectura modular similar a Angular y tiene soporte integrado de inyección de dependencias y decoradores.
Además,DenoEl runtime es compatible de forma nativa con TypeScript desde el primer día, y puede ejecutarse directamente sin configuración alguna..tsarchivos.BunIgualmente incluye soporte integrado de TypeScript.
Herramientas de línea de comandos y scripts
Con la ayuda dets-node、tsxherramientas como estas, el código TypeScript se puede ejecutar directamente sin compilación previa, ideal para escribir scripts de build y herramientas CLI.
Móvil y multiplataforma
React NativeSoporte completo de TypeScript; muchas aplicaciones móviles empresariales (como Microsoft Office móvil, Shopify, etc.) utilizan esta pila tecnológica.ExpoLa plantilla de nuevos proyectos también se basa en TypeScript por defecto.
Desarrollo de juegos y gráficos
Babylon.jsEl motor 3D de Microsoft está completamente escrito en TypeScript y trata las definiciones de tipos de TypeScript como ciudadanos de primera clase.PhaserLos motores de juegos 2D como estos también ofrecen definiciones de tipos completas.
Historia del desarrollo
El nacimiento y el crecimiento de TypeScript están estrechamente relacionados con la evolución del ecosistema de JavaScript; cada lanzamiento de una versión importante está impulsado por necesidades de ingeniería claras.
Orígenes (2010-2012)
La historia de TypeScript comienza con un desafío de ingeniería en Microsoft: cómo hacer mantenibles los grandes proyectos de JavaScript.
DiseñadorAnders HejlsbergEs una leyenda de la industria: arquitecto jefe de C# y creador de Turbo Pascal y Delphi. Comenzó a diseñar este lenguaje alrededor de 2010, con el objetivo central de introducir la verificación estática de tipos sin romper la compatibilidad con JavaScript.
Otro contexto del lanzamiento de TypeScript por Microsoft fue la publicación de Windows 8: las aplicaciones podían desarrollarse con HTML + JavaScript, y Microsoft quería atraer a los programadores de .NET, por lo que mucha de la sintaxis de TypeScript se mantuvo deliberadamente similar a C# y .NET.
En octubre de 2012, TypeScript 0.8 se publicó oficialmente, tras unos dos años de desarrollo interno en Microsoft.
Primeras versiones (2013-2015)
| Fecha | Versión | Hitos importantes |
|---|---|---|
| 2013-06 | 0.9 | Lanzamiento de la versión estable oficial, gran mejora de rendimiento, mejor integración con IDE. |
| 2014-04 | 1.0 | Primera versión estable oficial; introduce clases, interfaces y módulos, con soporte para compilar a JavaScript estándar. |
| 2014-07 | — | El código del compilador de TypeScript se vuelve de código abierto, alojado en GitHub, aceptando contribuciones de la comunidad. |
| 2015-04 | — | Microsoft lanza Visual Studio Code, con soporte profundo integrado para TypeScript; ambos se complementan mutuamente. |
| 2015-07 | 1.5 | Introduce soporte de sintaxis de módulos ES6, decoradores (experimental) y espacios de nombres. |
Crecimiento acelerado (2016-2019)
Esta etapa fue clave para que TypeScript pasara de ser una herramienta de nicho a convertirse en mainstream; el impulso principal provino de las decisiones del ecosistema de frameworks.
| Fecha | Versión / Evento | Hito |
|---|---|---|
| 2016-09 | TypeScript 2.0 | Introducción de los tipos no nulos (--strictNullChecks), una de las características más importantes de la seguridad de tipos de TypeScript; introducción de las uniones discriminadas |
| 2016 | Lanzamiento de Angular 2 | El equipo de Google Angular anunció la adopción de TypeScript como lenguaje de desarrollo oficial, llevando TypeScript a la atención del público general |
| 2017 | Serie TypeScript 2.x | Se introdujeron sucesivamente los tipos condicionales, los tipos mapeados y la palabra clave infer, lo que mejoró enormemente la capacidad expresiva del sistema de tipos |
| 2018-07 | TypeScript 3.0 | Referencias de proyectos (Project References), con soporte para monorepos de gran tamaño; se introdujo el tipo unknown (un tipo superior más seguro que any) |
| 2019 | DefinitelyTyped | El repositorio de definiciones de tipos mantenido por la comunidad, DefinitelyTyped (@types/*) supera los 7000 paquetes y cubre prácticamente todas las bibliotecas npm principales |
Madurez y popularización (2020-2022)
| Fecha | Versión / Evento | Contenido importante |
|---|---|---|
| 2020-08 | TypeScript 4.0 | Tipos de tupla variádicos y elementos de tupla etiquetados; la experiencia del editor mejoró significativamente |
| 2021 | Serie TypeScript 4.x | Tipos de literales de plantilla (Template Literal Types), mejora de los tipos de utilidad incorporados,noImplicitOverridey otras mejoras del modo estricto |
| 2022 | Encuesta State of JS | La tasa de uso de TypeScript superó por primera vez a la de JavaScript puro, convirtiéndose en el lenguaje superconjunto más popular del ecosistema JS |
| 2022 | Popularización de Vue 3 / Vite | El núcleo de Vue 3 fue reescrito con TypeScript y, junto con Vite, llevó la experiencia de TypeScript en el desarrollo frontend a un nuevo nivel |
Etapa moderna (2023-presente)
| Fecha | Versión | Características importantes |
|---|---|---|
| 2023-03 | TypeScript 5.0 | Decoradores modernos (estándar Stage 3), parámetros de tipo const, todos los enums se actualizaron a enums de unión, con una mejora significativa del rendimiento |
| 2023-08 | TypeScript 5.2 | Se introdujo Explicit Resource Management (usingpalabra clave), que resuelve el problema de la limpieza determinista de recursos como conexiones de bases de datos y manejadores de archivos |
| 2024-03 | TypeScript 5.4 | Mejoras en el estrechamiento de tipos en closures,NoInfertipos de utilidad |
| 2024-06 | TypeScript 5.5 | Inferencia de predicados de tipo y comprobación de sintaxis de expresiones regulares, lo que permite que el sistema de tipos comprenda la lógica del código con mayor precisión |
| 2024-11 | TypeScript 5.7 | Soporte para--target es2024una detección más fiable de variables no inicializadas |
| 2025-03 | TypeScript 5.8 | Comprobación mejorada de valores de retorno en tipos de acceso condicional e indexado; se admite--module nodenextbajo ... medianterequire()la carga de módulos ESM (requiere Node.js 22+) |
Perspectivas futuras: reescribir el compilador en Go
A principios de 2025, Microsoft anunció una decisión importante: reescribir el compilador de TypeScript en el lenguaje Go, con el nombre clave del proyectoCorsa。
Microsoft afirmó que se espera que el compilador reescrito ofrezca una mejora de rendimiento de más de 10 veces, y que el tiempo de compilación de proyectos grandes se reduzca de minutos a segundos.
Según el plan, la versión en Go se publicará oficialmente en TypeScript 7.x, mientras que las versiones actuales 5.x / 6.x de TypeScript continuarán con su iteración y mantenimiento normales. Se espera que la reescritura esté terminada a finales de 2025.
Esta reescritura no cambiará la sintaxis ni el sistema de tipos del propio lenguaje TypeScript; es una actualización transparente para los desarrolladores: tu código no necesita ningún cambio, solo la velocidad de compilación mejora drásticamente.
Comparación de TypeScript con otros lenguajes de tipado fuerte
Si tienes experiencia con otros lenguajes de tipado fuerte, la siguiente comparación puede ayudarte a situar rápidamente la filosofía de diseño de TypeScript.
| Elemento de comparación | TypeScript | Java / C# | Go |
|---|---|---|---|
| Sistema de tipos | Tipado estructural (duck typing) | Tipado nominal (debe declararse explícitamente la relación de herencia) | Tipado estructural (interfaces implícitas) |
| Seguridad de valores nulos | Al habilitarstrictNullChecksse admite | Java requiere anotaciones u Optional; C# 8+ lo admite | Mediante valores de error y comprobaciones de nil |
| Genéricos | Admite, sintaxis similar a Java/C# | Admite; Java tiene limitaciones por borrado de tipos | Admite desde Go 1.18+, con sintaxis relativamente sencilla |
| Artefacto de compilación | JavaScript (se ejecuta en entornos JS) | Bytecode (se ejecuta en JVM / CLR) | Código máquina nativo |
| Comprobación de tipos en tiempo de ejecución | No (la información de tipos se elimina tras la compilación) | Sí (mecanismo de reflexión) | Ninguno |
| Curva de aprendizaje | Amigable para desarrolladores de JS, se puede adoptar de forma gradual | Empinada para principiantes | Relativamente simple, curva de aprendizaje media |
TypeScript utilizaun sistema de tipado estructural(Structural Typing): si dos tipos tienen la misma "forma", se consideran compatibles, sin necesidad de declarar explícitamente relaciones de herencia. Esto difiere esencialmente del tipado nominal (Nominal Typing) de Java/C#, y es también la razón clave por la que TypeScript puede interoperar sin problemas con JavaScript.
Limitaciones de TypeScript
TypeScript no es una bala de plata; conocer sus límites es igualmente importante.
| Limitación | Descripción | Cómo abordarlo |
|---|---|---|
| Sin tipos en tiempo de ejecución | Toda la información de tipos se elimina después de la compilación, por lo que en tiempo de ejecución no se puede depender de los tipos para tomar decisiones | Cuando se necesite validación en tiempo de ejecución, usarzod、io-tsy otras bibliotecas |
| Paso de compilación | En comparación con JS puro, añade un paso de compilación adicional, lo que aumenta la complejidad del proyecto | Las herramientas de construcción modernas (Vite, esbuild) ya ofrecen una buena optimización para ello |
| El tipo any como vía de escape | El abuso deanyhará que la comprobación de tipos sea una formalidad vacía | HabilitarnoImplicitAnyystrictel modo, junto con reglas de ESLint |
| Barrera de entrada de la gimnasia de tipos | Los tipos condicionales y mapeados complejos no son amigables para los principiantes | La mayoría del código de negocio no necesita tipos avanzados; basta con aprender de forma progresiva |
| Compatibilidad con bibliotecas de terceros | Algunas bibliotecas antiguas carecen de definiciones de tipos, por lo que hay que escribir los archivos .d.ts manualmente | Primero busca en@types/*si de verdad no existe, escribe manualmente el archivo de declaraciones |