Question
I want to understand how .d.ts declaration files work in TypeScript.
I was told that .d.ts files are similar to .h header files in C and C++, but they do not seem to behave the same way. Right now, I am struggling to understand how to use them correctly.
It seems that I cannot place my .js or .ts implementation code inside a .d.ts file, so it looks like a project may need all three file types: .js, .ts, and .d.ts.
My questions are:
- What is the relationship between these three file types?
- How do I use a
*.d.tsfile? Does it mean I can permanently delete the*.tsfile? - If so, how does a
*.d.tsfile know which JavaScript file it describes?
Short Answer
By the end of this page, you will understand what .d.ts files are, how they differ from .ts and .js files, and when each file type is needed. You will also learn how TypeScript connects declaration files to JavaScript modules and why .d.ts files describe code rather than implement it.
Concept
What a .d.ts file is
A .d.ts file is a TypeScript declaration file. Its job is to describe the shape of code without containing the actual implementation.
That means a declaration file can say:
- a function exists
- what parameters it accepts
- what it returns
- what objects, classes, or constants are available
But it does not contain the executable logic.
The role of each file type
.ts
A .ts file contains TypeScript source code.
- It can contain implementation
- It can contain types
- It is usually compiled into
.js
Example:
export function add(a: number, b: number): number {
return a + b;
}
.js
A .js file contains .
Mental Model
Think of these files like a product in a box:
.jsis the actual product you can use.tsis the product being designed with detailed instructions.d.tsis the label on the box describing what is inside
The label is useful, but the label is not the product.
Another way to think about it:
.js= the working machine.d.ts= the blueprint of the machine's public controls.ts= the original source used to build the machine
A blueprint can describe a machine, but it cannot run by itself.
Syntax and Examples
Basic declaration syntax
A declaration file uses declarations instead of implementations.
Function declaration
export declare function greet(name: string): string;
This says:
- there is a function called
greet - it takes a
string - it returns a
string
But there is no function body.
Variable declaration
export declare const version: string;
Interface declaration
export interface User {
id: number;
name: string;
}
Class declaration
Step by Step Execution
Example
Suppose you have these files:
logger.js
export function log(message) {
return `[LOG] ${message}`;
}
logger.d.ts
export declare function log(message: string): string;
main.ts
import { log } from './logger';
const result = log('Hello');
console.log(result);
What happens step by step
1. TypeScript reads main.ts
It sees:
Real World Use Cases
1. Adding types to a JavaScript library
Many libraries are written in JavaScript but still want to support TypeScript users. A .d.ts file lets the library provide type information without rewriting the whole codebase in TypeScript.
2. Publishing a TypeScript package
A package author writes .ts source files and publishes:
- compiled
.js - generated
.d.ts
Consumers get both runtime code and type safety.
3. Typing legacy code
In older projects, teams often have lots of JavaScript already. They can gradually add .d.ts files to describe existing modules and improve editor support before fully migrating to TypeScript.
4. Describing browser globals or external APIs
Declaration files can describe values that exist at runtime but are not defined directly in your current source, such as:
- global variables injected by a script
- APIs provided by a host environment
- third-party plugins
5. Internal shared contracts in large codebases
Teams may use declarations to describe public APIs between packages, especially in monorepos or shared libraries.
Real Codebase Usage
Common patterns in real projects
Generate .d.ts from .ts
This is the most common pattern in TypeScript libraries. Developers write normal TypeScript, then let the compiler generate declarations.
Benefits:
- avoids duplicating types manually
- keeps declarations in sync with implementation
- reduces mistakes
Write .d.ts manually for JavaScript code
This is common when:
- a project is still mostly JavaScript
- only type hints are needed
- migration to TypeScript is gradual
Describe package public APIs
Many packages expose only selected functions and classes. Their declaration files describe the exported API clearly, which acts like documentation and type safety at the same time.
Use declarations for globals
Example:
declare const API_URL: string;
This is useful when a bundler, environment, or script injects something at runtime.
Validation and contract clarity
Developers use type declarations to make function usage clearer:
export {
: ;
: ;
}
(): ;
Common Mistakes
1. Putting implementation code inside .d.ts
A declaration file should not contain real executable logic.
Incorrect
export function add(a: number, b: number): number {
return a + b;
}
Correct
export declare function add(a: number, b: number): number;
2. Thinking .d.ts can run by itself
A .d.ts file is not runtime code. If you only keep a declaration file and remove the actual JavaScript or compiled output, there is nothing to execute.
3. Letting declarations get out of sync with implementation
math.js
() {
(a + b);
}
Comparisons
.ts vs .js vs .d.ts
| File type | Contains implementation? | Contains types? | Runs directly? | Common use |
|---|---|---|---|---|
.ts | Yes | Yes | No, usually compiled first | Main TypeScript source |
.js | Yes | Sometimes via JSDoc, but not TypeScript syntax | Yes | Runtime code |
.d.ts | No | Yes | No | Type declarations only |
.d.ts vs C/C++ header files
Cheat Sheet
Quick reference
What each file does
.ts= TypeScript source.js= runtime JavaScript.d.ts= type declarations only
Core rule
A .d.ts file describes code. It does not implement code.
Common file relationships
source.ts -> output.js + output.d.ts
or
library.js + library.d.ts
Declaration examples
export declare function greet(name: string): string;
export declare const version: string;
export interface User {
: ;
: ;
}
FAQ
What is a .d.ts file in TypeScript?
A .d.ts file is a declaration file that describes the types and exported API of code without containing the actual implementation.
Do I need both .ts and .d.ts files?
Not always. If you write TypeScript, your .ts files may be enough during development, and .d.ts files can be generated when needed. If you write JavaScript, you may add .d.ts files manually.
Can a .d.ts file replace a .ts file?
No, not as implementation. A .d.ts file only provides type information. You still need JavaScript or compiled TypeScript code to run the program.
How does TypeScript match a .d.ts file to a .js file?
Usually through the same module name or file path. For example, importing ./math lets TypeScript use math.d.ts for types and math.js at runtime.
Are .d.ts files only for libraries?
Mini Project
Description
Create a small JavaScript utility module and a matching TypeScript declaration file. This project demonstrates the real purpose of .d.ts files: giving TypeScript type information for JavaScript code that already exists and runs.
Goal
Build a JavaScript module that exports a few utility functions, then add a .d.ts file so a TypeScript file can import and use that module with full type checking.
Requirements
- Create a
utils.jsfile with at least two exported functions. - Create a matching
utils.d.tsfile that describes those exports. - Create a
main.tsfile that imports and uses the JavaScript module. - Make sure the declarations match the real JavaScript behavior.
- Include at least one function that returns a typed object.
Keep learning
Related questions
Angular formGroup Error Explained: Fixing 'Can't bind to formGroup' in Reactive Forms
Learn why Angular shows 'Can't bind to formGroup' and how to fix it by importing ReactiveFormsModule correctly.
Fix "Element implicitly has an 'any' type" in TypeScript Object Indexing
Learn why TypeScript rejects string object indexing and how to fix it with keyof, unions, and typed object keys in React.
Fix "Property has no initializer" in Angular TypeScript Components
Learn why Angular TypeScript shows "Property has no initializer" and how to fix it using defaults, optional properties, or definite assignment.