diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 290fa257da..6dd2747e33 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -1366,10 +1366,10 @@ namespace ts {
if (moduleNotFoundError) {
// report errors only if it was requested
- const nonDtsExtension = tryExtractTypeScriptExtensionNonDts(moduleName);
- if (nonDtsExtension) {
- const diag = Diagnostics.An_import_path_should_not_end_with_a_0_extension_Consider_importing_1_instead;
- error(moduleReferenceLiteral, diag, nonDtsExtension, removeExtension(moduleName, nonDtsExtension));
+ const tsExtension = tryExtractTypeScriptExtension(moduleName);
+ if (tsExtension) {
+ const diag = Diagnostics.An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead;
+ error(moduleReferenceLiteral, diag, tsExtension, removeExtension(moduleName, tsExtension));
}
else {
error(moduleReferenceLiteral, moduleNotFoundError, moduleName);
diff --git a/src/compiler/core.ts b/src/compiler/core.ts
index d77036660b..869cddb2d4 100644
--- a/src/compiler/core.ts
+++ b/src/compiler/core.ts
@@ -1198,8 +1198,7 @@ namespace ts {
/**
* List of supported extensions in order of file resolution precedence.
*/
- export const supportedTypeScriptExtensionsNonDts = [".ts", ".tsx"];
- export const supportedTypeScriptExtensions = supportedTypeScriptExtensionsNonDts.concat([".d.ts"]);
+ export const supportedTypeScriptExtensions = [".ts", ".tsx", ".d.ts"];
export const supportedJavascriptExtensions = [".js", ".jsx"];
const allSupportedExtensions = supportedTypeScriptExtensions.concat(supportedJavascriptExtensions);
diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json
index 93bd6c608f..8975e5daa0 100644
--- a/src/compiler/diagnosticMessages.json
+++ b/src/compiler/diagnosticMessages.json
@@ -1951,7 +1951,7 @@
"category": "Error",
"code": 2690
},
- "An import path should not end with a '{0}' extension. Consider importing '{1}' instead.": {
+ "An import path cannot end with a '{0}' extension. Consider importing '{1}' instead.": {
"category": "Error",
"code": 2691
},
diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index a2674d7978..d35ce64412 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -669,17 +669,7 @@ namespace ts {
* in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations.
*/
function loadModuleFromFile(candidate: string, extensions: string[], failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string | undefined {
- // If the candidate already has an extension load that or quit.
- if (hasTypeScriptFileExtension(candidate)) {
- // Don't allow `.ts` to appear at the end
- if (!fileExtensionIs(candidate, ".d.ts")) {
- return undefined;
- }
- return tryFile(candidate, failedLookupLocation, onlyRecordFailures, state);
- }
-
- // Next, try adding an extension.
- // We don't allow an import of "foo.ts" to be matched by "foo.ts.ts", but we do allow "foo.js" to be matched by "foo.js.ts".
+ // First, try adding an extension. An import of "foo" could be matched by a file "foo.ts", or "foo.js" by "foo.js.ts"
const resolvedByAddingExtension = tryAddingExtensions(candidate, extensions, failedLookupLocation, onlyRecordFailures, state);
if (resolvedByAddingExtension) {
return resolvedByAddingExtension;
@@ -736,7 +726,9 @@ namespace ts {
}
const typesFile = tryReadTypesSection(packageJsonPath, candidate, state);
if (typesFile) {
- const result = loadModuleFromFile(typesFile, extensions, failedLookupLocation, !directoryProbablyExists(getDirectoryPath(typesFile), state.host), state);
+ const onlyRecordFailures = !directoryProbablyExists(getDirectoryPath(typesFile), state.host);
+ // The package.json "typings" property must specify the file with extension, so just try that exact filename.
+ const result = tryFile(typesFile, failedLookupLocation, onlyRecordFailures, state);
if (result) {
return result;
}
diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts
index b92037b7e5..22c9355072 100644
--- a/src/compiler/utilities.ts
+++ b/src/compiler/utilities.ts
@@ -2727,9 +2727,11 @@ namespace ts {
}
/** Return ".ts" or ".tsx" if that is the extension. */
- export function tryExtractTypeScriptExtensionNonDts(fileName: string): string | undefined {
- return find(supportedTypeScriptExtensionsNonDts, extension => fileExtensionIs(fileName, extension));
+ export function tryExtractTypeScriptExtension(fileName: string): string | undefined {
+ return find(supportedTypescriptExtensionsWithDtsFirst, extension => fileExtensionIs(fileName, extension));
}
+ // Must have '.d.ts' first because if '.ts' goes first, that will be detected as the extension instead of '.d.ts'.
+ const supportedTypescriptExtensionsWithDtsFirst = supportedTypeScriptExtensions.slice().reverse();
/**
* Replace each instance of non-ascii characters by one, two, three, or four escape sequences
diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts
index ecdc18394b..b8467adda5 100644
--- a/src/harness/compilerRunner.ts
+++ b/src/harness/compilerRunner.ts
@@ -52,7 +52,7 @@ class CompilerBaselineRunner extends RunnerBase {
private makeUnitName(name: string, root: string) {
const path = ts.toPath(name, root, (fileName) => Harness.Compiler.getCanonicalFileName(fileName));
const pathStart = ts.toPath(Harness.IO.getCurrentDirectory(), "", (fileName) => Harness.Compiler.getCanonicalFileName(fileName));
- return path.replace(pathStart, "/");
+ return pathStart === "" ? path : path.replace(pathStart, "/");
};
public checkTestCodeOutput(fileName: string) {
diff --git a/tests/baselines/reference/moduleResolutionNoTs.errors.txt b/tests/baselines/reference/moduleResolutionNoTs.errors.txt
index 2a9b74a1af..c054330731 100644
--- a/tests/baselines/reference/moduleResolutionNoTs.errors.txt
+++ b/tests/baselines/reference/moduleResolutionNoTs.errors.txt
@@ -1,25 +1,31 @@
-tests/cases/compiler/user.ts(4,15): error TS2691: An import path should not end with a '.ts' extension. Consider importing './x' instead.
-tests/cases/compiler/user.ts(5,15): error TS2691: An import path should not end with a '.tsx' extension. Consider importing './y' instead.
+tests/cases/compiler/user.ts(1,15): error TS2691: An import path cannot end with a '.ts' extension. Consider importing './x' instead.
+tests/cases/compiler/user.ts(2,15): error TS2691: An import path cannot end with a '.tsx' extension. Consider importing './y' instead.
+tests/cases/compiler/user.ts(3,15): error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './z' instead.
-==== tests/cases/compiler/user.ts (2 errors) ====
- // '.ts' extension is OK in a reference
- ///
-
- import x from "./x.ts";
- ~~~~~~~~
-!!! error TS2691: An import path should not end with a '.ts' extension. Consider importing './x' instead.
- import y from "./y.tsx";
- ~~~~~~~~~
-!!! error TS2691: An import path should not end with a '.tsx' extension. Consider importing './y' instead.
-
- // Making sure the suggested fixes are valid:
- import x2 from "./x";
- import y2 from "./y";
-
==== tests/cases/compiler/x.ts (0 errors) ====
export default 0;
==== tests/cases/compiler/y.tsx (0 errors) ====
export default 0;
+
+==== tests/cases/compiler/z.d.ts (0 errors) ====
+ declare const x: number;
+ export default x;
+
+==== tests/cases/compiler/user.ts (3 errors) ====
+ import x from "./x.ts";
+ ~~~~~~~~
+!!! error TS2691: An import path cannot end with a '.ts' extension. Consider importing './x' instead.
+ import y from "./y.tsx";
+ ~~~~~~~~~
+!!! error TS2691: An import path cannot end with a '.tsx' extension. Consider importing './y' instead.
+ import z from "./z.d.ts";
+ ~~~~~~~~~~
+!!! error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './z' instead.
+
+ // Making sure the suggested fixes are valid:
+ import x2 from "./x";
+ import y2 from "./y";
+ import z2 from "./z";
\ No newline at end of file
diff --git a/tests/baselines/reference/moduleResolutionNoTs.js b/tests/baselines/reference/moduleResolutionNoTs.js
index d9d918f560..9ff33d688e 100644
--- a/tests/baselines/reference/moduleResolutionNoTs.js
+++ b/tests/baselines/reference/moduleResolutionNoTs.js
@@ -6,16 +6,19 @@ export default 0;
//// [y.tsx]
export default 0;
+//// [z.d.ts]
+declare const x: number;
+export default x;
+
//// [user.ts]
-// '.ts' extension is OK in a reference
-///
-
import x from "./x.ts";
import y from "./y.tsx";
+import z from "./z.d.ts";
// Making sure the suggested fixes are valid:
import x2 from "./x";
import y2 from "./y";
+import z2 from "./z";
//// [x.js]
@@ -27,6 +30,4 @@ exports["default"] = 0;
exports.__esModule = true;
exports["default"] = 0;
//// [user.js]
-// '.ts' extension is OK in a reference
-///
"use strict";
diff --git a/tests/cases/compiler/moduleResolutionNoTs.ts b/tests/cases/compiler/moduleResolutionNoTs.ts
index 683f6630d9..2051bc259b 100644
--- a/tests/cases/compiler/moduleResolutionNoTs.ts
+++ b/tests/cases/compiler/moduleResolutionNoTs.ts
@@ -4,13 +4,16 @@ export default 0;
// @filename: y.tsx
export default 0;
-// @filename: user.ts
-// '.ts' extension is OK in a reference
-///
+// @filename: z.d.ts
+declare const x: number;
+export default x;
+// @filename: user.ts
import x from "./x.ts";
import y from "./y.tsx";
+import z from "./z.d.ts";
// Making sure the suggested fixes are valid:
import x2 from "./x";
import y2 from "./y";
+import z2 from "./z";