Arroba types y los .d.ts

Cuando el código fuente descargado desde NPM se niegue a funcionar bien en TypeScript, deberemos prestar atención por si necesitásemos importar manualmente un archivo de definición de tipos para integrar el proyecto. El espacio de nombres @types genera definiciones de tipos si es posible para facilitar esta integración. Con esto cerramos esta temporada.

Cuando trabajamos con TypeScript y queremos importar módulos de JavaScript, a menudo nos encontramos con que algunos módulos se importan sin problemas, mientras que otros nos dan errores. Esto suele ocurrir porque TypeScript necesita conocer los tipos de las funciones o variables que estamos importando, y el código JavaScript puro no incluye esa información. Para solucionar esto, existen los archivos de definición con extensión .d.ts.

Estos archivos .d.ts no contienen código ejecutable, sino que describen la forma y los tipos de las funciones, clases o variables que existen en un módulo JavaScript. Por ejemplo, si tenemos una función llamada tokenToDate que acepta un string y un Date y devuelve un Date, el archivo .d.ts declarará esa función con la palabra clave declare, indicando a TypeScript qué tipos esperar sin necesidad de ver el código fuente real.

Cuando instalamos paquetes desde npm, es fundamental que estos incluyan sus propios archivos .d.ts para que TypeScript pueda entenderlos correctamente. Algunos paquetes están escritos en TypeScript y ya incluyen estos archivos, pero otros, que solo tienen código JavaScript, no los traen. En esos casos, TypeScript no sabe qué tipos tienen las funciones o variables, lo que genera errores al importar.

Para resolver este problema, podemos hacer dos cosas. Primero, en el archivo tsconfig.json, existe una opción llamada allowJs que permite a TypeScript procesar archivos JavaScript, pero esta opción no siempre funciona bien y no es la solución ideal. La segunda opción, más fiable, es instalar los tipos desde el repositorio DefinitelyTyped, que es una comunidad que mantiene definiciones de tipos para muchos paquetes populares. Estos paquetes se instalan con un nombre que empieza por @types/ seguido del nombre del paquete original. Por ejemplo, para un paquete llamado isode, instalaríamos @types/isode como dependencia de desarrollo. Esto añade el archivo .d.ts correspondiente y elimina los errores de importación.

Además, cuando desarrollamos nuestros propios proyectos en TypeScript y queremos distribuirlos para que otros los usen, es importante generar estos archivos .d.ts para que los consumidores de nuestro código puedan beneficiarse de la información de tipos. Para ello, configuramos el tsconfig.json activando la opción declaration. Así, al compilar con tsc, se generarán automáticamente los archivos .d.ts junto con los archivos .js transpilados.

Por ejemplo, si tenemos un archivo calculadora.ts que exporta funciones como sumar, restar y multiplicar, al compilar con la opción de declaración activada, obtendremos un archivo calculadora.d.ts que declara estas funciones con sus tipos correspondientes. Esto es esencial para que otros proyectos TypeScript puedan importar y usar nuestro código sin perder la información de tipos.

// calculadora.ts
export function sumar(a: number, b: number): number {
  return a + b;
}

export function restar(a: number, b: number): number {
  return a - b;
}

export function multiplicar(a: number, b: number): number {
  return a * b;
}

Al compilar con la opción declaration: true en tsconfig.json, se generará un archivo calculadora.d.ts similar a este:

export declare function sumar(a: number, b: number): number;
export declare function restar(a: number, b: number): number;
export declare function multiplicar(a: number, b: number): number;

De esta forma, aunque solo distribuyamos el código JavaScript, los usuarios de TypeScript podrán conocer los tipos y evitar errores.

En definitiva, los archivos .d.ts son la clave para que TypeScript pueda trabajar con módulos JavaScript sin perder la información de tipos. Ya sea instalando los tipos desde @types o generando nuestros propios archivos de definición, asegurarnos de que estos archivos estén disponibles es fundamental para una experiencia de desarrollo fluida y sin errores. Además, automatizar la generación de estos archivos con la configuración adecuada nos ahorra trabajo y reduce la posibilidad de errores humanos.

Lista de reproducción
  1. 1
    Temporada 1
    5 minutos
  2. 2
    ¿Qué es TypeScript?
    11 minutos
  3. 3
    Instalando TypeScript
    8 minutos
  4. 4
    Compilando un Hola Mundo sencillo
    7 minutos
  5. 5
    Hola Mundo pero con tipos
    10 minutos
  6. 6
    Tipos: tipos primitivos
    12 minutos
  7. 7
    Tipos: tipos especiales (any, null, ...)
    10 minutos
  8. 8
    Tipos: arrays y tuplas
    11 minutos
  9. 9
    Tipos: objetos
    7 minutos
  10. 10
    Funciones: lo básico
    9 minutos
  11. 11
    Funciones: tipando funciones
    9 minutos
  12. 12
    Clases: introducción a las clases
    9 minutos
  13. 13
    Clases: creando una clase
    10 minutos
  14. 14
    Clases: modificador private
    8 minutos
  15. 15
    Clases: modificador readonly
    3 minutos
  16. 16
    Clases: Atributos virtuales con getters y setters
    10 minutos
  17. 17
    Clases: herencia
    9 minutos
  18. 18
    Clases: modificadores abstract y protected
    8 minutos
  19. 19
    Tipos alias
    6 minutos
  20. 20
    Tipos literales
    5 minutos
  21. 21
    Uniones de tipos
    7 minutos
  22. 22
    Uniones discriminantes
    7 minutos
  23. 23
    Intersecciones de tipos
    5 minutos
  24. 24
    Interfaces: introducción
    7 minutos
  25. 25
    Interfaces: modificadores y funciones
    9 minutos
  26. 26
    Interfaces: usándolas con clases
    8 minutos
  27. 27
    Interfaces: herencia de interfaces
    8 minutos
  28. 28
    Interfaces: interfaces indizadas
    5 minutos
  29. 29
    Interfaces: funciones y tipos híbridos
    5 minutos
  30. 30
    ¿Qué diferencia hay entre interfaces y tipos? (2020)
    8 minutos
  31. 31
    Casteos con as
    6 minutos
  32. 32
    instanceof y las guardas
    9 minutos
  33. 33
    Tipos enumerados
    8 minutos
  34. 34
    Valores avanzados para enumerados
    7 minutos
  35. 35
    Enumerados con valores computados
    6 minutos
  36. 36
    Genéricos en tipos
    8 minutos
  37. 37
    Múltiples genéricos y buenas prácticas
    5 minutos
  38. 38
    Genéricos en funciones
    8 minutos
  39. 39
    Genéricos con restricciones
    6 minutos
  40. 40
    Tipos de utilidad
    3 minutos
  41. 41
    Exportando módulos
    9 minutos
  42. 42
    Importando módulos
    7 minutos
  43. 43
    Export default e import asterisco
    6 minutos
  44. 44
    tsconfig
    7 minutos
  45. 45
    Módulos desde NPM
    7 minutos
  46. 46
    Arroba types y los .d.ts
    8 minutos
  47. 47
    Ejemplo (1): creando una API REST simple en TypeScript
    11 minutos
  48. 48
    Ejemplo (2): montando un servidor Express
    8 minutos
  49. 49
    Ejemplo (3): haciendo las funciones de control de datos
    11 minutos
  50. 50
    Ejemplo (4): conectando todas las piezas
    7 minutos