diff --git a/src/compiler/program.ts b/src/compiler/program.ts index f81d007141..a33c0a64c3 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -545,6 +545,9 @@ namespace ts { return resolutions; } + /* @internal */ + export const inferredTypesContainingFile = "__inferred type names__.ts"; + interface DiagnosticCache { perFile?: Map; allDiagnostics?: Diagnostic[]; @@ -875,7 +878,7 @@ namespace ts { if (typeReferences.length) { // This containingFilename needs to match with the one used in managed-side const containingDirectory = options.configFilePath ? getDirectoryPath(options.configFilePath) : host.getCurrentDirectory(); - const containingFilename = combinePaths(containingDirectory, "__inferred type names__.ts"); + const containingFilename = combinePaths(containingDirectory, inferredTypesContainingFile); const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeReferences, containingFilename); for (let i = 0; i < typeReferences.length; i++) { processTypeReferenceDirective(typeReferences[i], resolutions[i]); diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index 49f1fd26bc..5af7919b6d 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -669,6 +669,11 @@ namespace ts { // Mark the file as needing re-evaluation of module resolution instead of using it blindly. resolution.isInvalidated = true; (filesWithInvalidatedResolutions || (filesWithInvalidatedResolutions = createMap())).set(containingFilePath, true); + + // When its a file with inferred types resolution, invalidate type reference directive resolution + if (containingFilePath.endsWith(inferredTypesContainingFile)) { + resolutionHost.onChangedAutomaticTypeDirectiveNames(); + } } }); }); diff --git a/src/testRunner/unittests/tscWatch/resolutionCache.ts b/src/testRunner/unittests/tscWatch/resolutionCache.ts index 802b9c5bc5..ad93442d29 100644 --- a/src/testRunner/unittests/tscWatch/resolutionCache.ts +++ b/src/testRunner/unittests/tscWatch/resolutionCache.ts @@ -402,6 +402,47 @@ declare module "fs" { host.checkTimeoutQueueLength(0); }); }); + + it("when types in compiler option are global and installed at later point", () => { + const projectRoot = "/user/username/projects/myproject"; + const app: File = { + path: `${projectRoot}/lib/app.ts`, + content: `myapp.component("hello");` + }; + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, + content: JSON.stringify({ + compilerOptions: { + module: "none", + types: ["@myapp/ts-types"] + } + }) + }; + const host = createWatchedSystem([app, tsconfig, libFile]); + const watch = createWatchOfConfigFile(tsconfig.path, host); + checkProgramActualFiles(watch(), [app.path, libFile.path]); + host.checkTimeoutQueueLength(0); + checkOutputErrorsInitial(host, [ + createCompilerDiagnostic(Diagnostics.Cannot_find_type_definition_file_for_0, "@myapp/ts-types") + ]); + + host.ensureFileOrFolder({ + path: `${projectRoot}/node_modules/@myapp/ts-types/package.json`, + content: JSON.stringify({ + version: "1.65.1", + types: "types/somefile.define.d.ts" + }) + }); + host.ensureFileOrFolder({ + path: `${projectRoot}/node_modules/@myapp/ts-types/types/somefile.define.d.ts`, + content: ` +declare namespace myapp { + function component(str: string): number; +}` + }); + host.checkTimeoutQueueLengthAndRun(1); + checkOutputErrorsIncremental(host, emptyArray); + }); }); describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch with modules linked to sibling folder", () => {