diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts
index 4a699c8bc34e6..85043a9fdf359 100644
--- a/src/compiler/commandLineParser.ts
+++ b/src/compiler/commandLineParser.ts
@@ -1089,7 +1089,7 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [
{
name: "allowImportingTsExtensions",
type: "boolean",
- affectsModuleResolution: true,
+ affectsSemanticDiagnostics: true,
category: Diagnostics.Modules,
description: Diagnostics.Allow_imports_to_include_TypeScript_file_extensions_Requires_moduleResolution_bundler_and_either_noEmit_or_emitDeclarationOnly_to_be_set,
defaultValueDescription: false,
diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json
index 377bc39a74d82..96ea8324d8e34 100644
--- a/src/compiler/diagnosticMessages.json
+++ b/src/compiler/diagnosticMessages.json
@@ -4233,7 +4233,7 @@
"category": "Error",
"code": 5095
},
- "Option 'allowImportingTsExtensions' can only be used when 'moduleResolution' is set to 'bundler' and either 'noEmit' or 'emitDeclarationOnly' is set.": {
+ "Option 'allowImportingTsExtensions' can only be used when either 'noEmit' or 'emitDeclarationOnly' is set.": {
"category": "Error",
"code": 5096
},
diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts
index 0d66245a58f41..45ba44eac4b00 100644
--- a/src/compiler/moduleNameResolver.ts
+++ b/src/compiler/moduleNameResolver.ts
@@ -3033,9 +3033,7 @@ export function classicNameResolver(moduleName: string, containingFile: string,
// Program errors validate that `noEmit` or `emitDeclarationOnly` is also set,
// so this function doesn't check them to avoid propagating errors.
export function shouldAllowImportingTsExtension(compilerOptions: CompilerOptions, fromFileName?: string) {
- return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Bundler && (
- !!compilerOptions.allowImportingTsExtensions ||
- fromFileName && isDeclarationFileName(fromFileName));
+ return !!compilerOptions.allowImportingTsExtensions || fromFileName && isDeclarationFileName(fromFileName);
}
/**
diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index 67e7e20928d58..dc7cd4784245b 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -4213,7 +4213,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
}
if (options.allowImportingTsExtensions && !(options.noEmit || options.emitDeclarationOnly)) {
- createOptionValueDiagnostic("allowImportingTsExtensions", Diagnostics.Option_allowImportingTsExtensions_can_only_be_used_when_moduleResolution_is_set_to_bundler_and_either_noEmit_or_emitDeclarationOnly_is_set);
+ createOptionValueDiagnostic("allowImportingTsExtensions", Diagnostics.Option_allowImportingTsExtensions_can_only_be_used_when_either_noEmit_or_emitDeclarationOnly_is_set);
}
const moduleResolution = getEmitModuleResolutionKind(options);
diff --git a/src/testRunner/unittests/tscWatch/programUpdates.ts b/src/testRunner/unittests/tscWatch/programUpdates.ts
index 3437470bcd461..2e62b3e41d112 100644
--- a/src/testRunner/unittests/tscWatch/programUpdates.ts
+++ b/src/testRunner/unittests/tscWatch/programUpdates.ts
@@ -1957,4 +1957,42 @@ import { x } from "../b";`),
},
]
});
+
+ verifyTscWatch({
+ scenario,
+ subScenario: "when changing `allowImportingTsExtensions` of config file",
+ commandLineArgs: ["-w", "-p", ".", "--extendedDiagnostics"],
+ sys: () => {
+ const module1: File = {
+ path: `/user/username/projects/myproject/a.ts`,
+ content: ``
+ };
+ const module2: File = {
+ path: `/user/username/projects/myproject/b.ts`,
+ content: `import "./a.ts";`
+ };
+ const config: File = {
+ path: `/user/username/projects/myproject/tsconfig.json`,
+ content: JSON.stringify({
+ compilerOptions: {
+ noEmit: true,
+ allowImportingTsExtensions: false
+ }
+ }),
+ };
+ return createWatchedSystem([module1, module2, config, libFile], { currentDirectory: "/user/username/projects/myproject" });
+ },
+ edits: [
+ {
+ caption: "Change allowImportingTsExtensions to true",
+ edit: sys => sys.writeFile(`/user/username/projects/myproject/tsconfig.json`, JSON.stringify({
+ compilerOptions: {
+ noEmit: true,
+ allowImportingTsExtensions: true
+ }
+ })),
+ timeouts: sys => sys.checkTimeoutQueueLengthAndRun(1),
+ },
+ ]
+ });
});
diff --git a/tests/baselines/reference/bundlerImportTsExtensions(allowimportingtsextensions=true,noemit=false).errors.txt b/tests/baselines/reference/bundlerImportTsExtensions(allowimportingtsextensions=true,noemit=false).errors.txt
index 928c92f5f33bc..c6a2bf4156b5e 100644
--- a/tests/baselines/reference/bundlerImportTsExtensions(allowimportingtsextensions=true,noemit=false).errors.txt
+++ b/tests/baselines/reference/bundlerImportTsExtensions(allowimportingtsextensions=true,noemit=false).errors.txt
@@ -1,6 +1,6 @@
error TS5056: Cannot write file 'out/b.js' because it would be overwritten by multiple input files.
error TS5056: Cannot write file 'out/c.js' because it would be overwritten by multiple input files.
-error TS5096: Option 'allowImportingTsExtensions' can only be used when 'moduleResolution' is set to 'bundler' and either 'noEmit' or 'emitDeclarationOnly' is set.
+error TS5096: Option 'allowImportingTsExtensions' can only be used when either 'noEmit' or 'emitDeclarationOnly' is set.
error TS6054: File '/project/e.txt' has an unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts', '.js', '.jsx', '.cts', '.d.cts', '.cjs', '.mts', '.d.mts', '.mjs'.
The file is in the program because:
Root file specified for compilation
@@ -11,7 +11,7 @@ error TS6054: File '/project/e.txt' has an unsupported extension. The only suppo
!!! error TS5056: Cannot write file 'out/b.js' because it would be overwritten by multiple input files.
!!! error TS5056: Cannot write file 'out/c.js' because it would be overwritten by multiple input files.
-!!! error TS5096: Option 'allowImportingTsExtensions' can only be used when 'moduleResolution' is set to 'bundler' and either 'noEmit' or 'emitDeclarationOnly' is set.
+!!! error TS5096: Option 'allowImportingTsExtensions' can only be used when either 'noEmit' or 'emitDeclarationOnly' is set.
!!! error TS6054: File '/project/e.txt' has an unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts', '.js', '.jsx', '.cts', '.d.cts', '.cjs', '.mts', '.d.mts', '.mjs'.
!!! error TS6054: The file is in the program because:
!!! error TS6054: Root file specified for compilation
diff --git a/tests/baselines/reference/tscWatch/programUpdates/when-changing-`allowImportingTsExtensions`-of-config-file.js b/tests/baselines/reference/tscWatch/programUpdates/when-changing-`allowImportingTsExtensions`-of-config-file.js
new file mode 100644
index 0000000000000..b66e13c4bf181
--- /dev/null
+++ b/tests/baselines/reference/tscWatch/programUpdates/when-changing-`allowImportingTsExtensions`-of-config-file.js
@@ -0,0 +1,146 @@
+Input::
+//// [/user/username/projects/myproject/a.ts]
+
+
+//// [/user/username/projects/myproject/b.ts]
+import "./a.ts";
+
+//// [/user/username/projects/myproject/tsconfig.json]
+{"compilerOptions":{"noEmit":true,"allowImportingTsExtensions":false}}
+
+//// [/a/lib/lib.d.ts]
+///
+interface Boolean {}
+interface Function {}
+interface CallableFunction {}
+interface NewableFunction {}
+interface IArguments {}
+interface Number { toExponential: any; }
+interface Object {}
+interface RegExp {}
+interface String { charAt: any; }
+interface Array { length: number; [n: number]: T; }
+
+
+/a/lib/tsc.js -w -p . --extendedDiagnostics
+Output::
+[[90m12:00:23 AM[0m] Starting compilation in watch mode...
+
+Current directory: /user/username/projects/myproject CaseSensitiveFileNames: false
+FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 undefined Config file
+Synchronizing program
+CreatingProgramWith::
+ roots: ["/user/username/projects/myproject/a.ts","/user/username/projects/myproject/b.ts"]
+ options: {"noEmit":true,"allowImportingTsExtensions":false,"watch":true,"project":"/user/username/projects/myproject","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"}
+FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/a.ts 250 undefined Source file
+FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b.ts 250 undefined Source file
+FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 250 undefined Source file
+DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Type roots
+Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Type roots
+[96mb.ts[0m:[93m1[0m:[93m8[0m - [91merror[0m[90m TS5097: [0mAn import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
+
+[7m1[0m import "./a.ts";
+[7m [0m [91m ~~~~~~~~[0m
+
+[[90m12:00:24 AM[0m] Found 1 error. Watching for file changes.
+
+DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 1 undefined Wild card directory
+Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 1 undefined Wild card directory
+
+
+Program root files: ["/user/username/projects/myproject/a.ts","/user/username/projects/myproject/b.ts"]
+Program options: {"noEmit":true,"allowImportingTsExtensions":false,"watch":true,"project":"/user/username/projects/myproject","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"}
+Program structureReused: Not
+Program files::
+/a/lib/lib.d.ts
+/user/username/projects/myproject/a.ts
+/user/username/projects/myproject/b.ts
+
+Semantic diagnostics in builder refreshed for::
+/a/lib/lib.d.ts
+/user/username/projects/myproject/a.ts
+/user/username/projects/myproject/b.ts
+
+Shape signatures in builder refreshed for::
+/a/lib/lib.d.ts (used version)
+/user/username/projects/myproject/a.ts (used version)
+/user/username/projects/myproject/b.ts (used version)
+
+PolledWatches::
+/user/username/projects/myproject/node_modules/@types:
+ {"pollingInterval":500}
+
+FsWatches::
+/user/username/projects/myproject/tsconfig.json:
+ {}
+/user/username/projects/myproject/a.ts:
+ {}
+/user/username/projects/myproject/b.ts:
+ {}
+/a/lib/lib.d.ts:
+ {}
+
+FsWatchesRecursive::
+/user/username/projects/myproject:
+ {}
+
+exitCode:: ExitStatus.undefined
+
+
+Change:: Change allowImportingTsExtensions to true
+
+Input::
+//// [/user/username/projects/myproject/tsconfig.json]
+{"compilerOptions":{"noEmit":true,"allowImportingTsExtensions":true}}
+
+
+Output::
+FileWatcher:: Triggered with /user/username/projects/myproject/tsconfig.json 1:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 undefined Config file
+Scheduling update
+Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/tsconfig.json 1:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 undefined Config file
+Reloading config file: /user/username/projects/myproject/tsconfig.json
+Synchronizing program
+[[90m12:00:28 AM[0m] File change detected. Starting incremental compilation...
+
+CreatingProgramWith::
+ roots: ["/user/username/projects/myproject/a.ts","/user/username/projects/myproject/b.ts"]
+ options: {"noEmit":true,"allowImportingTsExtensions":true,"watch":true,"project":"/user/username/projects/myproject","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"}
+[[90m12:00:29 AM[0m] Found 0 errors. Watching for file changes.
+
+
+
+Program root files: ["/user/username/projects/myproject/a.ts","/user/username/projects/myproject/b.ts"]
+Program options: {"noEmit":true,"allowImportingTsExtensions":true,"watch":true,"project":"/user/username/projects/myproject","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"}
+Program structureReused: Completely
+Program files::
+/a/lib/lib.d.ts
+/user/username/projects/myproject/a.ts
+/user/username/projects/myproject/b.ts
+
+Semantic diagnostics in builder refreshed for::
+/a/lib/lib.d.ts
+/user/username/projects/myproject/a.ts
+/user/username/projects/myproject/b.ts
+
+No shapes updated in the builder::
+
+PolledWatches::
+/user/username/projects/myproject/node_modules/@types:
+ {"pollingInterval":500}
+
+FsWatches::
+/user/username/projects/myproject/tsconfig.json:
+ {}
+/user/username/projects/myproject/a.ts:
+ {}
+/user/username/projects/myproject/b.ts:
+ {}
+/a/lib/lib.d.ts:
+ {}
+
+FsWatchesRecursive::
+/user/username/projects/myproject:
+ {}
+
+exitCode:: ExitStatus.undefined
+
diff --git a/tests/cases/conformance/moduleResolution/allowImportingTsExtensions.ts b/tests/cases/conformance/moduleResolution/allowImportingTsExtensions.ts
new file mode 100644
index 0000000000000..24004050d2de0
--- /dev/null
+++ b/tests/cases/conformance/moduleResolution/allowImportingTsExtensions.ts
@@ -0,0 +1,29 @@
+// @allowImportingTsExtensions: true
+// @noEmit: true
+// @moduleResolution: classic,node10,node16,nodenext,bundler
+// @jsx: preserve
+// @noTypesAndSymbols: true
+
+// @Filename: /ts.ts
+export {};
+
+// @Filename: /tsx.tsx
+export {};
+
+// @Filename: /dts.d.ts
+export {};
+
+// @Filename: /b.ts
+import {} from "./ts.js";
+import {} from "./ts.ts";
+import type {} from "./ts.d.ts";
+
+import {} from "./tsx.js";
+import {} from "./tsx.jsx";
+import {} from "./tsx.ts";
+import {} from "./tsx.tsx";
+import type {} from "./tsx.d.ts";
+
+import {} from "./dts.js";
+import {} from "./dts.ts";
+import type {} from "./dts.d.ts";