Declaration Files & DefinitelyTyped
When you call "Pune".toUpperCase() or document.querySelector(), TypeScript knows their types even though you never wrote them. When you import a package such as express, TypeScript usually knows its functions too. Where does all this type information come from?
The answer is declaration files: files ending in .d.ts that contain only types. In this lesson you will learn what they are, the three places library types come from, how to use the huge DefinitelyTyped collection, and how to write a small declaration file yourself for a library that has none.
What is a declaration file?
A .d.ts file describes the shape of JavaScript code without containing any code itself. Think of it as a menu card: it lists every dish and its price, but no food. It uses the declare keyword, which means "this exists somewhere at run time; here is its type".
Imagine an old JavaScript file money.js in your project:
// money.js
export function toRupees(paise) {
return "₹" + (paise / 100).toFixed(2);
}
export const GST_RATE = 0.18;A matching money.d.ts next to it tells TypeScript the types:
// money.d.ts
export declare function toRupees(paise: number): string;
export declare const GST_RATE: number;Now import { toRupees } from "./money.js" in a TypeScript file is fully typed. Function bodies and values are missing on purpose: the real code lives in money.js. When you compile a TypeScript library with the declaration option, tsc writes these .d.ts files for you, which is how library authors ship types.
Where library types come from
There are three sources, and TypeScript checks them automatically:
| Source | Example | What you do |
|---|---|---|
| Built into TypeScript | lib.es2025.d.ts, lib.dom.d.ts | Choose with target and lib in tsconfig.json |
| Bundled with the package | zod, axios, vite | Nothing: the package's package.json points to its .d.ts files |
| DefinitelyTyped | @types/node, @types/express, @types/react | npm install --save-dev @types/<name> |
DefinitelyTyped is a large community project on GitHub that maintains type definitions for thousands of JavaScript packages that do not ship their own. Each one is published on npm under the @types scope:
npm install --save-dev @types/node
npm install --save-dev @types/expressWhen you import express from "express", TypeScript finds node_modules/@types/express automatically. Packages that you only use as globals, such as Node.js's process or a test framework's describe, must also be listed in tsconfig.json, because TypeScript 7 loads no global @types packages unless you name them:
{
"compilerOptions": {
"types": ["node"]
}
}When there are no types
If a package has no types anywhere, importing it gives an error that explains the options:
src/main.ts(1,22): error TS7016: Could not find a declaration file for module 'old-sms'. 'C:/projects/school-app/node_modules/old-sms/index.js' implicitly has an 'any' type. Try `npm i --save-dev @types/old-sms` if it exists or add a new declaration (.d.ts) file containing `declare module 'old-sms';`
The quick fix, declare module "old-sms"; in a .d.ts file, makes every import from that package any. That silences the error but turns off checking. A better fix is to describe the parts you actually use:
// src/types/old-sms.d.ts
declare module "old-sms" {
export type DeliveryReport = { id: string; status: "sent" | "failed" };
export function send(to: string, text: string): Promise<DeliveryReport>;
export function balance(): Promise<number>;
}Put the file anywhere inside the folders your tsconfig.json includes (a src/types folder is common). Now send is typed, autocomplete works, and a call such as send(9829012345, "Hi") is caught because the phone number must be a string. You only need to declare what you use; you can add more later.
Declaring globals
Some scripts create global variables, for example an analytics or payment script loaded with a <script> tag. TypeScript does not know about them. You can add them with declare global inside a module, or with plain declare statements in a script-style .d.ts file:
export {}; // makes this file a module, required for "declare global"
declare global {
var shopConfig: { city: string; currency: string; openHours: [number, number] };
}
// In a real page, a <script> tag would create this object before your code runs.
globalThis.shopConfig = { city: "Jaipur", currency: "INR", openHours: [10, 21] };
const [open, close] = shopConfig.openHours;
console.log(`${shopConfig.city} shop, prices in ${shopConfig.currency}`);
console.log(`Open ${open}:00 to ${close}:00`);Jaipur shop, prices in INR Open 10:00 to 21:00
The declare global block produces no JavaScript at all; it only teaches TypeScript that shopConfig exists. Notice the use of var: global declarations need it, because only var creates a property on globalThis. This is one of the rare places where var is still correct.
Interfaces from libraries can be extended the same way through declaration merging (see Interfaces vs Type Aliases). For example, adding a property to the browser's Window interface:
declare global {
interface Window {
dataLayer: unknown[];
}
}
export {};Library types and skipLibCheck
.d.ts files from your dependencies are type-checked too, which takes time and can report errors in code you do not control. The skipLibCheck option, set by tsc --init, skips checking declaration files. It is safe for almost every project and makes builds faster.
Common mistakes
- Writing code in a
.d.tsfile. Declaration files contain types only; a function body there is an error. - Using
declare module "x";forever. It makes everythingany. Replace it with real declarations for the functions you use. - Installing
@typesfor a package that ships types. Check the npm badge first. - Forgetting
"types": ["node"]in TypeScript 7. Without it,processandBufferare unknown even with@types/nodeinstalled. - Using
letorconstinsidedeclare globalfor globals onglobalThis. Usevar.
Key points
- A
.d.tsdeclaration file contains only types and usesdeclareto describe code that exists elsewhere. - Types come from TypeScript's built-in lib files, from packages that bundle them, or from DefinitelyTyped's
@typespackages. - Imported packages find
@typesautomatically; global ones must be listed in"types"in TypeScript 7. - Error TS7016 means a package has no types: install
@types/<name>or writedeclare module "name" { ... }. declare globaladds global variables and extends interfaces such asWindow;skipLibCheckspeeds up builds.
Exercise
Your college project uses an old JavaScript package attendance-lib with two functions: markPresent(rollNo, date) returns true or false, and report(month) returns a promise of an array of { rollNo, daysPresent } objects. Write a declaration file for it, then write a TypeScript function that uses both functions with correct types.
Show solution
// src/types/attendance-lib.d.ts
declare module "attendance-lib" {
export type MonthlyRow = { rollNo: number; daysPresent: number };
export function markPresent(rollNo: number, date: string): boolean;
export function report(month: number): Promise<MonthlyRow[]>;
}// src/attendance.ts
import { markPresent, report, type MonthlyRow } from "attendance-lib";
export async function lowAttendance(month: number, minDays: number): Promise<MonthlyRow[]> {
markPresent(14, "2026-10-30");
const rows = await report(month);
return rows.filter((row) => row.daysPresent < minDays);
}The declaration file describes only what the project uses. Now report returns a typed promise, and a mistake such as markPresent("14", ...) is caught.
Quick Quiz
1. What does a .d.ts file contain?
Declaration files describe the types of code that lives elsewhere.
2. Where are @types/... packages maintained?
DefinitelyTyped publishes community-written types under the @types scope.
3. In TypeScript 7, you installed @types/node but process is still unknown. Why?
The types option defaults to [] in TypeScript 7, so global packages are not loaded automatically.
4. What is the downside of declare module "old-sms"; with no body?
A body-less module declaration silences the error by giving up on types.
Learn TypeScript with a mentor
Free lessons get you started. Our Full Stack Web Development training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
