ProgramaciónDesarrollador Frontend

¿Cómo funciona el mecanismo de tipado de módulos JavaScript importados en TypeScript? ¿Cómo tipar la importación si el archivo JS original no contiene tipos? ¿Cuáles son los matices y riesgos de trabajar con any en la importación?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

Historia del problema:

TypeScript está diseñado para agregar tipado estático a aplicaciones JS existentes. Surge la pregunta: ¿cómo tipar la importación si estamos conectando un módulo externo o uno propio, escrito en JavaScript puro, donde no hay tipos? En este caso, TypeScript utiliza lo que se llaman archivos de declaración (.d.ts), o infiere los tipos automáticamente (a veces incorrectamente).

Problema:

Si al importar TypeScript no encuentra una descripción de tipos adecuada, la variable adquiere el tipo any, lo que significa una pérdida total de seguridad de tipos. Esto puede llevar a errores que el compilador no detectará y a bugs en tiempo de ejecución. A menudo, los desarrolladores tienden a olvidar declarar explícitamente los tipos para las funciones/objetos importados.

Solución:

  1. Para sus módulos JS, se pueden escribir declaraciones de tipos manualmente (archivos .d.ts).
  2. Para bibliotecas populares, a menudo existen paquetes @types.
  3. Se pueden declarar tipos en la importación explícitamente, describiendo uno mismo la estructura del objeto necesario.
  4. Se recomienda evitar any, y si no se puede evitar, limitar al mínimo el alcance de su uso.

Ejemplo de código:

// 1. Tipado explícito de la importación del módulo JS import myFunc from './myLib'; declare function myFunc(x: number): boolean; // 2. Importación desde el módulo JS, para el cual se creó el archivo myLib.d.ts con export function myFunc(x: number): boolean; import { myFunc } from './myLib'; // 3. Importamos un módulo sin tipificación y describimos explícitamente el tipo import * as legacy from './legacy'; const typedLegacy: { runTask: (name: string) => void } = legacy;

Características clave:

  • En ausencia de declaraciones, el valor importado por defecto recibe el tipo any, lo que rompe la seguridad de tipos.
  • El mejor enfoque es crear archivos .d.ts para módulos externos/sus propias bibliotecas.
  • Si es necesario, se puede hacer una declaración local de funciones/módulos externos mediante declare/interfaces.

Preguntas trampa.

¿Puede TypeScript inferir automáticamente los tipos del módulo JS importado sin declaraciones?

No, si el archivo está escrito en JavaScript, sin declaraciones de tipos, TypeScript se ve obligado a asumir any y pierde la información de tipos, salvo en casos triviales (export const x = 1;).

¿Es posible "ampliar" los tipos importados si aparecen nuevos campos en el módulo JS?

Solo si actualiza el archivo de declaración (.d.ts). Si los tipos están fijados en .d.ts, TypeScript los usará como "verdad", cualquier nuevo campo permanecerá sin tipificación o provocará un error.

¿Es seguro importar un módulo JS externo en un proyecto TypeScript si no hay @types/ni declaraciones para él?

No, esto reduce drásticamente la seguridad: todo el trabajo con la importación queda sin tipar (any), el compilador no emitirá errores, incluso si el módulo no está disponible o si la API ha cambiado. Trabajar con tales módulos es aceptable solo como una solución temporal, con tipificación explícita o aislamiento del código.

Errores típicos y anti-patrones

  • Olvido de declaraciones (.d.ts) para paquetes externos
  • Confianza ciega en el implicit any al importar módulos JS
  • Violación de los límites del código seguro de tipos

Ejemplo de la vida

Caso negativo

Un desarrollador importa una biblioteca JS externa sin declaraciones, utilizando con confianza la API y obteniendo el tipo any. Después de una actualización de la biblioteca, cambia la firma de los métodos, pero no se producen errores, solo bugs en tiempo de ejecución.

Ventajas:

  • Rápido y fácil conectar cualquier módulo JS

Desventajas:

  • No hay garantías de seguridad de tipos, los errores permanecen indetectables hasta la ejecución

Caso positivo

Se crea un archivo de declaración .d.ts o se añade un paquete @types, la descripción de la API coincide estrictamente con el módulo JS original. Todos los métodos importados están tipificados, la IDE sugiere autocompletado, y cualquier discrepancia muestra un error de compilación.

Ventajas:

  • Seguridad de tipos, advertencia de errores antes de la ejecución
  • Soporte para autocompletado y documentación directamente en el código

Desventajas:

  • Se requiere tiempo para escribir .d.ts, mantener tipos al actualizar el módulo JS