{"record":{"id":"5460f7922332fc64","repo":"microsoft/TypeScript","slug":"only-declaration-files-should-be-generated-when-em","errorCode":null,"errorMessage":"Only declaration files should be generated when emitDeclarationOnly:true","messagePattern":"Only declaration files should be generated when emitDeclarationOnly:true","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/harness/harnessIO.ts","lineNumber":403,"sourceCode":"        declOtherFiles: TestFile[];\r\n        harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions | undefined;\r\n        options: ts.CompilerOptions;\r\n        currentDirectory: string;\r\n    }\r\n\r\n    export function prepareDeclarationCompilationContext(\r\n        inputFiles: readonly TestFile[],\r\n        otherFiles: readonly TestFile[],\r\n        result: compiler.CompilationResult,\r\n        harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions,\r\n        options: ts.CompilerOptions,\r\n        // Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file\r\n        currentDirectory: string | undefined,\r\n    ): DeclarationCompilationContext | undefined {\r\n        if (options.declaration && result.diagnostics.length === 0) {\r\n            if (options.emitDeclarationOnly) {\r\n                if (result.js.size > 0 || (result.dts.size === 0 && !options.noEmit)) {\r\n                    throw new Error(\"Only declaration files should be generated when emitDeclarationOnly:true\");\r\n                }\r\n            }\r\n            else if (result.dts.size !== result.getNumberOfJsFiles(/*includeJson*/ false)) {\r\n                throw new Error(\"There were no errors and declFiles generated did not match number of js files generated\");\r\n            }\r\n        }\r\n\r\n        const declInputFiles: TestFile[] = [];\r\n        const declOtherFiles: TestFile[] = [];\r\n\r\n        // if the .d.ts is non-empty, confirm it compiles correctly as well\r\n        if (options.declaration && result.diagnostics.length === 0 && result.dts.size > 0) {\r\n            ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles));\r\n            ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles));\r\n            return { declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory: currentDirectory || harnessSettings.currentDirectory };\r\n        }\r\n\r\n        function addDtsFile(file: TestFile, dtsFiles: TestFile[]) {\r","sourceCodeStart":385,"sourceCodeEnd":421,"githubUrl":"https://github.com/microsoft/TypeScript/blob/b465fdbfe175304d9b977da137b2c178ae1091d3/src/harness/harnessIO.ts#L385-L421","documentation":"Thrown by prepareDeclarationCompilationContext when options.declaration and options.emitDeclarationOnly are both set and compilation produced no errors, yet the result violates emitDeclarationOnly semantics: either JS files were emitted (result.js.size > 0) or, when noEmit is false, no declaration files were produced (result.dts.size === 0). The invariant is that with emitDeclarationOnly the compiler must emit only .d.ts files.","triggerScenarios":"A compiler test sets declaration:true and emitDeclarationOnly:true but the compilation result contains emitted JS, or produces zero .d.ts files while noEmit is false. This indicates the compiler output diverges from the declared intent.","commonSituations":"A test harness bug, a compiler regression that emits JS despite emitDeclarationOnly, or a test configuration where emitDeclarationOnly was set but noEmit was also unexpectedly true. Also seen when a transform/plugin interferes with emit filtering.","solutions":["Verify the compiler actually respects emitDeclarationOnly for the given input — if JS is being emitted, this may be a real compiler bug to file.","Check that noEmit is not set; if noEmit is intended, no .d.ts will be produced and the second clause triggers.","Inspect result.js and result.dts contents to see which files were unexpectedly emitted (or missing)."],"exampleFix":"// before — test options conflict\n// @declaration: true\n// @emitDeclarationOnly: true\n// @noEmit: true\n// after — remove noEmit so declarations are emitted\n// @declaration: true\n// @emitDeclarationOnly: true","handlingStrategy":"validation","validationCode":"// Sanity-check emit invariants before baselining declarations\nif (options.declaration && options.emitDeclarationOnly) {\n    if (options.noEmit) throw new Error(\"emitDeclarationOnly requires noEmit:false\");\n    if (result.js.size > 0) throw new Error(\"Compiler emitted JS under emitDeclarationOnly\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not combine emitDeclarationOnly with noEmit.","When authoring declaration tests, verify the compiler emits only .d.ts files."],"tags":["harness","compiler-output","declaration","emit","emit-declaration-only"],"backgroundTag":null,"analyzedSha":"b465fdbfe175304d9b977da137b2c178ae1091d3","analyzedAt":"2026-08-12T05:38:42.698Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}