Arquitectura Empresarial en TypeScript: Genéricos Avanzados y Tipado Estricto
Lo Que Dominarás en Este Tutorial
- Diseñar clientes de API tipados con genéricos e inferencia de tipos de retorno
- Eliminar errores en tiempo de ejecución mediante uniones discriminadas y comprobaciones exhaustivas
- Aprovechar los predicados de tipo inferidos en TypeScript 5.5+ para validar datos JSON externos
- Dominar utilidades avanzadas: ReturnType, Parameters, Omit, Pick y DeepReadonly
type AsyncState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; error: Error };
function renderState<T>(state: AsyncState<T>): string {
switch (state.status) {
case 'idle':
return 'Esperando acción...';
case 'loading':
return 'Descargando datos...';
case 'success':
return `Datos cargados: ${JSON.stringify(state.data)}`;
case 'error':
return `Error: ${state.error.message}`;
}
}
Preguntas Frecuentes
Profundizando: los genéricos y el tipado estricto en la práctica
El patrón en el corazón de este tutorial —una unión discriminada genérica como AsyncState<T> con un switch exhaustivo— es la forma en que las grandes bases de código en TypeScript se mantienen refactorizables. En la práctica, los genéricos se ganan su sitio en tres lugares: envoltorios de clientes de API que infieren los tipos de respuesta en lugar de forzarlos con castings, máquinas de estados cuyos estados imposibles se vuelven irrepresentables, y fronteras por donde entra JSON no confiable, donde los predicados de tipo inferidos de TypeScript 5.5 ayudan a sanear los datos antes de que se propaguen. Tipos utilitarios como ReturnType, Parameters, Pick, Omit y un DeepReadonly personalizado mantienen después cada tipo derivado en sincronía automática. La disciplina es la contención: cada genérico debería eliminar un casting o un tipo duplicado, no decorar el código.
Errores comunes
- Recurrir a any. Cada any apaga el comprobador justo donde el código empresarial más lo necesita; unknown combinado con estrechamiento mantiene la garantía y obliga a un tratamiento honesto.
- Switches no exhaustivos. Un switch sobre una unión sin una comprobación never en la rama por defecto compila hoy sin problemas y se comporta mal en silencio cuando alguien añada mañana una variante nueva.
- Confiar en los tipos en tiempo de ejecución. Los tipos se borran al compilar, así que una respuesta de API tipada no es más que una afirmación; los datos externos siguen necesitando validación en tiempo de ejecución antes de que la aplicación se apoye en ellos.
- Genéricos sobreingenierizados. La gimnasia de tipos que nadie del equipo puede leer es un lastre; si un genérico no elimina duplicación ni un casting, un tipo concreto es mejor.
Preguntas frecuentes
¿Los tipos complejos ralentizan la aplicación en ejecución?
No. Como indica la sección de preguntas de este tutorial, los tipos de TypeScript se borran por completo durante la compilación, así que el rendimiento en tiempo de ejecución es puramente el del JavaScript emitido.
¿Cuándo debería modelar el estado como una unión discriminada?
Siempre que los estados sean mutuamente excluyentes y carguen datos distintos —como idle, loading, success y error—, porque entonces el compilador obliga a cada consumidor a tratar cada caso.
¿Qué es un predicado de tipo inferido en TypeScript 5.5?
Permite que el compilador deduzca que una función de filtro también es una guarda de tipo, de modo que sanear JSON no confiable con una llamada a .filter estrecha automáticamente el tipo del arreglo resultante: una de las técnicas que este tutorial usa para limpiar datos entrantes sin afirmaciones de tipo manuales.