Skip to content

Tipos básicos ​

Los tipos son el vocabulario de TypeScript. En esta lección aprenderás a describir los datos más comunes: textos, números, listas, valores que pueden faltar y conjuntos de opciones fijas. Con esto ya podrás tipar el 80% del código que escribes a diario.

Concepto ​

Un tipo es un conjunto de valores permitidos. number es el conjunto de todos los números; boolean solo tiene dos valores (true y false); el tipo literal 'admin' tiene un único valor. Cuando anotas una variable, le dices a TS: "aquí solo puede haber valores de este conjunto".

La sintaxis es siempre la misma: dos puntos después del nombre.

ts
let nombre: string = 'Ana';

Primitivos: string, number, boolean ​

ts
const producto: string = 'Audífonos';
const precio: number = 899.5;        // enteros y decimales son number
const enOferta: boolean = false;

// Plantillas de texto también son string
const etiqueta: string = `${producto} - $${precio}`;

// Otros primitivos menos comunes
const grande: bigint = 9007199254740993n;
const id: symbol = Symbol('id');

Error común

Usa los tipos en minúscula: string, number, boolean. Los que empiezan con mayúscula (String, Number, Boolean) son los objetos envoltorio de JavaScript y casi nunca los quieres.

Inferencia de tipos ​

No necesitas anotar todo. TypeScript infiere el tipo a partir del valor inicial:

ts
let ciudad = 'Monterrey';   // TS infiere: string
let edad = 30;              // number
let activo = true;          // boolean

ciudad = 42;
// ❌ Type 'number' is not assignable to type 'string'.

// Con const, TS infiere el tipo más preciso posible: el literal
const rol = 'admin';        // tipo: 'admin' (no solo string)

Pasa el cursor sobre una variable en VS Code y verás el tipo inferido.

Buena práctica

Deja que TS infiera las variables locales y anota los parámetros de funciones, los retornos de funciones públicas y los datos que vienen de fuera (APIs, formularios). Anotar const x: number = 5 es ruido.

Arrays ​

Dos sintaxis equivalentes:

ts
const precios: number[] = [100, 250, 80];
const nombres: Array<string> = ['Ana', 'Luis'];

precios.push('gratis');
// ❌ Argument of type 'string' is not assignable to parameter of type 'number'.

// Arrays de objetos
const usuarios: { nombre: string; edad: number }[] = [
  { nombre: 'Ana', edad: 28 },
  { nombre: 'Luis', edad: 34 }
];

// Arrays de solo lectura: no se pueden modificar
const dias: readonly string[] = ['lun', 'mar', 'mié'];
dias.push('jue');
// ❌ Property 'push' does not exist on type 'readonly string[]'.

La forma number[] es la más común; Array<number> usa la sintaxis de genéricos que verás en Genéricos.

Tuplas ​

Una tupla es un array con longitud fija y un tipo por posición. Útil para pares de valores:

ts
// [latitud, longitud]
const coordenadas: [number, number] = [20.96, -89.62];

// [nombre, edad, activo]
const fila: [string, number, boolean] = ['Ana', 28, true];

// Tuplas con nombres (solo documentan, mejoran el autocompletado)
type Rango = [inicio: number, fin: number];
const horario: Rango = [9, 18];

// Así devuelve React su useState: una tupla [valor, función]
function usarContador(): [number, () => void] {
  let valor = 0;
  return [valor, () => { valor++; }];
}
const [conteo, incrementar] = usarContador();

Uniones ​

Una unión dice "puede ser esto o aquello". Se escribe con la barra vertical:

ts
let id: string | number;
id = 101;       // ✅
id = 'A-101';   // ✅
id = true;      // ❌

// Muy común: un valor o null
let usuarioActual: string | null = null;
usuarioActual = 'ana@correo.com';

Con una unión solo puedes usar lo que es común a todos los miembros. Para usar algo específico tienes que comprobar el tipo primero:

ts
function formatearId(id: string | number): string {
  // id.toUpperCase(); ❌ number no tiene toUpperCase
  if (typeof id === 'string') {
    return id.toUpperCase();      // aquí TS sabe que es string
  }
  return id.toString().padStart(5, '0'); // aquí es number
}

A esto se le llama narrowing (estrechamiento) y tiene su propia lección: Narrowing.

Tipos literales ​

Un tipo literal es un valor exacto. Combinados con uniones, crean listas de opciones válidas:

ts
type Estado = 'pendiente' | 'enviado' | 'entregado' | 'cancelado';
type Talla = 'S' | 'M' | 'L' | 'XL';
type Dado = 1 | 2 | 3 | 4 | 5 | 6;

let estadoPedido: Estado = 'pendiente';
estadoPedido = 'enviado';    // ✅
estadoPedido = 'perdido';
// ❌ Type '"perdido"' is not assignable to type 'Estado'.

function cambiarTema(tema: 'claro' | 'oscuro') {
  document.body.dataset.tema = tema;
}
cambiarTema('oscuro');  // ✅ y el editor te autocompleta las opciones

Esto es oro en proyectos reales: estados de pedidos, roles de usuarios, variantes de botones, métodos HTTP.

null y undefined con strict ​

Con strict: true, null y undefined son tipos propios. Un string no puede ser null a menos que lo digas:

ts
let nombre: string = null;
// ❌ Type 'null' is not assignable to type 'string'.

let apodo: string | null = null;           // ✅ explícito
let telefono: string | undefined;          // ✅ puede no tener valor

// TS te obliga a comprobar antes de usar
function longitud(texto: string | null): number {
  // return texto.length; ❌ 'texto' is possibly 'null'.
  return texto?.length ?? 0;               // ✅
}

Esto elimina los famosos "Cannot read properties of null".

any vs unknown ​

