¡Excelente elección! TypeScript es una herramienta fundamental en el desarrollo web moderno, especialmente para proyectos a gran escala, ya que añade seguridad de tipo y mejoras en la productividad. Aquí tienes un “cheatsheet” completo y bien estructurado de TypeScript, optimizado para ser claro y conciso para una IA conversacional.
🟦 TypeScript Cheatsheet Completo 🟦
TypeScript es un superset de JavaScript que añade tipado estático opcional al lenguaje. Se compila a JavaScript plano, lo que significa que cualquier código JavaScript válido es también código TypeScript válido. Su objetivo principal es ayudar a los desarrolladores a construir aplicaciones más robustas y escalables, detectando errores de tipo en tiempo de desarrollo.
1. 🌟 Conceptos Clave
- Tipado Estático: Permite definir los tipos de variables, funciones y objetos en tiempo de desarrollo, lo que ayuda a prevenir errores comunes antes de ejecutar el código.
- Superset de JavaScript: TypeScript incluye todas las características de JavaScript (ES6+), más sus propias características de tipado.
- Compilación: El código TypeScript (
.tso.tsx) se transpila a JavaScript (.js) para poder ser ejecutado por navegadores o Node.js. - Inferencia de Tipos: TypeScript es lo suficientemente inteligente como para deducir el tipo de una variable en muchos casos, eliminando la necesidad de anotarlo explícitamente.
- Editor Support: Los IDEs y editores de código (VS Code, WebStorm) ofrecen un excelente soporte para TypeScript, con autocompletado, refactorización y detección de errores en tiempo real.
2. 🛠️ Configuración Inicial
-
Instalación del Compilador (Global):
npm install -g typescript # o yarn global add typescript -
Inicializar Proyecto (
tsconfig.json):- Crea un archivo
tsconfig.jsonen la raíz de tu proyecto. Este archivo configura cómo el compilador de TypeScript (tsc) compilará tus archivos.
tsc --init - Crea un archivo
-
Compilar TypeScript:
tsc # Compila todos los archivos .ts según tsconfig.json tsc myFile.ts # Compila un archivo específico tsc --watch # Compila automáticamente los cambios
tsconfig.json (Opciones Comunes)
{
"compilerOptions": {
"target": "ESNext", // Versión de JS a la que compilar (ej. "ES2016", "ESNext")
"module": "ESNext", // Sistema de módulos (ej. "CommonJS", "ESNext")
"strict": true, // Habilita todas las opciones de comprobación de tipo estricta (recomendado)
"esModuleInterop": true, // Permite la interoperabilidad entre módulos CommonJS y ES
"skipLibCheck": true, // Omite la comprobación de tipos de archivos de declaración (d.ts)
"forceConsistentCasingInFileNames": true, // Impide referencias inconsistentes al mismo archivo
"outDir": "./dist", // Directorio de salida para los archivos JS compilados
"rootDir": "./src", // Directorio raíz de los archivos TS
"declaration": true, // Genera archivos .d.ts para tus módulos
"sourceMap": true, // Genera archivos .map para depuración
"jsx": "react-jsx" // Para proyectos React/JSX ("preserve", "react", "react-jsx")
},
"include": ["src/**/*"], // Archivos a incluir en la compilación
"exclude": ["node_modules", "dist"] // Archivos a excluir
}
3. 🧩 Tipos Básicos
number: Números (enteros y flotantes).let age: number = 30; let pi: number = 3.14;string: Cadenas de texto.let name: string = "Alice";boolean: Valores verdadero/falso.let isActive: boolean = true;null: El valornull.let value: null = null;undefined: El valorundefined.let data: undefined = undefined;symbol: Valores únicos e inmutables.let id: symbol = Symbol("id");bigint: Enteros de precisión arbitraria.let bigNumber: bigint = 9007199254740991n;any: Tipo comodín. Desactiva la comprobación de tipo para esa variable. Usar con precaución.let anything: any = "hello"; anything = 123;unknown: Similar aany, pero más seguro. Debes refinar su tipo antes de usarlo.let unknownValue: unknown = "test"; if (typeof unknownValue === "string") { console.log(unknownValue.toUpperCase()); // Ahora es seguro usar métodos de string }void: Para funciones que no devuelven ningún valor.function logMessage(): void { console.log("Mensaje."); }never: Representa un valor que nunca ocurre (ej. funciones que lanzan un error o bucles infinitos).function throwError(message: string): never { throw new Error(message); }
4. 📝 Anotaciones de Tipo
4.1. Variables
let count: number = 5;
let username: string = "Juan";
let isActiveUser: boolean = false;
4.2. Parámetros de Función y Retorno
function add(a: number, b: number): number {
return a + b;
}
const greet = (name: string): string => `Hello, ${name}`;
function log(message: string): void {
console.log(message);
}
5. 📦 Tipos Complejos
5.1. Arrays
let numbers: number[] = [1, 2, 3];
let names: Array<string> = ["Ana", "Luis"]; // Sintaxis genérica
5.2. Objetos
let user: { id: number; name: string; isActive?: boolean } = { // `?` para propiedad opcional
id: 1,
name: "Carlos",
};
user.isActive = true;
5.3. Tuplas
Arrays con un número fijo de elementos y tipos específicos en cada posición.
let person: [string, number] = ["Maria", 28];
// let invalidPerson: [string, number] = [28, "Maria"]; // Error
6. 🤝 Uniones e Intersecciones
6.1. Tipos de Unión (|)
Un valor puede ser de uno de los tipos especificados.
let id: number | string = 123;
id = "abc"; // Válido
// id = true; // Error
function printId(id: number | string): void {
if (typeof id === "string") {
console.log(id.toUpperCase());
} else {
console.log(id.toFixed(2));
}
}
6.2. Tipos de Intersección (&)
Combina múltiples tipos en uno solo, un valor debe ser de todos los tipos.
type Draggable = {
drag: () => void;
};
type Resizable = {
resize: () => void;
};
type UIWidget = Draggable & Resizable; // Debe tener ambos métodos
let widget: UIWidget = {
drag: () => console.log("Dragging"),
resize: () => console.log("Resizing"),
};
7. 🏷️ Tipos Personalizados
7.1. Interfaces
Definen la forma de los objetos. Pueden ser implementadas por clases y extendidas.
interface User {
readonly id: number; // Propiedad de solo lectura
name: string;
email?: string; // Propiedad opcional
}
interface AdminUser extends User { // Extiende la interfaz User
role: "admin" | "superadmin"; // Tipo literal de unión
permissions: string[];
}
const normalUser: User = { id: 1, name: "Alice" };
const admin: AdminUser = { id: 2, name: "Bob", role: "admin", permissions: ["manage_users"] };
// normalUser.id = 3; // Error: id es readonly
7.2. Alias de Tipo (type)
Crea un nuevo nombre para un tipo existente. Puede ser usado para cualquier tipo (primitivos, uniones, tuplas, objetos). No puede ser implementado por clases, pero puede ser extendido por intersecciones.
type Age = number;
type UserID = string | number;
type Point = {
x: number;
y: number;
};
type CardSuit = "Clubs" | "Diamonds" | "Hearts" | "Spades"; // Tipos literales
const myAge: Age = 25;
const center: Point = { x: 10, y: 20 };
const suit: CardSuit = "Clubs";
Diferencias clave interface vs type:
interfacepuede serdeclaradavarias veces y se fusionarán (Declaration Merging).typeno.interfacese usa para definir la forma deobjetosprincipalmente, y para clases.typees más flexible, puede aliasar primitivos, uniones, intersecciones, etc.- Generalmente,
interfacepara objetos/clases,typepara todo lo demás o cuando se necesiten las características específicas detype.
8. 📊 Enums
Conjuntos de constantes con nombres fáciles de usar.
enum Direction {
Up, // 0 por defecto
Down, // 1
Left, // 2
Right // 3
}
console.log(Direction.Up); // 0
console.log(Direction[0]); // "Up"
enum Status {
Active = "ACTIVE",
Inactive = "INACTIVE",
Pending = "PENDING"
}
console.log(Status.Active); // "ACTIVE"
// Uso con otros tipos
function setUserStatus(status: Status): void {
console.log(`User status set to: ${status}`);
}
setUserStatus(Status.Active);
9. 🚀 Genéricos (Generics)
Permiten escribir componentes o funciones que pueden trabajar con una variedad de tipos en lugar de uno solo, sin perder la seguridad de tipos.
function identity<T>(arg: T): T { // `T` es un placeholder para el tipo
return arg;
}
let output1 = identity<string>("myString"); // output1 es de tipo string
let output2 = identity<number>(100); // output2 es de tipo number
interface Box<T> { // Interfaz genérica
value: T;
}
const stringBox: Box<string> = { value: "Hello" };
const numberBox: Box<number> = { value: 123 };
// Restricciones de tipo (Constraints)
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T { // `T` debe tener una propiedad `length`
console.log(arg.length);
return arg;
}
loggingIdentity("hello"); // Válido
loggingIdentity([1, 2, 3]); // Válido
// loggingIdentity(5); // Error: number no tiene 'length'
10. 🏷️ Afirmaciones de Tipo (Type Assertions)
Le dices al compilador que sabes más sobre el tipo de un valor de lo que él puede inferir. No realizan comprobaciones en tiempo de ejecución.
- Sintaxis
as type(preferida en TSX). - Sintaxis
<type>value.
let someValue: unknown = "this is a string";
let strLength: number = (someValue as string).length; // "someValue" es tratado como string
// let strLength: number = (<string>someValue).length; // Sintaxis alternativa
const inputElement = document.getElementById("myInput") as HTMLInputElement;
// inputElement.value ahora tiene acceso a la propiedad 'value'
11. 🛡️ Guardas de Tipo (Type Guards)
Permiten reducir el tipo de una variable dentro de un bloque condicional.
typeof: Para tipos primitivos.instanceof: Para clases.- Guardas de Tipo Personalizadas: Funciones que devuelven un predicado de tipo (
parameter is Type).
// typeof
function printValue(value: string | number) {
if (typeof value === "string") {
console.log(value.toLowerCase()); // 'value' es string aquí
} else {
console.log(value.toFixed(2)); // 'value' es number aquí
}
}
// instanceof
class Cat {
meow() { console.log("Meow!"); }
}
class Dog {
bark() { console.log("Woof!"); }
}
function makeSound(animal: Cat | Dog) {
if (animal instanceof Cat) {
animal.meow();
} else {
animal.bark();
}
}
// Guarda de Tipo Personalizada
interface Bird {
fly: () => void;
}
interface Fish {
swim: () => void;
}
function isBird(pet: Bird | Fish): pet is Bird { // Predicado de tipo
return (pet as Bird).fly !== undefined;
}
function move(pet: Bird | Fish) {
if (isBird(pet)) {
pet.fly();
} else {
pet.swim();
}
}
12. 👻 Nulos y Definidos (Null & Undefined)
-
strictNullChecks: Opción del compilador (muy recomendada). Si estrue,nullyundefinedsolo pueden ser asignados aany, sus propios tipos, o uniones que los incluyan.let username: string = "Bob"; // username = null; // Error si strictNullChecks es true let optionalName: string | null = null; // Válido -
Encadenamiento Opcional (
?.): Accede a propiedades de un objeto que podría sernulloundefinedsin lanzar un error.interface UserProfile { name: string; address?: { street: string; city: string; }; } let user: UserProfile = { name: "John" }; console.log(user.address?.street); // undefined (no hay error) -
Coalescencia Nula (
??): Proporciona un valor por defecto si una expresión esnulloundefined(a diferencia de||que también captura0,"",false).let value: number | null = null; let result = value ?? 100; // result es 100 let emptyString: string = ""; let name = emptyString ?? "Default Name"; // name es "" -
Operador de Asignación No Nula (
!): Le dice al compilador que sabes que una variable no seránulloundefineden ese punto. Usar con extrema precaución.function greet(name: string | null) { // console.log(name.toUpperCase()); // Error si strictNullChecks es true console.log(name!.toUpperCase()); // Asume que 'name' no será null } greet("Alice"); // greet(null); // Esto causaría un error en tiempo de ejecución
13. 🛠️ Tipos de Utilidad (Built-in Utility Types)
Funciones genéricas que transforman tipos.
Partial<T>: Hace que todas las propiedades deTsean opcionales.interface Todo { title: string; description: string; completed: boolean; } type PartialTodo = Partial<Todo>; // { title?: string; description?: string; completed?: boolean; }Readonly<T>: Hace que todas las propiedades deTsean de solo lectura.type ReadonlyTodo = Readonly<Todo>; // { readonly title: string; readonly description: string; readonly completed: boolean; }Pick<T, K>: Construye un tipo seleccionando un conjunto de propiedadesKdeT.type TodoPreview = Pick<Todo, "title" | "completed">; // { title: string; completed: boolean; }Omit<T, K>: Construye un tipo seleccionando todas las propiedades deTexceptoK.type TodoWithoutDescription = Omit<Todo, "description">; // { title: string; completed: boolean; }Exclude<UnionType, ExcludedMembers>: Excluye deUnionTypetodos los miembros que son asignables aExcludedMembers.type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"Extract<Type, Union>: Extrae deTypetodos los miembros que son asignables aUnion.type T0 = Extract<"a" | "b" | "c", "a" | "f">; // "a"NonNullable<T>: ExcluyenullyundefineddeT.type T0 = NonNullable<string | number | undefined>; // string | numberParameters<T>: Obtiene los tipos de los parámetros de una funciónTcomo una tupla.function f1(arg: { a: number, b: string }) {} type T0 = Parameters<typeof f1>; // [{ a: number, b: string }]ReturnType<T>: Obtiene el tipo de retorno de una funciónT.type T0 = ReturnType<typeof f1>; // voidAwaited<T>: Extrae el tipo resuelto de una Promesa.type PromiseType = Promise<string>; type Result = Awaited<PromiseType>; // string
14. 💡 Buenas Prácticas y Consejos
- Habilita
strictentsconfig.json: Esto activa todas las comprobaciones de tipo estrictas y ayuda a escribir código más robusto. - Inferencia vs. Anotación: Deja que TypeScript infiera los tipos cuando sea obvio. Anota explícitamente cuando no sea claro, para parámetros de función, y para retornos de función.
- Usa
interfacepara objetos/clases,typepara todo lo demás: Una convención común que ayuda a la consistencia. - Evita
anysiempre que sea posible:anyderrota el propósito de TypeScript. Usaunknownsi el tipo es verdaderamente desconocido y luego refínalo con guardas de tipo. - Escribe tests para tipos complejos: Si tienes transformaciones de tipo o lógica compleja, usa
expectType(de librerías comodts-jestotsd) para verificar que tus tipos se comportan como esperas. - Organiza tus tipos: Coloca las definiciones de tipo en archivos
.d.ts(declaración) o en archivos.tsdedicados cuando los tipos sean complejos o reutilizables. - Aprovecha el IDE: Tu editor de código es tu mejor amigo con TypeScript. Usa el autocompletado, la refactorización y la detección de errores.
- Documenta tus tipos: Para tipos complejos o API públicas, añade comentarios JSDoc para explicar su propósito.
- Aprende sobre
utility types: Te ahorrarán mucho tiempo y código repetitivo.
Este cheatsheet te proporciona una referencia completa y concisa de TypeScript, cubriendo los fundamentos y las características esenciales para escribir código seguro, mantenible y escalable.