How to fix Type definition file must have .d.ts extension in TypeScript
TypeScript only accepts .d.ts files as declaration sources, so pointing a typeRoots, types, or package types path at a .ts file triggers this error. Rename the declaration material to .d.ts and regenerate your package.ts output before publishing so the compiler can safely load the definitions.
Quick fix
Fixes Type definition file must have .d.ts extension
mv src/types/ambient-declarations.ts src/types/ambient-declarations.d.ts- Rename the offending declaration file to .d.ts
- Restrict typeRoots / types to directories that actually contain .d.ts files
- Emit real .d.ts output instead of referencing your .ts sources
mv src/types/ambient-declarations.ts src/types/ambient-declarations.d.tsType definition file must have .d.ts extension
What this error means
The compiler emits "Type definition file must have .d.ts extension" whenever it resolves a declaration file that does not end with .d.ts. Declaration lookups originate from tsconfig's `types` / `typeRoots` settings or from package.json's `types` / `typings` entry, so the compiler refuses to treat an implementation (.ts) file as a declaration source. TypeScript deliberately keeps declarations and runtime code separate. .d.ts files describe the exported API surface without containing JavaScript, which allows the compiler to load ambient types without executing code. When a file is missing the .d.ts suffix, the compiler cannot know whether it should parse it as generated declaration output or as another implementation module, so it raises this error instead of silently misinterpreting your types.
Typical symptoms
- tsc (or tsc --build) fails with "Type definition file must have .d.ts extension", usually before any other diagnostics appear
- tsserver/VS Code highlights the offending path as a declaration problem
- The error pops up after adding a custom type declaration directory to typeRoots
- Publishing a library fails because package.json types now point at an index.ts file
- The error can appear during npm pack when the distributed types directory still contains .ts files
- A clean npm install followed by tsc still fails even though only declaration files are bundled
- CI linting catches the failure when declaration files are emitted to dist/types but renamed incorrectly
Common causes
- typeRoots or types in tsconfig.json points to a directory/file that contains .ts or .tsx sources instead of .d.ts
- package.json types/typings references an entry point that still uses the .ts extension instead of the emitted .d.ts
- You manually authored ambient declarations but forgot to rename the file to .d.ts before publishing
- A build step copies .ts files into dist/types expecting the consumer to compile them, which breaks the compiler check
- You configured a monorepo so that declaration files still live next to implementation files with .ts extension
- tsc --emitDeclarationOnly generates declarations into a folder that also contains .ts files with the same name
- A third-party package ships a .ts declaration stub in node_modules/@types, so TypeScript rejects it
- Custom script or bundler concatenated declarations without enforcing the .d.ts suffix
How to fix "Type definition file must have .d.ts extension"
If you wrote the declaration manually, rename it to have the exact .d.ts suffix and update any references to it:
mv src/types/ambient-declarations.ts src/types/ambient-declarations.d.tsThen adjust package.json so the types field points to a .d.ts file:
{
"types": "dist/types/index.d.ts"
}TypeScript only loads files that end with .d.ts, so the rename is the easiest fix when the file was already just a declaration file with ambient namespaces or module augmentations.
Open your tsconfig.json and make sure the compilerOptions look like this:
{
"compilerOptions": {
"typeRoots": ["./node_modules/@types", "./src/types"],
"types": ["node", "my-types"]
}
}If you previously pointed to a directory with implementation (.ts) files, remove that path. Directories listed under typeRoots are scanned for .d.ts files only, so shrinking the list to actual declaration bundles prevents the compiler from seeing .ts files and complaining.
Let TypeScript generate declarations from your implementation files so consumers get clean .d.ts files:
{
"compilerOptions": {
"declaration": true,
"emitDeclarationOnly": true,
"declarationDir": "dist/types",
"outDir": "dist",
"declarationMap": true
}
}After running tsc, publish the generated dist/types folder. The entry in package.json should point at dist/types/index.d.ts and any manual scripts that previously copied .ts files into that folder can be removed.
Advanced notes
TypeScript refuses to load a declaration file without .d.ts so that the compiler can keep the code/ambient split explicit. If you need to expose a type-only API, either ship the generated .d.ts files or move the declarations into a proper ambient module after compiling. Bundlers sometimes emit index.d.ts alongside .js, so double-check that the bundler does not accidentally copy .ts leftovers into the declaration directory.
Frequently asked questions
- What does "Type definition file must have .d.ts extension" mean?
- ts. ts) file as a declaration source. TypeScript deliberately keeps declarations and runtime code separate.
- How do I fix "Type definition file must have .d.ts extension"?
- TypeScript only accepts .d.ts files as declaration sources, so pointing a typeRoots, types, or package types path at a .ts file triggers this error. Rename the declaration material to .d.ts and regenerate your package.ts output before publishing so the compiler can safely load the definitions.
- What causes "Type definition file must have .d.ts extension"?
- typeRoots or types in tsconfig.json points to a directory/file that contains .ts or .tsx sources instead of .d.ts package.json types/typings references an entry point that still uses the .ts extension instead of the emitted .d.ts You manually authored ambient declarations but forgot to rename the file to .d.ts before publishing
- Is the "Type definition file must have .d.ts extension" error serious?
- It is a medium-severity error โ more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- ๐TypeScript Official Documentation
- ๐Declaration files introduction(Official Docs)
- ๐tsconfig.json โ types(Official Docs)