Skip to content

TypeScript Declaration Files — Complete Guide

DodaTech Updated 2026-06-28 7 min read

In this tutorial, you will learn about TypeScript Declaration Files. We cover key concepts, practical examples, and best practices to help you master this topic.

TypeScript declaration files (.d.ts) describe the shape of JavaScript modules and global variables without providing implementation — they are the bridge that brings type safety to the entire JavaScript ecosystem.

What You'll Learn

  • What .d.ts files are and how they work
  • The declare keyword for global and module types
  • Ambient module declarations
  • DefinitelyTyped and @types/ packages
  • Writing custom declaration files

Why It Matters

TypeScript cannot type-check JavaScript modules without type information. Declaration files provide that information without modifying the original JS code. Every @types/ package on npm is a collection of .d.ts files, making thousands of JS libraries usable in TypeScript.

Real-World Use

The Doda Browser extension API types live in @types/chrome — a DefinitelyTyped package containing hundreds of .d.ts files describing every Chrome API. Without them, extension development in TypeScript would be impossible. Durga Antivirus Pro uses custom .d.ts files to type REST API endpoints.

Learning Path

flowchart LR
  A[Namespaces & Modules] --> B[Declaration Files]
  B --> C[Type Manipulation]
  B --> D[You Are Here]
  C --> E[Classes & OOP]
  E --> F[Inheritance]

What Is a .d.ts File?

A .d.ts file contains only type information — no runtime code:

// my-lib.d.ts
export function greet(name: string): string;
export const VERSION: string;
export interface Config {
  debug: boolean;
  timeout: number;
}

When TypeScript compiles, it uses .d.ts files for Type Checking without generating any JavaScript from them.

Generating .d.ts from .ts

Enable in tsconfig.json:

{
  "compilerOptions": {
    "declaration": true,
    "declarationMap": true,
    "emitDeclarationOnly": false
  }
}

Now compiling math.ts:

export function add(a: number, b: number): number {
  return a + b;
}

Generates math.d.ts:

export declare function add(a: number, b: number): number;

The declare Keyword

Use declare to tell TypeScript that a value exists at runtime without providing an implementation:

// globals.d.ts
declare const API_BASE_URL: string;
declare function sendRequest(path: string): Promise<unknown>;
declare class ApiClient {
  constructor(baseUrl: string);
  get<T>(path: string): Promise<T>;
}

declare var, let, const

declare var environment: string;      // Can be reassigned
declare let debugMode: boolean;       // Block-scoped
declare const APP_VERSION: string;    // Constant — cannot be reassigned

declare function

declare function $(selector: string): HTMLElement[];
declare function $(element: HTMLElement): HTMLElement[];

// Overloads
declare function format(input: string): string;
declare function format(input: number): string;

declare class

declare class Animal {
  constructor(name: string);
  speak(): void;
  readonly name: string;
}

declare namespace

declare namespace MyLib {
  function init(config: Record<string, unknown>): void;
  const VERSION: string;
  namespace Events {
    function on(event: string, handler: () => void): void;
  }
}

declare module

// For ambient modules (modules without type definitions)
declare module "some-untyped-lib" {
  export function doStuff(): void;
  export const version: string;
}

// For non-JS file imports
declare module "*.svg" {
  const content: string;
  export default content;
}

declare module "*.module.css" {
  const classes: Record<string, string>;
  export default classes;
}

declare global

Used inside a module to add declarations to the global scope:

// src/types/global.d.ts
export {};

declare global {
  interface Window {
    __APP_CONFIG__: {
      API_URL: string;
      VERSION: string;
    };
  }

  const __DEV__: boolean;
}

// Now usable anywhere without import
console.log(window.__APP_CONFIG__.API_URL);

Ambient Module Declarations

For untyped npm packages:

// src/types/untyped.d.ts
declare module "obscure-js-library" {
  export interface Options {
    timeout?: number;
    retries?: number;
  }

  export function run(options?: Options): Promise<string>;
  export const DEFAULT_TIMEOUT: number;
}

Wildcard Module Declarations

// Match all files of a certain pattern
declare module "*.json" {
  const value: unknown;
  export default value;
}

declare module "*.md" {
  const content: string;
  export default content;
}

DefinitelyTyped

DefinitelyTyped is a GitHub Repository containing thousands of community-maintained .d.ts files for popular JavaScript libraries.

Using @types/ Packages

npm install --save-dev @types/react
npm install --save-dev @types/express
npm install --save-dev @types/node

TypeScript automatically finds type definitions in node_modules/@types/ unless you set typeRoots in tsconfig.

Finding Type Definitions

  • Check the library's documentation for built-in types
  • Search for @types/library-name on npm
  • Check DefinitelyTyped on GitHub: https://github.com/DefinitelyTyped/DefinitelyTyped
  • If none exists, write your own ambient declaration

Writing Custom Declaration Files

