Chuleta de TypeScript
Resumen de consulta rápida con lo esencial de TypeScript 5 en modo strict. Cada apartado enlaza a la lección donde se explica con calma.
Instalar y compilar
| Terminal | Qué hace |
|---|---|
npm init -y | Crea package.json |
npm install --save-dev typescript | Instala el compilador en el proyecto |
npx tsc --init | Crea tsconfig.json |
npx tsc | Compila el proyecto según tsconfig.json |
npx tsc app.ts | Compila un archivo suelto a app.js |
npx tsc --watch | Recompila al guardar |
npx tsc --noEmit | Solo comprueba tipos, sin generar JS |
node app.js | Ejecuta el JavaScript generado |
node app.ts | Node.js reciente ejecuta .ts directamente (sin comprobar tipos) |
npx tsx app.ts | Ejecuta .ts con tsx |
Consejo: los tipos desaparecen al compilar. Solo sirven para que el compilador te avise antes de ejecutar.
Más en: ¿Qué es TypeScript? · Instalar y compilar
Tipos básicos
| Código | Qué hace |
|---|---|
let nombre: string = "Ana"; | Texto |
let edad: number = 30; | Número (enteros y decimales) |
let activo: boolean = true; | Booleano |
const IVA = 0.21; | Con const el tipo es el valor: 0.21 |
let x = 5; | Inferencia: TypeScript deduce number |
let id: bigint = 10n; | Enteros muy grandes |
let a: null = null; | Solo admite null |
let u: undefined = undefined; | Solo admite undefined |
let dato: unknown; | Cualquier valor, pero hay que comprobarlo antes de usarlo |
let cualquiera: any; | Desactiva la comprobación: evítalo |
function fallar(): never { throw new Error("x"); } | Nunca devuelve nada |
function log(): void {} | No devuelve nada útil |
valor as string | Aserción de tipo: tú aseguras el tipo |
valor! | Aserción non-null: afirma que no es null |
valor satisfies Tipo | Comprueba el tipo sin ensancharlo |
Más en: Tipos básicos
Arrays y tuplas
| Código | Qué hace |
|---|---|
let nums: number[] = [1, 2, 3]; | Array de números |
let nombres: Array<string> = []; | Misma idea con sintaxis genérica |
let matriz: number[][] = [[1], [2]]; | Array de arrays |
const fijo: readonly number[] = [1, 2]; | Array de solo lectura |
let par: [string, number] = ["Ana", 30]; | Tupla: longitud y tipos fijos |
let pto: [x: number, y: number]; | Tupla con nombres |
let opc: [string, number?]; | Elemento opcional |
const [nombre, edad] = par; | Desestructura la tupla |
nums[5] | Tipo number (con noUncheckedIndexedAccess: number | undefined) |
nums.map(n => n * 2) | Se infiere number[] |
const colores = ["rojo", "azul"] as const; | Tupla de solo lectura con literales |
typeof colores[number] | "rojo" | "azul" |
Más en: Arrays y tuplas
Interfaces y type
interface Usuario {
readonly id: number;
nombre: string;
email?: string;
}
type Punto = { x: number; y: number };
| Código | Qué hace |
|---|---|
interface A { x: number } | Describe la forma de un objeto |
type A = { x: number } | Alias: también describe objetos |
email?: string | Propiedad opcional |
readonly id: number | No se puede reasignar |
interface B extends A { y: number } | Extiende una interfaz |
type C = A & { y: number } | Intersección: une tipos |
[clave: string]: number | Firma de índice: claves libres |
Record<string, number> | Objeto con claves string y valores number |
type Id = string | number; | Alias de una unión |
type Callback = (x: number) => void; | Alias de una función |
interface A { x: number } repetida | Se fusionan (solo con interface) |
typeof objeto | Tipo de un valor existente |
keyof Usuario | "id" | "nombre" | "email" |
Usuario["nombre"] | string (tipo de una propiedad) |
Consejo: usa
interfacepara objetos ytypepara uniones, tuplas y funciones.
Más en: Objetos e interfaces · Uniones y alias
Uniones y literales
| Código | Qué hace |
|---|---|
let id: string | number; | Acepta uno de los dos tipos |
let rol: "admin" | "user"; | Tipo literal: solo esos valores |
type Estado = "cargando" | "ok" | "error"; | Alias de literales |
let n: number | null = null; | Valor opcional explícito |
let a: 1 | 2 | 3; | Literales numéricos |
type Resp = { ok: true; datos: string } | { ok: false; error: string }; | Unión discriminada |
const r = "ok"; | Tipo "ok" (con let sería string) |
as const | Congela un objeto con literales de solo lectura |
type Ruta = `/${string}`; | Tipo plantilla: empieza por / |
type Resp =
| { ok: true; datos: string }
| { ok: false; error: string };
function mostrar(r: Resp): string {
return r.ok ? r.datos : r.error;
}
Más en: Uniones y alias
Narrowing
| Código | Qué hace |
|---|---|
typeof x === "string" | Dentro del if, x es string |
x instanceof Date | Dentro del if, x es Date |
"nombre" in obj | Comprueba si existe la propiedad |
Array.isArray(x) | Dentro del if, x es un array |
if (x) | Descarta null, undefined, 0 y "" |
x !== null | Descarta null |
x ?? "defecto" | Valor por defecto si es null o undefined |
x?.propiedad | Acceso seguro: undefined si x es nulo |
r.ok === true | Estrecha una unión discriminada |
function esTexto(x: unknown): x is string | Guarda de tipo propia |
function afirmar(x: unknown): asserts x is string | Función que lanza si no se cumple |
const _: never = valor; | Comprueba que cubriste todos los casos |
function longitud(x: string | string[]): number {
if (typeof x === "string") {
return x.length;
}
return x.length; // aquí x es string[]
}
Más en: Narrowing
Funciones
function precioFinal(precio: number, iva: number = 0.21): number {
return Math.round(precio * (1 + iva) * 100) / 100;
}
const saludar = (nombre: string): string => `Hola, ${nombre}`;
| Código | Qué hace |
|---|---|
(a: number, b: number): number | Tipos de parámetros y de retorno |
(x?: number) | Parámetro opcional (number | undefined) |
(x = 10) | Valor por defecto (se infiere number) |
(...nums: number[]) | Parámetros rest |
(): void | No devuelve nada |
type Op = (a: number, b: number) => number; | Tipo de una función |
(cb: (x: number) => void) | Parámetro que es una función |
(): Promise<string> | Función asíncrona |
(this: Elemento) | Declara el tipo de this |
function f(x: string): string; | Sobrecarga: firma antes de la implementación |
(obj: { id: number; nombre: string }) | Parámetro con forma de objeto |
([a, b]: [number, number]) | Desestructura una tupla |
ReturnType<typeof f> | Tipo que devuelve f |
Parameters<typeof f> | Tupla con los parámetros de f |
Más en: Funciones
Clases
class Cuenta {
static total = 0;
constructor(
public readonly titular: string,
private saldo: number = 0,
) {
Cuenta.total++;
}
ingresar(cantidad: number): void {
this.saldo += cantidad;
}
get balance(): number {
return this.saldo;
}
}
| Código | Qué hace |
|---|---|
public / private / protected | Visibilidad (solo en compilación) |
#saldo = 0; | Privado de verdad también en JavaScript |
readonly id: number | Solo se asigna en el constructor |
constructor(private x: number) {} | Declara y asigna la propiedad |
class B extends A { ... } | Herencia |
super(x) | Llama al constructor del padre |
override metodo() {} | Marca que sobrescribe uno del padre |
class A implements Interfaz { ... } | La clase cumple un contrato |
abstract class Figura { abstract area(): number; } | Clase que no se instancia |
static contar() {} | Método de la clase |
get x() / set x(v) | Getter y setter |
class Caja<T> { ... } | Clase genérica |
x: string; sin valor | Error en strict: inicialízala en el constructor |
x!: string; | Afirma que se asignará más tarde |
Más en: Clases
Enums
| Código | Qué hace |
|---|---|
enum Dir { Arriba, Abajo } | Enum numérico: Dir.Arriba vale 0 |
enum Dir { Arriba = 1, Abajo } | Empieza en 1: Abajo vale 2 |
enum Color { Rojo = "ROJO" } | Enum de texto |
const enum Dir { ... } | Se sustituye por el valor al compilar |
Dir[0] | "Arriba" (solo enums numéricos) |
let d: Dir = Dir.Abajo; | Variable del tipo del enum |
keyof typeof Color | Unión de los nombres: "Rojo" |
const Rol = { Admin: "admin", User: "user" } as const; | Alternativa sin enum |
type Rol = typeof Rol[keyof typeof Rol]; | "admin" | "user" |
Consejo: muchas veces basta una unión de literales:
type Rol = "admin" \| "user". Es más simple y no genera código.
Más en: Enums
Genéricos
function primero<T>(lista: T[]): T | undefined {
return lista[0];
}
const n = primero([1, 2, 3]); // number | undefined
const s = primero(["a", "b"]); // string | undefined
| Código | Qué hace |
|---|---|
function f<T>(x: T): T | Función genérica |
f<string>("a") | Indica el tipo a mano |
interface Caja<T> { valor: T } | Interfaz genérica |
type Par<A, B> = [A, B]; | Alias con varios parámetros |
<T extends { id: number }> | Restricción: T debe tener id |
<T, K extends keyof T>(obj: T, k: K): T[K] | Lee una propiedad con su tipo exacto |
<T = string> | Tipo por defecto |
Promise<T> | Promesa que resuelve a T |
Array<T> / Map<K, V> / Set<T> | Tipos genéricos integrados |
async function cargar<T>(url: string): Promise<T> | Función genérica asíncrona |
Más en: Genéricos
Tipos utilitarios
Código (con Usuario { id, nombre, email }) | Resultado |
|---|---|
Partial<Usuario> | Todas las propiedades opcionales |
Required<Usuario> | Todas obligatorias |
Readonly<Usuario> | Todas de solo lectura |
Pick<Usuario, "id" | "nombre"> | Solo esas propiedades |
Omit<Usuario, "email"> | Todas menos email |
Record<"a" | "b", number> | { a: number; b: number } |
Exclude<"a" | "b" | "c", "a"> | "b" | "c" |
Extract<"a" | "b", "a" | "z"> | "a" |
NonNullable<string | null> | string |
ReturnType<typeof f> | Tipo que devuelve f |
Parameters<typeof f> | Tupla con los parámetros de f |
Awaited<Promise<string>> | string |
keyof Usuario | "id" | "nombre" | "email" |
{ [K in keyof T]: boolean } | Tipo mapeado: recorre las claves |
Más en: Tipos utilitarios
Módulos
| Código | Qué hace |
|---|---|
export function sumar() {} | Exporta desde un módulo |
export default class Carrito {} | Exportación por defecto |
export type { Usuario }; | Exporta solo un tipo |
import { sumar } from "./utils.js"; | Importa con nombre |
import type { Usuario } from "./tipos.js"; | Importa solo el tipo (se borra al compilar) |
import * as util from "./utils.js"; | Importa todo en un objeto |
declare module "libreria"; | Declara tipos de un módulo sin ellos |
npm install --save-dev @types/node | Instala tipos de una librería |
.d.ts | Archivo solo de declaraciones de tipos |
Cuidado: en módulos de Node.js escribe la extensión
.jsen el import, aunque el archivo sea.ts.
Más en: Módulos y tsconfig
tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"strict": true,
"outDir": "dist",
"rootDir": "src",
"noUncheckedIndexedAccess": true,
"skipLibCheck": true
},
"include": ["src"]
}
Opción de tsconfig.json | Qué hace |
|---|---|
"strict": true | Activa todas las comprobaciones estrictas |
"target" | Versión de JavaScript que genera |
"module" | Sistema de módulos de salida |
"outDir" / "rootDir" | Carpeta de salida / de origen |
"noUncheckedIndexedAccess" | Los índices de array pueden dar undefined |
"noImplicitAny" | Prohíbe any implícito (incluido en strict) |
"strictNullChecks" | null y undefined no valen para todo (incluido en strict) |
"lib": ["ES2022", "DOM"] | Tipos disponibles (DOM para navegador) |
"include" / "exclude" | Qué archivos entran en el proyecto |
Más en: Módulos y tsconfig · Instalar y compilar
DOM
| Código | Qué hace |
|---|---|
document.querySelector("h1") | HTMLHeadingElement | null |
document.querySelector<HTMLInputElement>("#email") | HTMLInputElement | null |
document.getElementById("menu") | HTMLElement | null |
if (el) { ... } | Comprueba que no sea null antes de usarlo |
el?.classList.add("activo") | Acceso seguro |
document.querySelector("#x") as HTMLButtonElement | Aserción: tú aseguras que existe |
input.value | string (solo en inputs) |
input.valueAsNumber | number |
boton.addEventListener("click", (e: MouseEvent) => { ... }) | Evento con tipo |
form.addEventListener("submit", (e: SubmitEvent) => ...) | Envío de formulario |
e.target as HTMLInputElement | Elemento que originó el evento |
e.currentTarget | Elemento al que está pegado el listener |
new FormData(form) | Recoge los campos |
document.createElement("li") | HTMLLIElement |
"lib": ["DOM"] en tsconfig.json | Necesario para tener los tipos del DOM |
const input = document.querySelector<HTMLInputElement>("#nombre");
const boton = document.querySelector<HTMLButtonElement>("#enviar");
boton?.addEventListener("click", () => {
if (input) {
console.log(input.value.trim());
}
});
Más en: DOM con TypeScript · Proyecto
TypeScript · devschool.es/chuletas/typescript/