Archivos de declaración .d.ts
Los archivos de declaración (.d.ts) contienen exclusivamente información de tipos, sin implementación. Describen la forma de código JavaScript existente para que TypeScript pueda verificar tipos y proporcionar autocompletado.

Cuando TypeScript compila un archivo .ts con la opción declaration: true, genera automáticamente un archivo .d.ts correspondiente:
// matematicas.ts (código fuente)
export function sumar(a: number, b: number): number {
return a + b
}
export const PI = 3.14159
// matematicas.d.ts (generado automáticamente)
export declare function sumar(a: number, b: number): number
export declare const PI: number
El archivo .d.ts describe la firma pública del módulo sin incluir la lógica interna. La palabra clave declare indica que la implementación existe en otro lugar.
Los archivos .d.ts no generan código JavaScript. Su único propósito es proporcionar información de tipos al compilador de TypeScript y a los editores de código.
Cuando se necesitan archivos .d.ts
Los archivos de declaración son necesarios en varios escenarios:
- Librerías JavaScript sin tipos: Cuando se usa una librería escrita en JavaScript que no incluye tipos
- Publicar paquetes npm: Para que los consumidores de la librería tengan información de tipos
- APIs del entorno: Para describir APIs globales del navegador, Node.js u otros entornos
- Integración con código legado: Para añadir tipos a código JavaScript existente sin reescribirlo
DefinitelyTyped y paquetes @types
DefinitelyTyped es un repositorio comunitario que contiene archivos de declaración para miles de librerías JavaScript. Los tipos se distribuyen como paquetes npm bajo el scope @types:
// Instalar una librería y sus tipos
// npm install lodash
// npm install @types/lodash --save-dev
import _ from "lodash"
// TypeScript conoce todos los métodos de lodash
const ordenados = _.sortBy([3, 1, 2])
const agrupados = _.groupBy(["uno", "dos", "tres"], s => s.length)
TypeScript busca automáticamente los tipos en node_modules/@types/ para cualquier paquete importado. No es necesaria ninguna configuración adicional.
Tipos incluidos en el paquete
Muchas librerías modernas incluyen sus propios tipos directamente en el paquete npm. El campo types (o typings) en package.json indica donde se encuentran:
{
"name": "mi-librería",
"main": "dist/index.js",
"types": "dist/index.d.ts"
}
Cuando una librería incluye tipos, no es necesario instalar un paquete @types separado.
Configurar typeRoots
La opción typeRoots en tsconfig.json controla donde busca TypeScript los paquetes de tipos:
{
"compilerOptions": {
"typeRoots": ["./node_modules/@types", "./tipos-propios"]
}
}
La opción types limita que paquetes de @types se incluyen automáticamente:
{
"compilerOptions": {
"types": ["node", "jest"]
}
}
Declaraciones ambientales con declare
La palabra clave declare describe entidades que existen en el entorno de ejecución pero no están definidas en el código TypeScript actual:
// globales.d.ts
declare const VERSION: string
declare function registrarMetrica(nombre: string, valor: number): void
declare class Analytics {
trackEvento(nombre: string, propiedades?: Record<string, unknown>): void
trackPagina(url: string): void
}
Estas declaraciones informan a TypeScript de que estas entidades existen en tiempo de ejecución (por ejemplo, inyectadas por un script externo) y describen sus tipos.
Declarar variables globales
// global.d.ts (sin import/export, opera en ámbito global)
declare const __DEV__: boolean
declare const __VERSION__: string
declare function setTimeout(callback: () => void, ms: number): number
Declarar módulos ambientales
Para describir un módulo que existe en el entorno pero no tiene archivos .d.ts:
// declarations.d.ts
declare module "mi-librería-sin-tipos" {
export function procesar(datos: string): number
export function transformar<T>(entrada: T[]): T[]
export const VERSION: string
}
Después de esta declaración, TypeScript reconoce las importaciones de ese módulo:
import { procesar, VERSION } from "mi-librería-sin-tipos"
const resultado = procesar("datos")
console.log(VERSION)
Módulos con patrón wildcard
Los módulos con patrón usan un comodin * para cubrir múltiples rutas de importación:
// declarations.d.ts
declare module "*.css" {
const clases: Record<string, string>
export default clases
}
declare module "*.svg" {
const contenido: string
export default contenido
}
declare module "*.json" {
const valor: unknown
export default valor
}
Esto permite importar archivos no TypeScript con tipado básico:
import estilos from "./componente.css"
import logo from "./logo.svg"
console.log(estilos.contenedor) // string
console.log(logo) // string
Augmentación global
La augmentación global permite añadir declaraciones al ámbito global desde un módulo. Se usa declare global dentro de un archivo que ya es un módulo:
// extensiones.ts
export {} // Convierte el archivo en módulo
declare global {
interface Window {
analytics: {
trackEvento(nombre: string): void
trackPagina(url: string): void
}
}
var __APP_CONFIG__: {
apiUrl: string
entorno: string
}
}
Después de esta declaración, TypeScript reconoce estas propiedades globales en todo el proyecto:
// En cualquier otro archivo
window.analytics.trackEvento("click_boton")
console.log(__APP_CONFIG__.apiUrl)
Extender tipos globales existentes
Se pueden añadir métodos o propiedades a tipos globales como Array, String o Promise:
// extensiones-array.ts
export {}
declare global {
interface Array<T> {
primero(): T | undefined
ultimo(): T | undefined
}
}
// Implementación (necesaria en tiempo de ejecución)
Array.prototype.primero = function () {
return this[0]
}
Array.prototype.ultimo = function () {
return this[this.length - 1]
}
const números = [1, 2, 3, 4, 5]
const primero = números.primero() // number | undefined
const ultimo = números.ultimo() // number | undefined
La augmentación global debe usarse con precaución. Modificar tipos globales afecta a todo el proyecto y puede crear conflictos con librerías de terceros.
Augmentación de módulos
La augmentación de módulos permite extender los tipos de un módulo existente sin modificar su código fuente. Se diferencia de los módulos ambientales en que el archivo que contiene la augmentación es un módulo (tiene import o export):
// extensiones-express.ts
import { Request, Response } from "express"
declare module "express" {
interface Request {
usuario?: {
id: string
nombre: string
rol: string
}
}
}
Ahora TypeScript reconoce la propiedad usuario en todas las instancias de Request:
import { Request, Response } from "express"
function middleware(req: Request, res: Response, next: () => void) {
req.usuario = {
id: "123",
nombre: "Ana",
rol: "admin"
}
next()
}
Extender librerías de terceros
// extensiones-react.ts
import "react"
declare module "react" {
interface CSSProperties {
[clave: `--${string}`]: string | number
}
}
Esto permite usar variables CSS custom en estilos inline de React:
const estilos: React.CSSProperties = {
color: "blue",
"--color-primario": "#3178c6",
"--espaciado": 8
}
Escribir declaraciones para librerías sin tipos
Cuando una librería no tiene tipos disponibles (ni incluidos ni en @types), se pueden escribir declaraciones personalizadas.
Declaración mínima
La forma más rápida es declarar el módulo sin detalle de tipos:
// declarations.d.ts
declare module "librería-sin-tipos"
Esto silencia los errores de importación, pero todos los tipos seran any. Es mejor proporcionar tipos específicos.
Declaración detallada
Analizar la documentación o el código fuente de la librería para describir su API:
// tipos/mi-librería.d.ts
declare module "mi-librería-graficos" {
export interface OpcionesGrafico {
tipo: "linea" | "barra" | "circular"
datos: number[]
etiquetas: string[]
titulo?: string
ancho?: number
alto?: number
}
export class Grafico {
constructor(contenedor: HTMLElement, opciones: OpcionesGrafico)
renderizar(): void
actualizar(datos: number[]): void
destruir(): void
}
export function crearGrafico(
contenedor: HTMLElement,
opciones: OpcionesGrafico
): Grafico
}
Declaración para módulo CommonJS
Algunas librerías usan module.exports en lugar de exportaciones ES:
// tipos/vieja-librería.d.ts
declare module "vieja-librería" {
interface Opciones {
debug?: boolean
timeout?: number
}
function inicializar(opciones?: Opciones): void
function procesar(datos: string): Promise<string>
export = { inicializar, procesar }
}
Declaración para librería con namespace
Algunas librerías exponen un objeto global con múltiples métodos:
// tipos/utilidad-global.d.ts
declare namespace MiUtilidad {
function formatear(valor: number, decimales?: number): string
function parsear(texto: string): number
function validar(entrada: unknown): boolean
interface Configuración {
locale: string
moneda: string
}
function configurar(config: Partial<Configuración>): void
}
declare module "mi-utilidad" {
export = MiUtilidad
}
Estructura de archivos de declaración
Archivo único para declaraciones globales
// src/tipos/global.d.ts
// Variables de entorno
declare const process: {
env: Record<string, string | undefined>
}
// Módulos de assets
declare module "*.png" {
const src: string
export default src
}
declare module "*.module.css" {
const clases: Record<string, string>
export default clases
}
Archivos separados por librería
src/
tipos/
global.d.ts # Declaraciones globales
mi-librería.d.ts # Tipos para mi-librería
otra-librería.d.ts # Tipos para otra-librería
tsconfig.json
El tsconfig.json debe incluir los archivos de declaración en el ámbito de compilación:
{
"compilerOptions": {
"typeRoots": ["./node_modules/@types", "./src/tipos"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts"]
}
Verificar declaraciones
Para comprobar que las declaraciones son correctas, se puede crear un archivo de prueba que importe y use la librería:
// test-tipos.ts
import { Grafico, crearGrafico } from "mi-librería-graficos"
const contenedor = document.getElementById("grafico")!
const grafico = crearGrafico(contenedor, {
tipo: "barra",
datos: [10, 20, 30],
etiquetas: ["A", "B", "C"]
})
grafico.renderizar()
grafico.actualizar([15, 25, 35])
grafico.destruir()
Si TypeScript no muestra errores y el autocompletado funciona correctamente, las declaraciones son válidas. Este enfoque permite integrar cualquier librería JavaScript en un proyecto TypeScript con seguridad de tipos completa.
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, TypeScript es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de TypeScript
Explora más contenido relacionado con TypeScript y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Comprender que son los archivos de declaración .d.ts y cuando se necesitan, usar DefinitelyTyped y paquetes @types, escribir declaraciones ambientales con declare, aplicar global augmentation y module augmentation, y crear declaraciones personalizadas para librerías sin tipos.