Declaration Files

Hard

Declaration files (`.d.ts`) describe the types of JavaScript code without containing any implementation. They are how TypeScript understands third-party JavaScript libraries, global variables, and module shapes. The DefinitelyTyped repository (`@types/*` packages) provides declaration files for thousands of libraries. Understanding how to read, write, and troubleshoot declaration files is essential for working with TypeScript in real projects.

Interactive Visualization

Key Points

  • Declaration files (`.d.ts`) contain only type information — no runtime code
  • `declare` keyword introduces ambient declarations for existing JavaScript
  • `@types/*` packages from DefinitelyTyped provide types for JS libraries
  • Module augmentation lets you extend existing module types
  • Global augmentation adds types to the global scope
  • Triple-slash directives (`/// <reference>`) link declaration files together
  • `declare module "name"` creates type definitions for untyped modules

Code Examples

Writing Declaration Files

// types/analytics.d.ts — declare types for a JS analytics library
declare module 'analytics-lib' {
  interface AnalyticsConfig {
    apiKey: string
    debug?: boolean
    batchSize?: number
  }

  interface Event {
    name: string
    properties?: Record<string, unknown>
    timestamp?: Date
  }

  export function init(config: AnalyticsConfig): void
  export function track(event: Event): Promise<void>
  export function identify(userId: string, traits?: Record<string, unknown>): void
}

// Usage in application code
import { init, track } from 'analytics-lib'

init({ apiKey: 'abc123', debug: true })
track({ name: 'page_view', properties: { path: '/home' } })

Declaration files describe the API surface of JavaScript libraries. The `declare module` syntax creates type definitions that TypeScript uses for type checking imports.

Module Augmentation

// Extend Express Request with custom properties
import 'express'

declare module 'express' {
  interface Request {
    userId?: string
    sessionId?: string
  }
}

// Now TypeScript recognizes these properties
import { Request, Response } from 'express'

function authMiddleware(req: Request, _res: Response, next: () => void): void {
  req.userId = 'user-123'  // No type error
  next()
}

// Extend a library's types with new methods
declare module 'dayjs' {
  interface Dayjs {
    businessDaysAdd(days: number): Dayjs
  }
}

Module augmentation lets you add new properties or methods to existing types from third-party libraries without modifying the original source code.

Global & Ambient Declarations

// global.d.ts — add global types
declare global {
  interface Window {
    __APP_CONFIG__: {
      apiUrl: string
      version: string
      features: Record<string, boolean>
    }
  }

  // Declare a global function (e.g., injected by a script tag)
  function gtag(command: string, ...args: unknown[]): void
}

// Environment variable types for Vite or Next.js
declare namespace NodeJS {
  interface ProcessEnv {
    DATABASE_URL: string
    API_SECRET: string
    NODE_ENV: 'development' | 'production' | 'test'
  }
}

export {}  // This makes the file a module (required for declare global)

Global declarations extend the global scope with custom types. The `declare global` block adds types to Window, process.env, or any global interface.

Common Mistakes

  • Forgetting the `export {}` in files that use `declare global` (makes it a module)
  • Confusing `declare module` (module augmentation) with regular module declarations
  • Not checking DefinitelyTyped before writing custom declarations for popular libraries
  • Placing declaration files outside the TypeScript compilation scope (not included in tsconfig)
  • Writing implementation code in `.d.ts` files — they should only contain type declarations

Interview Tips

  • Know how to write a basic declaration file for an untyped JavaScript library
  • Explain module augmentation with a practical example like extending Express Request
  • Mention DefinitelyTyped and `@types/*` packages as the standard type source
  • Understand the difference between `declare module` for new modules vs augmentation

Related Concepts