Introducción: por qué la documentación es una inversión, no una pérdida de tiempo
Cada desarrollador se ha enfrentado a la situación: al volver a tu propio código después de un mes, apenas recuerdas para qué sirve tal o cual parámetro. Qué decir de los nuevos miembros del equipo que intentan entender tu proyecto. La documentación de calidad para un proyecto TypeScript no es solo un complemento agradable, sino un elemento críticamente importante que acelera la incorporación, reduce la cantidad de errores y hace que el código sea mantenible.
TypeScript, al ser una extensión de JavaScript, proporciona un potente sistema de tipos. Sin embargo, los tipos por sí solos no siempre responden a la pregunta "por qué". La documentación llena ese vacío. En este artículo, analizaremos el ciclo completo: desde la elección del estilo de comentarios hasta la generación de un sitio estático con documentación.
1. Fundamentos: JSDoc, TSDoc y TypeScript
Para documentar código TypeScript, históricamente han surgido dos estándares principales: JSDoc y TSDoc. JSDoc es el viejo y querido formato que proviene del mundo de JavaScript. TSDoc es un estándar más moderno, optimizado específicamente para TypeScript. Ambos enfoques utilizan comentarios en el formato /** ... */.
Veamos un ejemplo básico usando JSDoc:
/** * Calcula la suma de dos números. * @param a - Primer sumando * @param b - Segundo sumando * @returns Suma de a y b */function add(a: number, b: number): number { return a + b;}Así es como se ve en el estilo TSDoc usando las etiquetas @param y @returns:
/** * Calcula la suma de dos números. * @param a - Primer sumando * @param b - Segundo sumando * @returns Suma de a y b */function add(a: number, b: number): number { return a + b;}La diferencia es mínima, pero TSDoc agrega soporte para construcciones específicas de TypeScript, como genéricos y tipos condicionales.
1.1 Documentación de interfaces y tipos
Se debe prestar especial atención a las interfaces y tipos. Son el "esqueleto" de un proyecto TypeScript. Aquí hay un ejemplo de una interfaz bien documentada:
/** * Representa un usuario del sistema. */interface User { /** Identificador único del usuario */ id: string; /** Nombre completo del usuario */ name: string; /** Dirección de correo electrónico (debe ser única) */ email: string; /** Fecha del último inicio de sesión en el sistema (opcional) */ lastLogin?: Date; /** Rol del usuario en el sistema */ role: 'admin' | 'user' | 'moderator';}Observa: cada parámetro de la interfaz tiene su propio comentario /** ... */. Esto permite que el IDE (por ejemplo, VS Code) muestre sugerencias al usar esta interfaz.
2. Técnicas avanzadas: genéricos y tipos condicionales
TypeScript es famoso por su sistema de tipos, y la documentación debe reflejar su complejidad. Esto se aplica especialmente a los genéricos (generic types) y los tipos condicionales (conditional types).
Veamos un ejemplo de un genérico con documentación:
/** * Crea un array a partir de un solo elemento de tipo T. * @template T - Tipo del elemento que se colocará en el array * @param item - Elemento a envolver * @returns Array que contiene el elemento pasado */function wrapInArray<T>(item: T): T[] { return [item];}La etiqueta @template indica explícitamente qué es T. Esto es especialmente útil cuando hay varios genéricos o tienen una relación compleja.
Para los tipos condicionales, la documentación se vuelve aún más importante. Ejemplo:
/** * Extrae el tipo de valor de un Promise, si se pasa un Promise. * De lo contrario, devuelve el tipo original. * @template T - Tipo que puede ser un Promise o no * @example * // Para Promise<number> devolverá number * type Result = UnwrapPromise<Promise<number>>; // number