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.
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.
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.
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.
Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript
Type narrowing from typeof check produces 'never'
How to fix "Type narrowing produces never" in TypeScript
Type parameter 'T' has conflicting constraints
How to fix "Type parameter has conflicting constraints" in TypeScript