Declaraciones de tipo (.d.ts) en TypeScript

Intermedio
TypeScript
TypeScript
Actualizado: 18/04/2026

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.

Ecosistema de ficheros de declaración .d.ts

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 - Autor del tutorial

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.