When a Library Has No Types

// types/d3-heatmap.d.ts
declare module "d3-heatmap" {
  export interface HeatmapConfig {
    data: number[][];
    width?: number;
    height?: number;
    colors?: string[];
  }

  export function createHeatmap(container: HTMLElement, config: HeatmapConfig): void;
  export function updateHeatmap(config: HeatmapConfig): void;
}

Merging Existing Types

// Extend an existing module's types
import "express";

declare module "express" {
  interface Request {
    user?: {
      id: string;
      role: "admin" | "user";
    };
    requestId?: string;
  }
}

Publishing Type Definitions

If you publish a TypeScript library, ensure consumers get type information:

{
  "name": "my-typescript-lib",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "files": ["dist"]
}

The types field points to the entry .d.ts file. TypeScript automatically picks it up when consumers import your package.

Common Mistakes

1. Using declare module for a Package That Already Has Types

Check if the package already ships its own .d.ts files (check the types field in its package.json). Only use declare module as a fallback.

2. Declaration Files Not Being Included

Ensure your tsconfig includes the declaration files:

{
  "include": ["src/**/*", "types/**/*.d.ts"]
}

3. Writing Runtime Code in .d.ts Files

// BAD: .d.ts should only have types
export function add(a: number, b: number): number {
  return a + b; // Runtime code — does not belong in .d.ts
}

// GOOD: just the signature
export declare function add(a: number, b: number): number;

4. Not Using declare Inside .d.ts

Inside a .d.ts file, everything is implicitly declare. But using it explicitly is good practice.

5. Confusing .d.ts and .ts Files

  • .ts files: implementation + types, generates .js + .d.ts
  • .d.ts files: types only, no JavaScript generated

6. Missing export {} for Global Augmentations

When using declare global inside a module, you must include export {} to mark the file as a module:

// Without this, the file is treated as a script, not a module
export {};

declare global {
  // ...
}

Practice Questions

  1. What is the purpose of a .d.ts file? To describe the types of JavaScript code without providing runtime implementation, enabling type checking for JS libraries.

  2. What does the declare keyword do? It tells TypeScript that a value exists at runtime, providing its type without requiring an implementation.

  3. What is DefinitelyTyped? A community-maintained repository of .d.ts files for thousands of JavaScript libraries, distributed as @types/ npm packages.

  4. How do you extend an existing module's types? Use module augmentation: declare module "existing-module" { ... } to add properties to its interfaces.

Challenge: Write a .d.ts file for a hypothetical csv-parser library that exports a parseCSV(text: string): Record<string, string>[] function and a CsvParserOptions interface. Then write a separate script that uses it.

FAQ

What is the difference between `.d.ts` and `.ts` files?

.ts files contain both implementation and types. .d.ts files contain only type declarations — no executable code.

Where does TypeScript look for type definitions?

In node_modules/@types/ by default. You can configure this with typeRoots in tsconfig.json.

Can I write a `.d.ts` file for a global script (not a module)?

Yes. Use declare var, declare function, and declare namespace at the top level without any import/export.

What is `/// `?

A triple-slash directive that imports type definitions from @types/packagename.

Do I need to install `@types/node` to use Node.js APIs in TypeScript?

Yes. Node.js's built-in modules (fs, path, http) require @types/node for type information.

Mini Project: Type Definitions for a Weather API

// types/weather-api.d.ts
declare module "weather-api" {
  export interface Coordinates {
    lat: number;
    lon: number;
  }

  export interface WeatherData {
    temperature: number;
    humidity: number;
    condition: "sunny" | "cloudy" | "rainy" | "snowy";
    windSpeed: number;
    timestamp: string;
  }

  export interface ForecastDay {
    date: string;
    high: number;
    low: number;
    condition: string;
  }

  export function getCurrentWeather(coords: Coordinates): Promise<WeatherData>;
  export function getForecast(coords: Coordinates, days: number): Promise<ForecastDay[]>;
  export function setApiKey(key: string): void;

  export const DEFAULT_UNITS: "metric" | "imperial";
}

// Use it:
import { getCurrentWeather, getForecast } from "weather-api";

async function displayWeather(lat: number, lon: number) {
  const current = await getCurrentWeather({ lat, lon });
  console.log(`Temperature: ${current.temperature}°C, ${current.condition}`);

  const forecast = await getForecast({ lat, lon }, 5);
  for (const day of forecast) {
    console.log(`${day.date}: ${day.high}°C / ${day.low}°C — ${day.condition}`);
  }
}

What's Next

Now explore the satisfies operator and branded types:

Lesson Description
{{< ref "/programming-languages/typescript/16-namespaces-modules" >}} Review namespaces and modules
{{< ref "/programming-languages/typescript/18-type-manipulation" >}} satisfies, branded types
{{< ref "/programming-languages/typescript/19-classes" >}} Classes in TypeScript

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro