@types/* en dependencies o devDependencies: los principales errores

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: ¿por qué la pregunta sobre @types/* atormenta incluso a desarrolladores experimentados?



¿Alguna vez ha perdido una hora depurando un error que, al final, se reducía a la ubicación incorrecta de un paquete @types/* en package.json? Si es así, no está solo. La pregunta «How do I decide whether @types/* goes into dependencies or devDependencies?» ha acumulado miles de visitas en Stack Overflow y se ha convertido en un verdadero dolor de cabeza para la comunidad de TypeScript.



Parecería sencillo: poner los tipos en devDependencies y listo. Pero no es tan fácil. Cuando su proyecto comienza a crecer, se integran bibliotecas de terceros, monorepositorios y pipelines de CI/CD, la colocación incorrecta de los tipos puede provocar errores fatales de compilación, caídas inesperadas en producción o, peor aún, una pérdida silenciosa de la tipificación.



En este artículo, analizaremos los 5 errores más comunes al trabajar con @types/*, aprenderemos a tomar la decisión correcta basándonos en escenarios reales y crearemos una lista de verificación que le protegerá de problemas. ¿Listo? ¡Allá vamos!



Error n.º 1: «Todos los @types/* siempre van en devDependencies» — un mito que rompe compilaciones



El consejo más popular en internet dice: «Los tipos no son código en tiempo de ejecución, por lo tanto siempre deben estar en devDependencies». Y esto en el 90% de los casos es cierto. Pero hay una excepción importante que se olvida.



Cuándo devDependencies es la elección correcta

Si está escribiendo una aplicación (servidor web en Express, frontend en React, utilidad de línea de comandos), entonces todos los @types/* deben ir sin dudas a devDependencies. Su usuario final no compila TypeScript, ejecuta JavaScript ya compilado. Los tipos solo los necesita usted durante el desarrollo.



// Ejemplo para una aplicación en Express{  "devDependencies": {    "@types/express": "^4.17.21",    "@types/node": "^20.11.0",    "typescript": "^5.3.3"  }}


Cuándo devDependencies es un error fatal

Ahora imagine: usted desarrolla una biblioteca que exporta tipos de TypeScript para consumidores externos. Si los tipos de su biblioteca dependen de @types/express y usted lo coloca en devDependencies, el usuario que instale su biblioteca no recibirá esos tipos automáticamente. Y su IDE comenzará a mostrar subrayados rojos.



// ❌ Incorrecto para una biblioteca que exporta tipos{  "devDependencies": {    "@types/express": "^4.17.21" // ¡El usuario no verá estos tipos!  }}

// ✅ Correcto{ "dependencies": { "@types/express": "^4.17.21" // Los tipos estarán disponibles para los consumidores }}


Regla de oro: Si su biblioteca reexporta tipos de un paquete @types/* o los utiliza en una API pública, entonces ese paquete debe estar en dependencies. Si los tipos se usan solo internamente — devDependencies.



Error n.º 2: Ignorar la diferencia entre «lo uso en el código» y «lo uso en los tipos»



Muchos desarrolladores se confunden: «Yo importo Request de express, entonces express debe estar en dependencies». Esto es cierto para el paquete express en sí, pero no para sus tipos.



Analicemos con un ejemplo concreto. Hay tres escenarios de uso del paquete @types/lodash:



  • Escenario A: Usted escribe import _ from 'lodash' y usa _.chunk(). Los tipos solo son necesarios para la compilación — devDependencies.
  • Escenario B: Usted crea una función function mySort(arr: T[]): T[] y dentro usa _.orderBy. Los tipos no salen al exterior — devDependencies.
  • Escenario C: Usted escribe export function proc

Blogs

Book Recommendations