diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts
index ae2025148fd4b..d2332db89a182 100644
--- a/src/compiler/moduleSpecifiers.ts
+++ b/src/compiler/moduleSpecifiers.ts
@@ -24,6 +24,7 @@ import {
ExportAssignment,
Extension,
extensionFromPath,
+ extensionsNotSupportingExtensionlessResolution,
fileExtensionIsOneOf,
FileIncludeKind,
firstDefined,
@@ -91,6 +92,7 @@ import {
removeExtension,
removeFileExtension,
removeSuffix,
+ removeTrailingDirectorySeparator,
ResolutionMode,
resolvePath,
ScriptKind,
@@ -1007,10 +1009,24 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan
// happens very easily in fourslash tests though, since every test file listed gets included. See
// importNameCodeFix_typesVersions.ts for an example.)
const mainExportFile = toPath(mainFileRelative, packageRootPath, getCanonicalFileName);
- if (removeFileExtension(mainExportFile) === removeFileExtension(getCanonicalFileName(moduleFileToTry))) {
+ const canonicalModuleFileToTry = getCanonicalFileName(moduleFileToTry);
+ if (removeFileExtension(mainExportFile) === removeFileExtension(canonicalModuleFileToTry)) {
// ^ An arbitrary removal of file extension for this comparison is almost certainly wrong
return { packageRootPath, moduleFileToTry };
}
+ else if (
+ packageJsonContent.type !== "module" &&
+ !fileExtensionIsOneOf(canonicalModuleFileToTry, extensionsNotSupportingExtensionlessResolution) &&
+ startsWith(canonicalModuleFileToTry, mainExportFile) &&
+ getDirectoryPath(canonicalModuleFileToTry) === removeTrailingDirectorySeparator(mainExportFile) &&
+ removeFileExtension(getBaseFileName(canonicalModuleFileToTry)) === "index"
+ ) {
+ // if mainExportFile is a directory, which contains moduleFileToTry, we just try index file
+ // example mainExportFile: `pkg/lib` and moduleFileToTry: `pkg/lib/index`, we can use packageRootPath
+ // but this behavior is deprecated for packages with "type": "module", so we only do this for packages without "type": "module"
+ // and make sure that the extension on index.{???} is something that supports omitting the extension
+ return { packageRootPath, moduleFileToTry };
+ }
}
}
else {
diff --git a/tests/cases/fourslash/autoImportPackageRootPath.ts b/tests/cases/fourslash/autoImportPackageRootPath.ts
new file mode 100644
index 0000000000000..843202e89edd9
--- /dev/null
+++ b/tests/cases/fourslash/autoImportPackageRootPath.ts
@@ -0,0 +1,26 @@
+///
+
+// @allowJs: true
+
+// @Filename: /node_modules/pkg/package.json
+//// {
+//// "name": "pkg",
+//// "version": "1.0.0",
+//// "main": "lib",
+//// "module": "lib"
+//// }
+
+// @Filename: /node_modules/pkg/lib/index.js
+//// export function foo() {};
+
+// @Filename: /package.json
+//// {
+//// "dependencies": {
+//// "pkg": "*"
+//// }
+//// }
+
+// @Filename: /index.ts
+//// foo/**/
+
+verify.importFixModuleSpecifiers("", ["pkg"]);
diff --git a/tests/cases/fourslash/autoImportPackageRootPathExtension.ts b/tests/cases/fourslash/autoImportPackageRootPathExtension.ts
new file mode 100644
index 0000000000000..dc1d08f34bfd9
--- /dev/null
+++ b/tests/cases/fourslash/autoImportPackageRootPathExtension.ts
@@ -0,0 +1,25 @@
+///
+
+// @allowJs: true
+
+// @Filename: /node_modules/pkg/package.json
+//// {
+//// "name": "pkg",
+//// "version": "1.0.0",
+//// "main": "lib"
+//// }
+
+// @Filename: /node_modules/pkg/lib/index.d.mts
+//// export declare function foo(): any;
+
+// @Filename: /package.json
+//// {
+//// "dependencies": {
+//// "pkg": "*"
+//// }
+//// }
+
+// @Filename: /index.ts
+//// foo/**/
+
+verify.importFixModuleSpecifiers("", ["pkg/lib/index.mjs"]);
diff --git a/tests/cases/fourslash/autoImportPackageRootPathTypeModule.ts b/tests/cases/fourslash/autoImportPackageRootPathTypeModule.ts
new file mode 100644
index 0000000000000..44b0825d5ea99
--- /dev/null
+++ b/tests/cases/fourslash/autoImportPackageRootPathTypeModule.ts
@@ -0,0 +1,26 @@
+///
+
+// @allowJs: true
+
+// @Filename: /node_modules/pkg/package.json
+//// {
+//// "name": "pkg",
+//// "version": "1.0.0",
+//// "main": "lib",
+//// "type": "module"
+//// }
+
+// @Filename: /node_modules/pkg/lib/index.js
+//// export function foo() {};
+
+// @Filename: /package.json
+//// {
+//// "dependencies": {
+//// "pkg": "*"
+//// }
+//// }
+
+// @Filename: /index.ts
+//// foo/**/
+
+verify.importFixModuleSpecifiers("", ["pkg/lib"]);