Declaration Files and Module Interop
Know how TypeScript finds and combines type declarations: declaration files, scripts vs modules, global and module augmentation, package.json resolution, and CommonJS/ESM interop.
Key points
- 1
A
.d.tsfile holds only types anddeclareforms and emits nothing. Ambient declarations describe values that something else provides at runtime. - 2
A top-level
importorexportmakes a file a module. Declarations in modules are local, so global changes needdeclare global { … }. Useexport {}to make an import-free file a module. - 3
declare module "x" { … }is an ambient module declaration in a script file (the full typing) but a merging augmentation in a module file. Augmentations need a resolvable, typed target (TS2664/TS2665). - 4
Interfaces and namespaces merge. Later interface declarations' overloads come first, and namespaces can add statics to functions, classes and enums (but must come after them).
- 5
With an "exports" map, TypeScript reads its "types" conditions and ignores the top-level "types" field. Without one, it tries "types", a .d.ts beside "main", index.d.ts, then @types.
- 6
Type CommonJS
module.exports = fnwithexport =, notexport default. Mark type-only imports and re-exports (import type,export type) for isolatedModules and verbatimModuleSyntax. - 7
TypeScript 6.0 defaults
typesto[](list global @types such as jest and node, or use "*"), and deprecatesesModuleInterop: falseandallowSyntheticDefaultImports: false.
Common traps
Adding an import to a global .d.ts silently turns
interface Window { … }into a local type, so the augmentation stops applying.A shim
declare module "pkg"in an import-free file replaces the package's real typings instead of extending them.Declaration files only count if they are in the program; a file outside
includeworks in the editor but fails in CI.
Test yourself on Declaration Files and Module Interop
Ten questions, with the answer and explanation after each one.