Secrets of *.d.ts: How TypeScript Sees Third-Party Code

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Does Your Code "Get Along" with lodash?

Have you ever wondered how TypeScript knows the types for a regular JavaScript library like lodash or jQuery? After all, you just write import _ from 'lodash', and suddenly you get autocompletion and type checking. Magic? No, it's the work of the mysterious *.d.ts files.

On Stack Overflow, the question "About \"*.d.ts\" in TypeScript" has garnered thousands of views — developers want to understand what lies behind this extension. Today, we'll look under the hood of TypeScript and break down how type declarations work. You'll learn not only the theory but also get practical examples that will help you create your own types for any JavaScript project.



What is .d.ts Really?

Files with the .d.ts extension are TypeScript declaration files. They contain only type descriptions, not the implementation. Think of them as a "contract": TypeScript looks at this file and understands what functions, classes, and variables exist, and what their types are.

The key difference from regular .ts files: .d.ts is not compiled into JavaScript. They exist only for static analysis and autocompletion.



// myLibrary.d.tsexport function greet(name: string): void;export const VERSION: string;


Now, if you import this library, TypeScript will know: greet takes a string and returns nothing, and VERSION is a string. Without this file, you would get the error "Could not find a declaration file for module".



How Does TypeScript Find .d.ts?

The declaration search mechanism works in several stages:

  • Automatic search: If a .d.ts file with the same name sits next to a .js file, TypeScript will pick it up automatically.
  • The types or typings field in package.json: Many libraries specify the path to their declaration file. For example: "types": "./lib/index.d.ts".
  • The /// <reference path="" /> directive: Manual pointing to a declaration file (an outdated method, but still encountered).
  • @types packages: If a library does not include its own types, the community publishes them on npm under the name @types/library-name.

When you write npm install @types/react, you are downloading exactly a set of .d.ts files that describe React.



Under the Hood: How TypeScript Processes .d.ts

Let's imagine that TypeScript is a detective investigating a "case of types." The .d.ts files are witness statements. They say: "Here is the add function, it takes two numbers and returns a number." TypeScript believes these statements and does not check if they are actually true (since there is no implementation).



Ambient Declarations

One of the most powerful features of .d.ts is declaring ambient modules. This allows you to describe types for modules that don't exist in your code. For example, you want to use the global variable $ from jQuery:



// globals.d.tsdeclare var $: (selector: string) => any;


Or describe an entire module:



// my-custom-module.d.tsdeclare module 'my-custom-module' {    export function doSomething(x: number): string;    export interface Config {        timeout: number;    }}


Now you can write import { doSomething } from 'my-custom-module' — and TypeScript will know the types.



Global Types vs Module Types

An important distinction: .d.ts files can be either global (if they have no import/export) or module-based (if they do). Global declarations are visible

Blogs

Book Recommendations