// .d.ts files provide type info without runtime code
Note Declaration files describe the shape of existing JavaScript code. They contain only type information — no executable code. TypeScript automatically picks up .d.ts files in your project. Most npm packages include their own or have a @types/package companion.
declare const name: Type;
declare function fn(): Type;
declare class Name { ... }
declare module "name" { ... }
example
// Tell TypeScript about a global that exists at runtime
declare const gtag: (
command: "config" | "event",
targetId: string,
params?: Record<string, unknown>
) => void;
// Tell TypeScript about a global class
declare class Stripe {
constructor(apiKey: string);
charges: {
create(params: { amount: number; currency: string }): Promise<unknown>;
};
}
gtag("event", "purchase", { value: 99.99 });
output
// declare tells TypeScript 'trust me, this exists at runtime'
Note declare is for things that already exist in the runtime environment but TypeScript cannot see (global scripts, CDN libraries, injected variables). It emits zero JavaScript. Using declare when the value does not actually exist leads to runtime crashes with no compile-time warning.
// types/untyped-libs.d.ts// Type an entire untyped npm package
declare module "color-hash" {
exportdefaultclass ColorHash {
constructor(options?: { lightness: number });
hex(input: string): string;
rgb(input: string): [number, number, number];
}
}
// Wildcard: type all .svg imports
declare module "*.svg" {
const content: string;
exportdefault content;
}
// Wildcard: type all .css modules
declare module "*.module.css" {
const classes: Record<string, string>;
exportdefault classes;
}
output
// Now: import ColorHash from 'color-hash'; // fully typed
Note Ambient module declarations let you type third-party packages that lack types, or describe non-JS imports (CSS, SVG, images). Wildcard modules (*.ext) match any import path ending with that extension. Place these in a .d.ts file included in your tsconfig.
ambient moduledeclare moduletype untyped packagewildcard modulecss module typesvg import type
Module Augmentation
syntax
// In a .ts file (not .d.ts)import"original-module";
declare module "original-module" {
interface ExistingInterface {
newProperty: Type;
}
}
example
// Augmenting Express Requestimport"express";
declare module "express" {
interface Request {
userId?: string;
sessionToken?: string;
permissions?: string[];
}
}
// Now in your middleware:import { Request, Response, NextFunction } from"express";
function authMiddleware(req: Request, res: Response, next: NextFunction) {
req.userId = "usr_123"; // No error — augmented
req.permissions = ["read"]; // No error — augmented
next();
}
output
// The augmented properties are available everywhere Request is used
Note Module augmentation extends existing module types without modifying the original package. The file performing augmentation must be a module itself (have at least one import/export). This only works for interfaces and namespaces — you cannot add new top-level exports through augmentation.
module augmentationextend module typesaugment expressadd property to typepatch types
/// <reference types="vite/client" />// Enables Vite-specific types like import.meta.env/// <reference lib="es2022" />// Includes ES2022 library types/// <reference path="./custom-globals.d.ts" />// Explicitly includes another declaration file
output
// Triple-slash directives are special comments that instruct the compiler
Note Triple-slash directives must appear at the very top of the file (before any code). They are mostly obsolete for modern projects — tsconfig's 'types', 'lib', and 'include' options do the same job. The main surviving use case is /// <reference types="..." /> in .d.ts files and Vite/framework setups.
// ES modules are the standard; namespaces are legacy
Note Namespaces (formerly 'internal modules') are largely obsolete. Modern TypeScript projects should use ES modules (import/export) exclusively. Namespaces still appear in declaration files for global libraries and in legacy codebases. Do not use namespace and module imports in the same file.
namespacenamespace vs moduleinternal modulelegacy namespaceorganize types