CodeForge

TypeScript de Cero a Experto / TS en el mundo real

Declaration files: tipar lo que TS no ve

Teoría20 min20 XP

No todo el código que usas tiene tipos: librerías viejas en JavaScript puro, variables globales inyectadas por un script, propiedades que agregas a window. Los declaration files (.d.ts) son la forma de darle a TypeScript conocimiento sobre código que no puede ver —tipos sin implementación, puros contratos. Es la herramienta para que TS entienda el mundo real que lo rodea.

El manual de instrucciones sin la máquina

declare: describir sin implementar

Un archivo .d.ts contiene solo TIPOS —descripciones—, nunca código ejecutable. La palabra declare dice "esto existe en algún lado, créeme y tipéalo":

tipos.d.ts
// un archivo .d.ts: solo declaraciones, cero implementación

// una variable global que un <script> externo puso en window:
declare const VERSION_APP: string;

// una función global disponible en el entorno:
declare function rastrear(evento: string): void;

// ahora puedes usarlas en tu código TS con tipos, sin que TS vea su código:
console.log(VERSION_APP.toUpperCase());   // ✓ TS sabe que es string
rastrear("pagina_vista");                 // ✓ tipada

En un .d.ts no hay cuerpos de función ni valores —solo formas. declare const VERSION_APP: string le promete a TS "existe una variable global llamada así, de tipo string" (puesta quizá por un <script> en el HTML). TS te deja usarla tipada, aunque su valor real llegue de fuera. Es el manual para lo que existe en runtime pero TS no ve en tu código.

Tipar una librería sin tipos

Si usas una librería JavaScript que no trae tipos (ni un paquete @types/), la tipas con declare module:

libreria.d.ts
// una librería vieja 'calculadora-legacy' sin tipos propios:
declare module "calculadora-legacy" {
export function sumar(a: number, b: number): number;
export function formatear(valor: number): string;
export const version: string;
}

// ahora en tu código, el import está tipado:
// import { sumar, formatear } from "calculadora-legacy";
// sumar(2, 3);              ✓ tipado
// sumar("2", 3);            ❌ error, como debe ser

Ampliar tipos existentes: module augmentation

A veces no quieres crear un tipo nuevo, sino AMPLIAR uno que ya existe —agregar una propiedad a window, o a los tipos de una librería. Aquí vuelve el declaration merging de las interfaces (módulo 3):

augmentation.d.ts
// agregar una propiedad global a Window (que tu app pone en runtime):
declare global {
interface Window {
  miApp: {
    version: string;
    usuario: { id: number } | null;
  };
}
}

// ahora window.miApp está tipado en TODO el proyecto:
// window.miApp.version.toUpperCase();   ✓
// window.miApp.usuario?.id;             ✓

export {};   // esto convierte el archivo en un módulo (necesario para 'declare global')

declare global { interface Window { ... } } FUSIONA tu declaración con la interface Window nativa (declaration merging, módulo 3), agregándole miApp. Es el patrón estándar para tipar lo que tu app inyecta en el objeto global. El export {} del final es un truco necesario: convierte el archivo en un módulo, requisito de declare global. Lo mismo sirve para ampliar los tipos de Express, de Vue, o de cualquier librería con puntos de extensión.

Un <script> externo en tu HTML define una variable global window.CONFIG con datos. En tu código TS, usar window.CONFIG da error 'Property CONFIG does not exist on Window'. ¿Cómo lo tipas?

Mini-reto

Tipa el entorno (en un proyecto TS con un env.d.ts): 1) declara una variable global declare const API_URL: string (que imaginas puesta por tu bundler); 2) amplía Window con declare global para agregar una propiedad analytics: { rastrear(evento: string): void }; 3) usa ambas en un .ts y confirma que TS las reconoce tipadas. Escribiste un manual para código que TS no ve.

Qué sigue

Última lección del módulo: las clases a fondo en TypeScript —modificadores de acceso, propiedades de parámetro, clases abstractas— y una probada de los DECORADORES, la sintaxis para añadir comportamiento a clases y métodos que verás en Angular y NestJS. El TypeScript orientado a objetos que usan los frameworks del backend.