Ambos aceptan cualquier valor, pero se comportan de forma opuesta:

  • any apaga TypeScript. Puedes hacer lo que quieras con él y TS no te avisa de nada.
  • unknown es la versión segura: acepta cualquier cosa, pero no te deja usarlo hasta que compruebes qué es.
ts
let a: any = 'hola';
a.metodoQueNoExiste();   // TS no se queja... 💥 explota al ejecutar
a = 5;
a.toUpperCase();         // tampoco se queja

let u: unknown = 'hola';
u.toUpperCase();
// ❌ 'u' is of type 'unknown'.

if (typeof u === 'string') {
  u.toUpperCase();       // ✅ ahora sí: comprobaste que es string
}

// Caso real: JSON.parse devuelve any; tú lo tratas como unknown
const datos: unknown = JSON.parse('{"precio": 100}');

Buena práctica

Evita any. Cuando no sepas qué tipo llega (una API, JSON.parse, un catch), usa unknown y valida. Es como recibir un paquete sin etiqueta: lo revisas antes de usarlo.

void y never ​

  • void: la función no devuelve nada útil.
  • never: la función nunca termina (lanza un error o es un bucle infinito), o un valor que no puede existir.
ts
function registrar(mensaje: string): void {
  console.log(`[LOG] ${mensaje}`);
}

function fallar(mensaje: string): never {
  throw new Error(mensaje);
}

// never también aparece cuando una unión se queda sin opciones
function describir(x: string | number) {
  if (typeof x === 'string') return 'texto';
  if (typeof x === 'number') return 'número';
  const imposible: never = x;   // aquí x ya no puede ser nada
  return imposible;
}

Verás never en acción para revisar exhaustividad en Narrowing.

Enums vs uniones de literales ​

TypeScript tiene enum, una forma de nombrar un conjunto de constantes:

ts
enum EstadoPedido {
  Pendiente = 'pendiente',
  Enviado = 'enviado',
  Entregado = 'entregado'
}

let e: EstadoPedido = EstadoPedido.Enviado;
console.log(e); // 'enviado'

Pero los enums tienen detalles incómodos: generan código JavaScript extra (son de las pocas cosas de TS que no se borran), los numéricos aceptan números arbitrarios y no funcionan con el modo de Node que solo quita tipos. Hoy la mayoría de los equipos prefieren uniones de literales:

ts
type EstadoPedido = 'pendiente' | 'enviado' | 'entregado';

let estado: EstadoPedido = 'enviado';  // simple, sin código extra

Si además necesitas la lista de valores en tiempo de ejecución (para un <select>, por ejemplo), usa as const.

as const ​

as const le dice a TS: "trata este valor como constante y lo más preciso posible". Los arrays se vuelven tuplas de solo lectura y los strings se vuelven literales:

ts
const colores = ['rojo', 'verde', 'azul'];
// tipo: string[]

const coloresFijos = ['rojo', 'verde', 'azul'] as const;
// tipo: readonly ['rojo', 'verde', 'azul']

// Derivar una unión desde el array: ¡una sola fuente de verdad!
const ESTADOS = ['pendiente', 'enviado', 'entregado'] as const;
type Estado = (typeof ESTADOS)[number];
// 'pendiente' | 'enviado' | 'entregado'

// Ahora puedes recorrer los valores y también usarlos como tipo
ESTADOS.forEach((e) => console.log(e));

// Objetos de configuración
const CONFIG = {
  apiUrl: 'https://api.mitienda.mx',
  reintentos: 3
} as const;
// CONFIG.reintentos = 5; ❌ es readonly

El truco (typeof ESTADOS)[number] significa "el tipo de cualquier elemento del array". Lo usarás mucho.

Ejercicios ​

  1. Declara (con el tipo adecuado) un array de precios, una tupla [nombre, cantidad] y una variable que pueda ser string o null.
  2. Crea un tipo MetodoHttp con 'GET', 'POST', 'PUT' y 'DELETE', y una función peticion(url: string, metodo: MetodoHttp) que devuelva un texto como "GET /api/usuarios".
  3. Escribe una función aMayusculas(valor: unknown): string que devuelva el texto en mayúsculas si es string, y '' en cualquier otro caso.
  4. Con as const, crea un array ROLES con 'admin', 'editor' y 'lector', y deriva de él el tipo Rol.
Ver solución
ts
// 1
const precios: number[] = [120, 80, 45];
const linea: [string, number] = ['Café', 2];
let cupon: string | null = null;

// 2
type MetodoHttp = 'GET' | 'POST' | 'PUT' | 'DELETE';

function peticion(url: string, metodo: MetodoHttp): string {
  return `${metodo} ${url}`;
}
peticion('/api/usuarios', 'GET'); // 'GET /api/usuarios'

// 3
function aMayusculas(valor: unknown): string {
  if (typeof valor === 'string') {
    return valor.toUpperCase();
  }
  return '';
}

// 4
const ROLES = ['admin', 'editor', 'lector'] as const;
type Rol = (typeof ROLES)[number]; // 'admin' | 'editor' | 'lector'

Resumen ​

  • Primitivos: string, number, boolean (en minúscula).
  • TS infiere tipos; anota sobre todo parámetros y datos externos.
  • Arrays: number[] o Array<number>; tuplas: [number, number].
  • Uniones (A | B) y literales crean opciones precisas: 'claro' | 'oscuro'.
  • Con strict, null y undefined deben declararse explícitamente.
  • unknown en lugar de any: obliga a comprobar antes de usar.
  • void = no devuelve nada; never = nunca ocurre.
  • Prefiere uniones de literales sobre enum; usa as const para derivar tipos desde valores.

Siguiente: Interfaces y types

Academia Web — aprende, copia y construye.