Lección 87 — Tipos Literales y Const Assertions
🧠 Concepto
Section titled “🧠 Concepto”Los tipos literales permiten especificar valores exactos como tipos. Las const assertions (as const) convierten un valor mutable en un tipo inmutable y preciso.
Tipos literales
Section titled “Tipos literales”Un tipo literal no es solo string o number, sino un valor específico:
type Color = 'rojo' | 'verde' | 'azul';type Direccion = 'norte' | 'sur' | 'este' | 'oeste';type Puerto = 3000 | 3001 | 8080;
let miColor: Color = 'rojo'; // ✅let miColor2: Color = 'amarillo'; // ❌ ErrorLos tipos literales suelen combinarse con union types para crear opciones fijas.
const assertions (as const)
Section titled “const assertions (as const)”Cuando usas as const al final de un valor, TS infiere el tipo más específico posible y marca todo como readonly:
// Sin as constlet colores = ['rojo', 'verde', 'azul'];// tipo: string[]
// Con as constconst coloresConst = ['rojo', 'verde', 'azul'] as const;// tipo: readonly ['rojo', 'verde', 'azul']Efectos de as const
Section titled “Efectos de as const”- Literales en lugar de tipos generales: los valores se convierten en sus tipos literales.
- readonly en arrays y objetos: no se pueden modificar.
- Anidación profunda: afecta a todas las propiedades anidadas.
const config = { url: 'https://api.example.com', puerto: 443, opciones: { timeout: 5000, retries: 3 }} as const;
// config.url = 'otra'; ❌ readonly// config.opciones.timeout = 3000; ❌ readonly// Tipo inferido:// {// readonly url: 'https://api.example.com';// readonly puerto: 443;// readonly opciones: {// readonly timeout: 5000;// readonly retries: 3;// };// }💻 Ejemplo
Section titled “💻 Ejemplo”// Tipos literales para una máquina de estadostype EstadoPedido = 'pendiente' | 'confirmado' | 'enviado' | 'entregado' | 'cancelado';
function transicionEstado(actual: EstadoPedido, nuevo: EstadoPedido): EstadoPedido { if (actual === 'cancelado') { throw new Error('No se puede cambiar un pedido cancelado'); } return nuevo;}
// as const en arraysconst DIAS_LABORABLES = ['lun', 'mar', 'mié', 'jue', 'vie'] as const;type DiaLaborable = typeof DIAS_LABORABLES[number]; // 'lun' | 'mar' | 'mié' | 'jue' | 'vie'
function esLaborable(dia: string): dia is DiaLaborable { return DIAS_LABORABLES.includes(dia as DiaLaborable);}
// as const en objetosconst ROLES = { ADMIN: 'admin', EDITOR: 'editor', VISOR: 'visor'} as const;
type Rol = typeof ROLES[keyof typeof ROLES]; // 'admin' | 'editor' | 'visor'
function tienePermiso(rol: Rol, accion: string): boolean { if (rol === ROLES.ADMIN) return true; if (rol === ROLES.EDITOR) return accion !== 'eliminar'; return accion === 'leer';}📝 Ejercicio
Section titled “📝 Ejercicio”Define un objeto CONFIG_APP con as const que contenga:
nombreApp: 'MiApp'version: '2.0.0'entornos: ['dev', 'staging', 'prod']como array
Usa typeof y keyof para extraer:
- El tipo
NombreApp(literal) - El tipo
Entorno(unión de los valores del array) - El tipo
Version(literal)
⚠️ Nota
Section titled “⚠️ Nota”as const no convierte el valor en una constante JS (eso ya lo hace const). Lo que hace es cambiar cómo TypeScript infiere el tipo. El valor sigue siendo mutable en runtime si no usas const o medidas adicionales.
Combina as const con typeof para extraer tipos literales de configuraciones y constantes. Es una técnica muy potente para mantener una única fuente de verdad: defines los valores una vez y derivas los tipos automáticamente.