Declaration files en TypeScript: escribir .d.ts para librerías JavaScript

Los ficheros de declaración (.d.ts) son la forma que tiene TypeScript de entender librerías JavaScript que no incluyen tipos propios. Describen la forma de los valores exportados por un módulo sin incluir ninguna implementación. Saber leerlos, escribirlos y publicarlos junto a una librería es una habilidad esencial en proyectos TypeScript maduros.

DefinitelyTyped y @types

La mayoría de librerías populares sin tipos propios tienen un paquete @types/nombre en DefinitelyTyped, mantenido por la comunidad. Para usarlos, instálalos como dependencia de desarrollo:

npm install --save-dev @types/node @types/express @types/lodash

TypeScript los detecta automáticamente si typeRoots no está configurado de forma restrictiva en tsconfig. Una vez instalados, las importaciones de esas librerías tienen tipos completos sin que tengas que hacer nada más.

Escribir un fichero .d.ts básico

Si una librería no tiene tipos en DefinitelyTyped, puedes escribir un fichero .d.ts mínimo para declarar lo que usas. Crea un fichero con el nombre de la librería en un directorio @types en tu proyecto:

// @types/libreria-sin-tipos/index.d.ts

declare module "libreria-sin-tipos" {
  export function procesar(entrada: string): string;
  export function transformar(valor: number, opciones?: TransformOptions): number;

  export interface TransformOptions {
    precision?: number;
    redondear?: boolean;
  }
}

En tsconfig, apunta a tu directorio de tipos:

{
  "compilerOptions": {
    "typeRoots": ["./node_modules/@types", "./@types"]
  }
}

declare global: extender tipos globales

Para añadir propiedades a objetos globales como Window, process.env o globalThis, usa declare global dentro de un módulo (un fichero con al menos un import o export) o directamente en un script (fichero sin imports):

// global.d.ts (sin imports: es un script, afecta al scope global)
declare global {
  interface Window {
    analyticsId: string;
    featureFlags: Record;
  }
}

// O para tipar variables de entorno en Node.js:
declare namespace NodeJS {
  interface ProcessEnv {
    DATABASE_URL: string;
    API_KEY: string;
    NODE_ENV: "development" | "production" | "test";
  }
}

Publicar tipos junto a una librería npm

Si publicas una librería TypeScript, incluye los tipos compilados y apunta a ellos desde package.json:

// package.json
{
  "name": "mi-libreria",
  "version": "1.0.0",
  "main": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs",
      "types": "./dist/index.d.ts"
    }
  }
}

En el tsconfig activa "declaration": true y opcionalmente "declarationMap": true para generar source maps de las declaraciones, lo que permite a los usuarios de la librería navegar al código fuente desde el editor.

Leer ficheros .d.ts: cómo entender la API de una librería

Cuando el autocompletado no funciona o quieres entender exactamente qué tipo devuelve una función, ir al fichero .d.ts es la fuente de verdad. En VS Code, pulsa F12 sobre cualquier símbolo para ir a su declaración. Los ficheros .d.ts en node_modules/@types/ o en el propio paquete contienen todas las firmas con comentarios JSDoc que aparecen en los tooltips del editor.

Imagen: Pexels / Nemuel Sereti

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP