Ambient declarations y global types en TypeScript | Nicolás Garzón
Una declaración ambient describe algo que existe durante ejecución, pero cuya implementación no aparece en ese archivo TypeScript.
TypeScript
Copiar declare const BUILD_VERSION : string ;
TypeScript
Copiar declare const analytics: AnalyticsClient; El bundler, script global o host debe crear realmente analytics.
TypeScript
Copiar declare function showNotification (
message: string ,
) : void ; TypeScript
Copiar declare class LegacyClient {
constructor ( apiKey: string ) ;
request ( path: string ) : Promise < unknown > ;
} Un .d.ts sin top-level import/export puede añadir nombres al global.
TypeScript
Copiar interface Window {
applicationVersion: string ;
} Un archivo con export {} es módulo y sus nombres son privados salvo declare global.
TypeScript
Copiar export { } ;
declare global {
interface Window {
applicationVersion: string ;
}
} Es la forma explícita de ampliar globals desde un módulo.
TypeScript
Copiar export { } ;
declare global {
const __APP_CONFIG__: AppConfig;
} La build debe inyectarla o asignarla realmente.
TypeScript
Copiar window. __APP_CONFIG__; No es necesariamente equivalente a un lexical global en todos los módulos y runtimes. Declara el lugar exacto donde el valor existe.
TypeScript
Copiar declare global {
interface Window {
__APP_CONFIG__: AppConfig;
}
} TypeScript
Copiar declare module "legacy-parser" {
export function parse ( value: string ) : unknown ;
} Se usa cuando el módulo runtime existe, pero faltan declarations.
TypeScript
Copiar declare module "*.svg" {
const url: string ;
export default url;
} Debe coincidir con el comportamiento real del bundler. Algunos setups transforman SVG a componente, otros a URL.
TypeScript
Copiar interface ImportMetaEnv {
readonly VITE_API_URL : string ;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
} Tiparlo como string no garantiza que exista ni que tenga una URL válida. Valida configuración al iniciar.
Tipos como process, Buffer o módulos node:* vienen de las declarations de Node. Instalar @types/node añade esos globals y módulos al programa.
No lo incluyas en un proyecto de navegador si vuelve disponibles APIs que el runtime no tendrá, salvo archivos/configuraciones separados.
JSON
Copiar {
"compilerOptions" : {
"types" : [ "node" , "vitest/globals" ]
}
} Limita qué paquetes @types añaden globals. No controla imports normales de tipos.
Cambia directorios donde TypeScript busca paquetes de tipos. Configurarlo reemplaza el comportamiento por defecto y puede ocultar @types instalados. Rara vez es necesario.
JSON
Copiar {
"compilerOptions" : {
"lib" : [ "ES2024" , "DOM" ]
}
} Añade declarations de APIs estándar y del host. No polyfillea el runtime.
Puede incluir tipos para un archivo o declaration package. En código moderno, tsconfig e imports suelen ser preferibles, pero las referencias siguen siendo útiles en declarations y librerías.
Dos packages pueden declarar el mismo global de forma incompatible. Mantén globals mínimos y separa tsconfigs para browser, server y tests.
TypeScript
Copiar
declare global {
interface Window {
PaymentWidget: {
open ( options: PaymentOptions) : void ;
} ;
}
}
export { } ; La aplicación todavía debe cargar el script antes de usarlo.
Usar declare para “crear” una variable.
Añadir DOM o Node libs a entornos que no las tienen.
Declarar un asset con forma distinta a la transformación real.
Crear globals desde un archivo que accidentalmente es script.
Instalar @types/node y asumir que Buffer existe en navegador.
Usar typeRoots sin entender que reemplaza búsqueda por defecto.
Tipar env vars sin validarlas.
Cargar un script después de acceder a su global.
Ambient declarations describen valores externos.
declare no emite implementación.
Los .d.ts scripts pueden modificar el global.
declare global amplía globals desde módulos.
Ambient modules describen paquetes o assets externos.
lib y types cambian APIs visibles al checker.
Tipos disponibles no garantizan capacidades runtime.
Globals deben mantenerse controlados y separados por entorno.
¿Por qué incluir DOM en lib permite usar document pero no hace que exista en Node?
Respuesta Porque lib solo agrega declarations al checker. No instala ni implementa las APIs del navegador durante ejecución.
Module augmentation y declaration merging amplía contratos externos sin inventar implementación.