diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 20d075cdfc07f..8842735df2942 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -3607,6 +3607,7 @@ namespace ts {
(isModuleDeclaration(location) ? location : location.parent && isModuleDeclaration(location.parent) && location.parent.name === location ? location.parent : undefined)?.name ||
(isLiteralImportTypeNode(location) ? location : undefined)?.argument.literal;
const mode = contextSpecifier && isStringLiteralLike(contextSpecifier) ? getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat;
+ const moduleResolutionKind = getEmitModuleResolutionKind(compilerOptions);
const resolvedModule = getResolvedModule(currentSourceFile, moduleReference, mode);
const resolutionDiagnostic = resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule);
const sourceFile = resolvedModule
@@ -3617,11 +3618,43 @@ namespace ts {
if (resolutionDiagnostic) {
error(errorNode, resolutionDiagnostic, moduleReference, resolvedModule.resolvedFileName);
}
+
+ if (moduleResolutionKind === ModuleResolutionKind.Minimal && pathContainsNodeModules(moduleReference)) {
+ // A relative import into node_modules is a problem for a few reasons:
+ // 1. Portability - if the code gets published as a library, it will very likely break
+ // 2. It's unclear how we should resolve types. By typical relative import rules, we
+ // would ignore package.json fields that tell us where to find types and would have
+ // no special behavior linking up node_modules/@types with their implementations -
+ // we would only find .d.ts files as siblings of .js files. Any package that puts
+ // their types in a separate directory, or is typed by @types, would be broken.
+ // Some of these redirections would be safe to do, but others might reflect
+ // Node-specific resolution features that would only work with non-relative imports.
+ // The module resolver still returns a result, because it's possible for a module in
+ // node_modules to end up in the program, and module specifier generation assumes that it
+ // is always possible to generate a module specifier, even if it also generates a diagnostic.
+ error(errorNode, Diagnostics.Relative_imports_into_node_modules_are_not_allowed);
+ }
+ else if (resolvedModule.resolvedUsingTsExtension && isDeclarationFileName(moduleReference)) {
+ const importOrExport =
+ findAncestor(location, isImportDeclaration)?.importClause ||
+ findAncestor(location, or(isImportEqualsDeclaration, isExportDeclaration));
+ if (importOrExport && !importOrExport.isTypeOnly || findAncestor(location, isImportCall)) {
+ error(
+ errorNode,
+ Diagnostics.A_declaration_file_cannot_be_imported_without_import_type_Did_you_mean_to_import_an_implementation_file_0_instead,
+ getSuggestedImportSource(Debug.checkDefined(tryExtractTSExtension(moduleReference))));
+ }
+ }
+ else if (resolvedModule.resolvedUsingTsExtension && !shouldAllowImportingTsExtension(compilerOptions, currentSourceFile.fileName)) {
+ const tsExtension = Debug.checkDefined(tryExtractTSExtension(moduleReference));
+ error(errorNode, Diagnostics.An_import_path_can_only_end_with_a_0_extension_when_allowImportingTsExtensions_is_enabled, tsExtension);
+ }
+
if (sourceFile.symbol) {
if (resolvedModule.isExternalLibraryImport && !resolutionExtensionIsTSOrJson(resolvedModule.extension)) {
errorOnImplicitAnyModule(/*isError*/ false, errorNode, resolvedModule, moduleReference);
}
- if (getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext) {
+ if (moduleResolutionKind === ModuleResolutionKind.Node16 || moduleResolutionKind === ModuleResolutionKind.NodeNext) {
const isSyncImport = (currentSourceFile.impliedNodeFormat === ModuleKind.CommonJS && !findAncestor(location, isImportCall)) || !!findAncestor(location, isImportEqualsDeclaration);
const overrideClauseHost = findAncestor(location, l => isImportTypeNode(l) || isExportDeclaration(l) || isImportDeclaration(l)) as ImportTypeNode | ImportDeclaration | ExportDeclaration | undefined;
const overrideClause = overrideClauseHost && isImportTypeNode(overrideClauseHost) ? overrideClauseHost.assertions?.assertClause : overrideClauseHost?.assertClause;
@@ -3729,25 +3762,17 @@ namespace ts {
else {
const tsExtension = tryExtractTSExtension(moduleReference);
const isExtensionlessRelativePathImport = pathIsRelative(moduleReference) && !hasExtension(moduleReference);
- const moduleResolutionKind = getEmitModuleResolutionKind(compilerOptions);
const resolutionIsNode16OrNext = moduleResolutionKind === ModuleResolutionKind.Node16 ||
moduleResolutionKind === ModuleResolutionKind.NodeNext;
- if (tsExtension) {
- const diag = Diagnostics.An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead;
- const importSourceWithoutExtension = removeExtension(moduleReference, tsExtension);
- let replacedImportSource = importSourceWithoutExtension;
- /**
- * Direct users to import source with .js extension if outputting an ES module.
- * @see https://github.com/microsoft/TypeScript/issues/42151
- */
- if (moduleKind >= ModuleKind.ES2015) {
- replacedImportSource += tsExtension === Extension.Mts ? ".mjs" : tsExtension === Extension.Cts ? ".cjs" : ".js";
- }
- error(errorNode, diag, tsExtension, replacedImportSource);
+ if (moduleResolutionKind === ModuleResolutionKind.Minimal && pathContainsNodeModules(moduleReference)) {
+ error(errorNode, Diagnostics.Relative_imports_into_node_modules_are_not_allowed);
+ }
+ else if (tsExtension) {
+ errorOnTSExtensionImport(tsExtension);
}
else if (!compilerOptions.resolveJsonModule &&
fileExtensionIs(moduleReference, Extension.Json) &&
- getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Classic &&
+ moduleResolutionKind !== ModuleResolutionKind.Classic &&
hasJsonModuleEmitEnabled(compilerOptions)) {
error(errorNode, Diagnostics.Cannot_find_module_0_Consider_using_resolveJsonModule_to_import_module_with_json_extension, moduleReference);
}
@@ -3769,6 +3794,23 @@ namespace ts {
}
}
return undefined;
+
+ function errorOnTSExtensionImport(tsExtension: string) {
+ const diag = Diagnostics.An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead;
+ error(errorNode, diag, tsExtension, getSuggestedImportSource(tsExtension));
+ }
+
+ function getSuggestedImportSource(tsExtension: string) {
+ const importSourceWithoutExtension = removeExtension(moduleReference, tsExtension);
+ /**
+ * Direct users to import source with .js extension if outputting an ES module.
+ * @see https://github.com/microsoft/TypeScript/issues/42151
+ */
+ if (moduleKind >= ModuleKind.ES2015 || getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Minimal) {
+ return importSourceWithoutExtension + (tsExtension === Extension.Mts ? ".mjs" : tsExtension === Extension.Cts ? ".cjs" : ".js");
+ }
+ return importSourceWithoutExtension;
+ }
}
function errorOnImplicitAnyModule(isError: boolean, errorNode: Node, { packageId, resolvedFileName }: ResolvedModuleFull, moduleReference: string): void {
diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts
index b3dcb04c777d9..2c15cf46ab842 100644
--- a/src/compiler/commandLineParser.ts
+++ b/src/compiler/commandLineParser.ts
@@ -839,6 +839,7 @@ namespace ts {
classic: ModuleResolutionKind.Classic,
node16: ModuleResolutionKind.Node16,
nodenext: ModuleResolutionKind.NodeNext,
+ minimal: ModuleResolutionKind.Minimal,
})),
affectsModuleResolution: true,
paramType: Diagnostics.STRATEGY,
@@ -955,6 +956,14 @@ namespace ts {
category: Diagnostics.Modules,
description: Diagnostics.List_of_file_name_suffixes_to_search_when_resolving_a_module,
},
+ {
+ name: "allowImportingTsExtensions",
+ type: "boolean",
+ affectsModuleResolution: true,
+ category: Diagnostics.Modules,
+ description: Diagnostics.Allow_imports_to_include_TypeScript_file_extensions_Requires_moduleResolution_minimal_and_either_noEmit_or_emitDeclarationOnly_to_be_set,
+ defaultValueDescription: false,
+ },
// Source Maps
{
diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json
index 7a8f3192d917c..cea15688a0f65 100644
--- a/src/compiler/diagnosticMessages.json
+++ b/src/compiler/diagnosticMessages.json
@@ -3567,6 +3567,14 @@
"category": "Error",
"code": 2845
},
+ "A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file '{0}' instead?": {
+ "category": "Error",
+ "code": 2846
+ },
+ "Relative imports into 'node_modules' are not allowed.": {
+ "category": "Error",
+ "code": 2847
+ },
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
@@ -4225,6 +4233,14 @@
"category": "Error",
"code": 5095
},
+ "Option 'allowImportingTsExtensions' can only be used when 'moduleResolution' is set to 'minimal' and either 'noEmit' or 'emitDeclarationOnly' is set.": {
+ "category": "Error",
+ "code": 5096
+ },
+ "An import path can only end with a '{0}' extension when 'allowImportingTsExtensions' is enabled.": {
+ "category": "Error",
+ "code": 5097
+ },
"Generates a sourcemap for each corresponding '.d.ts' file.": {
"category": "Message",
@@ -4447,10 +4463,6 @@
"category": "Message",
"code": 6066
},
- "Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6).": {
- "category": "Message",
- "code": 6069
- },
"Initializes a TypeScript project and creates a tsconfig.json file.": {
"category": "Message",
"code": 6070
@@ -5414,6 +5426,10 @@
"category": "Message",
"code": 6401
},
+ "Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set.": {
+ "category": "Message",
+ "code": 6402
+ },
"The expected type comes from property '{0}' which is declared here on type '{1}'": {
"category": "Message",
diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts
index 222d1dee63f4d..a15f98cd95717 100644
--- a/src/compiler/moduleNameResolver.ts
+++ b/src/compiler/moduleNameResolver.ts
@@ -22,7 +22,11 @@ namespace ts {
};
}
}
- return r && { path: r.path, extension: r.ext, packageId };
+ return r && { path: r.path, extension: r.ext, packageId, resolvedUsingTsExtension: r.resolvedUsingTsExtension };
+ }
+
+ function createLoaderWithNoPackageId
(loader: (...args: P) => PathAndExtension | undefined): (...args: P) => Resolved | undefined {
+ return (...args) => noPackageId(loader(...args));
}
function noPackageId(r: PathAndExtension | undefined): Resolved | undefined {
@@ -32,7 +36,7 @@ namespace ts {
function removeIgnoredPackageId(r: Resolved | undefined): PathAndExtension | undefined {
if (r) {
Debug.assert(r.packageId === undefined);
- return { path: r.path, ext: r.extension };
+ return { path: r.path, ext: r.extension, resolvedUsingTsExtension: r.resolvedUsingTsExtension };
}
}
@@ -51,6 +55,7 @@ namespace ts {
* Note: This is a file name with preserved original casing, not a normalized `Path`.
*/
originalPath?: string | true;
+ resolvedUsingTsExtension: boolean | undefined;
}
/** Result of trying to resolve a module at a file. Needs to have 'packageId' added later. */
@@ -58,6 +63,7 @@ namespace ts {
path: string;
// (Use a different name than `extension` to make sure Resolved isn't assignable to PathAndExtension.)
ext: Extension;
+ resolvedUsingTsExtension: boolean | undefined;
}
/**
@@ -100,7 +106,14 @@ namespace ts {
return resultFromCache;
}
return {
- resolvedModule: resolved && { resolvedFileName: resolved.path, originalPath: resolved.originalPath === true ? undefined : resolved.originalPath, extension: resolved.extension, isExternalLibraryImport, packageId: resolved.packageId },
+ resolvedModule: resolved && {
+ resolvedFileName: resolved.path,
+ originalPath: resolved.originalPath === true ? undefined : resolved.originalPath,
+ extension: resolved.extension,
+ isExternalLibraryImport,
+ packageId: resolved.packageId,
+ resolvedUsingTsExtension: !!resolved.resolvedUsingTsExtension,
+ },
failedLookupLocations,
affectingLocations,
resolutionDiagnostics: diagnostics,
@@ -1020,6 +1033,9 @@ namespace ts {
case ModuleResolutionKind.Classic:
result = classicNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference);
break;
+ case ModuleResolutionKind.Minimal:
+ result = minimalModuleNameResolver(moduleName, containingFile, compilerOptions, host);
+ break;
default:
return Debug.fail(`Unexpected moduleResolution: ${moduleResolution}`);
}
@@ -1559,7 +1575,10 @@ namespace ts {
function loadModuleFromFileNoImplicitExtensions(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined {
// If that didn't work, try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one;
// e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts"
- if (hasJSFileExtension(candidate) || (fileExtensionIs(candidate, Extension.Json) && state.compilerOptions.resolveJsonModule)) {
+ if (hasJSFileExtension(candidate) ||
+ (state.compilerOptions.resolveJsonModule && fileExtensionIs(candidate, Extension.Json)) ||
+ (shouldResolveTsExtension(state.compilerOptions) && fileExtensionIsOneOf(candidate, supportedTSExtensionsFlat))
+ ) {
const extensionless = removeFileExtension(candidate);
const extension = candidate.substring(extensionless.length);
if (state.traceEnabled) {
@@ -1572,7 +1591,7 @@ namespace ts {
function loadJSOrExactTSFileName(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined {
if ((extensions === Extensions.TypeScript || extensions === Extensions.DtsOnly) && fileExtensionIsOneOf(candidate, supportedTSExtensionsFlat)) {
const result = tryFile(candidate, onlyRecordFailures, state);
- return result !== undefined ? { path: candidate, ext: tryExtractTSExtension(candidate) as Extension } : undefined;
+ return result !== undefined ? { path: candidate, ext: tryExtractTSExtension(candidate) as Extension, resolvedUsingTsExtension: undefined } : undefined;
}
return loadModuleFromFileNoImplicitExtensions(extensions, candidate, onlyRecordFailures, state);
@@ -1619,6 +1638,13 @@ namespace ts {
case Extension.Json:
candidate += Extension.Json;
return useDts ? tryExtension(Extension.Dts) : undefined;
+ case Extension.Ts:
+ case Extension.Tsx:
+ case Extension.Dts:
+ if (shouldResolveTsExtension(state.compilerOptions)) {
+ return tryExtension(originalExtension, /*resolvedUsingTsExtension*/ true);
+ }
+ // falls through
default:
return tryExtension(Extension.Ts) || tryExtension(Extension.Tsx) || (useDts ? tryExtension(Extension.Dts) : undefined);
}
@@ -1642,9 +1668,9 @@ namespace ts {
return tryExtension(Extension.Json);
}
- function tryExtension(ext: Extension): PathAndExtension | undefined {
+ function tryExtension(ext: Extension, resolvedUsingTsExtension?: boolean): PathAndExtension | undefined {
const path = tryFile(candidate + ext, onlyRecordFailures, state);
- return path === undefined ? undefined : { path, ext };
+ return path === undefined ? undefined : { path, ext, resolvedUsingTsExtension };
}
}
@@ -1959,9 +1985,9 @@ namespace ts {
}
/** Resolve from an arbitrarily specified file. Return `undefined` if it has an unsupported extension. */
- function resolvedIfExtensionMatches(extensions: Extensions, path: string): PathAndExtension | undefined {
+ function resolvedIfExtensionMatches(extensions: Extensions, path: string, resolvedUsingTsExtension?: boolean): PathAndExtension | undefined {
const ext = tryGetExtensionFromPath(path);
- return ext !== undefined && extensionIsOk(extensions, ext) ? { path, ext } : undefined;
+ return ext !== undefined && extensionIsOk(extensions, ext) ? { path, ext, resolvedUsingTsExtension } : undefined;
}
/** True if `extension` is one of the supported `extensions`. */
@@ -2158,7 +2184,13 @@ namespace ts {
if (isImports && !startsWith(target, "../") && !startsWith(target, "/") && !isRootedDiskPath(target)) {
const combinedLookup = pattern ? target.replace(/\*/g, subpath) : target + subpath;
const result = nodeModuleNameResolverWorker(state.features, combinedLookup, scope.packageDirectory + "/", state.compilerOptions, state.host, cache, [extensions], redirectedReference);
- return toSearchResult(result.resolvedModule ? { path: result.resolvedModule.resolvedFileName, extension: result.resolvedModule.extension, packageId: result.resolvedModule.packageId, originalPath: result.resolvedModule.originalPath } : undefined);
+ return toSearchResult(result.resolvedModule ? {
+ path: result.resolvedModule.resolvedFileName,
+ extension: result.resolvedModule.extension,
+ packageId: result.resolvedModule.packageId,
+ originalPath: result.resolvedModule.originalPath,
+ resolvedUsingTsExtension: result.resolvedModule.resolvedUsingTsExtension
+ } : undefined);
}
if (state.traceEnabled) {
trace(state.host, Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName);
@@ -2506,7 +2538,7 @@ namespace ts {
if (extension !== undefined) {
const path = tryFile(candidate, onlyRecordFailures, state);
if (path !== undefined) {
- return noPackageId({ path, ext: extension });
+ return noPackageId({ path, ext: extension, resolvedUsingTsExtension: undefined });
}
}
return loader(extensions, candidate, onlyRecordFailures || !directoryProbablyExists(getDirectoryPath(candidate), state.host), state);
@@ -2566,7 +2598,15 @@ namespace ts {
trace(state.host, Diagnostics.Resolution_for_module_0_was_found_in_cache_from_location_1, moduleName, containingDirectory);
}
state.resultFromCache = result;
- return { value: result.resolvedModule && { path: result.resolvedModule.resolvedFileName, originalPath: result.resolvedModule.originalPath || true, extension: result.resolvedModule.extension, packageId: result.resolvedModule.packageId } };
+ return {
+ value: result.resolvedModule && {
+ path: result.resolvedModule.resolvedFileName,
+ originalPath: result.resolvedModule.originalPath || true,
+ extension: result.resolvedModule.extension,
+ packageId: result.resolvedModule.packageId,
+ resolvedUsingTsExtension: result.resolvedModule.resolvedUsingTsExtension
+ }
+ };
}
}
@@ -2631,6 +2671,58 @@ namespace ts {
}
}
+ export function minimalModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
+ const traceEnabled = isTraceEnabled(compilerOptions, host);
+ const failedLookupLocations: string[] = [];
+ const affectingLocations: string[] = [];
+ const containingDirectory = getDirectoryPath(containingFile);
+ const diagnostics: Diagnostic[] = [];
+ const state: ModuleResolutionState = {
+ compilerOptions,
+ host,
+ traceEnabled,
+ failedLookupLocations,
+ affectingLocations,
+ packageJsonInfoCache: undefined,
+ features: NodeResolutionFeatures.None,
+ conditions: [],
+ requestContainingDirectory: containingDirectory,
+ reportDiagnostic: diag => void diagnostics.push(diag),
+ };
+
+ const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
+ return createResolvedModuleWithFailedLookupLocations(
+ tryResolve(Extensions.TypeScript) || tryResolve(Extensions.JavaScript),
+ /*isExternalLibraryImport*/ false,
+ failedLookupLocations,
+ affectingLocations,
+ diagnostics,
+ state.resultFromCache);
+
+ function tryResolve(extensions: Extensions) {
+ const resolvedUsingSettings = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, createLoaderWithNoPackageId(loadModuleFromFileNoImplicitExtensions), state);
+ if (resolvedUsingSettings) {
+ return resolvedUsingSettings;
+ }
+ const resolvedRelative = loadModuleFromFileNoImplicitExtensions(extensions, candidate, /*onlyRecordFailures*/ false, state);
+ if (resolvedRelative) {
+ return noPackageId(resolvedRelative);
+ }
+ }
+ }
+
+ export function shouldResolveTsExtension(compilerOptions: CompilerOptions) {
+ return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Minimal;
+ }
+
+ // 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 shouldResolveTsExtension(compilerOptions) && (
+ !!compilerOptions.allowImportingTsExtensions ||
+ fromFileName && isDeclarationFileName(fromFileName));
+ }
+
/**
* A host may load a module from a global cache of typings.
* This is the minumum code needed to expose that functionality; the rest is in the host.
diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts
index 32640fcb81579..119a55565f34d 100644
--- a/src/compiler/moduleSpecifiers.ts
+++ b/src/compiler/moduleSpecifiers.ts
@@ -3,49 +3,87 @@
namespace ts.moduleSpecifiers {
const enum RelativePreference { Relative, NonRelative, Shortest, ExternalNonRelative }
// See UserPreferences#importPathEnding
- const enum Ending { Minimal, Index, JsExtension }
+ const enum Ending { Minimal, Index, JsExtension, TsExtension }
// Processed preferences
interface Preferences {
readonly relativePreference: RelativePreference;
- readonly ending: Ending;
+ /**
+ * @param syntaxImpliedNodeFormat Used when the import syntax implies ESM or CJS irrespective of the mode of the file.
+ */
+ getAllowedEndingsInPrefererredOrder(syntaxImpliedNodeFormat?: SourceFile["impliedNodeFormat"]): Ending[];
}
- function getPreferences(host: ModuleSpecifierResolutionHost, { importModuleSpecifierPreference, importModuleSpecifierEnding }: UserPreferences, compilerOptions: CompilerOptions, importingSourceFile: SourceFile): Preferences {
+ function getPreferences(
+ host: ModuleSpecifierResolutionHost,
+ { importModuleSpecifierPreference, importModuleSpecifierEnding }: UserPreferences,
+ compilerOptions: CompilerOptions,
+ importingSourceFile: SourceFile,
+ oldImportSpecifier?: string,
+ ): Preferences {
+ const preferredEnding = getPreferredEnding();
return {
relativePreference:
+ oldImportSpecifier !== undefined ? (isExternalModuleNameRelative(oldImportSpecifier) ?
+ RelativePreference.Relative :
+ RelativePreference.NonRelative) :
importModuleSpecifierPreference === "relative" ? RelativePreference.Relative :
importModuleSpecifierPreference === "non-relative" ? RelativePreference.NonRelative :
importModuleSpecifierPreference === "project-relative" ? RelativePreference.ExternalNonRelative :
RelativePreference.Shortest,
- ending: getEnding(),
+ getAllowedEndingsInPrefererredOrder: syntaxImpliedNodeFormat => {
+ if (syntaxImpliedNodeFormat === ModuleKind.ESNext ||
+ getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Minimal ||
+ isFormatRequiringExtensions()
+ ) {
+ if (shouldAllowImportingTsExtension(compilerOptions, importingSourceFile.fileName)) {
+ return [Ending.TsExtension, Ending.JsExtension];
+ }
+ return [Ending.JsExtension];
+ }
+ if (getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Classic) {
+ return [Ending.Index, Ending.JsExtension];
+ }
+ switch (preferredEnding) {
+ case Ending.JsExtension: return [Ending.JsExtension, Ending.Minimal, Ending.Index];
+ case Ending.TsExtension: return [Ending.TsExtension, Ending.TsExtension, Ending.Minimal, Ending.Index];
+ case Ending.Index: return [Ending.Index, Ending.Minimal, Ending.JsExtension];
+ case Ending.Minimal: return [Ending.Minimal, Ending.Index, Ending.JsExtension];
+ default: Debug.assertNever(preferredEnding);
+ }
+ },
};
- function getEnding(): Ending {
+
+ function getPreferredEnding(): Ending {
+ if (oldImportSpecifier !== undefined) {
+ if (hasJSFileExtension(oldImportSpecifier)) return Ending.JsExtension;
+ if (endsWith(oldImportSpecifier, "/index")) return Ending.Index;
+ }
switch (importModuleSpecifierEnding) {
case "minimal": return Ending.Minimal;
case "index": return Ending.Index;
- case "js": return Ending.JsExtension;
- default: return usesJsExtensionOnImports(importingSourceFile) || isFormatRequiringExtensions(compilerOptions, importingSourceFile.path, host) ? Ending.JsExtension
- : getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeJs ? Ending.Index : Ending.Minimal;
+ case "js": return shouldAllowImportingTsExtension(compilerOptions) ? Ending.TsExtension : Ending.JsExtension;
+ default: return usesExtensionsOnImports(importingSourceFile)
+ ? shouldAllowImportingTsExtension(compilerOptions) ? Ending.TsExtension : Ending.JsExtension
+ : Ending.Minimal;
}
}
- }
-
- function getPreferencesForUpdate(compilerOptions: CompilerOptions, oldImportSpecifier: string, importingSourceFileName: Path, host: ModuleSpecifierResolutionHost): Preferences {
- return {
- relativePreference: isExternalModuleNameRelative(oldImportSpecifier) ? RelativePreference.Relative : RelativePreference.NonRelative,
- ending: hasJSFileExtension(oldImportSpecifier) || isFormatRequiringExtensions(compilerOptions, importingSourceFileName, host) ?
- Ending.JsExtension :
- getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeJs || endsWith(oldImportSpecifier, "index") ? Ending.Index : Ending.Minimal,
- };
- }
- function isFormatRequiringExtensions(compilerOptions: CompilerOptions, importingSourceFileName: Path, host: ModuleSpecifierResolutionHost) {
- if (getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Node16
- && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeNext) {
- return false;
+ function isFormatRequiringExtensions() {
+ switch (getEmitModuleResolutionKind(compilerOptions)) {
+ case ModuleResolutionKind.Minimal:
+ return true;
+ case ModuleResolutionKind.Node16:
+ case ModuleResolutionKind.NodeNext:
+ return getImpliedNodeFormatForFile(
+ importingSourceFile.path,
+ host.getPackageJsonInfoCache?.(),
+ getModuleResolutionHost(host), compilerOptions,
+ ) !== ModuleKind.CommonJS;
+ default:
+ return false;
+ }
}
- return getImpliedNodeFormatForFile(importingSourceFileName, host.getPackageJsonInfoCache?.(), getModuleResolutionHost(host), compilerOptions) !== ModuleKind.CommonJS;
}
function getModuleResolutionHost(host: ModuleSpecifierResolutionHost): ModuleResolutionHost {
@@ -72,7 +110,7 @@ namespace ts.moduleSpecifiers {
oldImportSpecifier: string,
options: ModuleSpecifierOptions = {},
): string | undefined {
- const res = getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName, host, getPreferencesForUpdate(compilerOptions, oldImportSpecifier, importingSourceFileName, host), {}, options);
+ const res = getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName, host, getPreferences(host, {}, compilerOptions, importingSourceFile, oldImportSpecifier), {}, options);
if (res === oldImportSpecifier) return undefined;
return res;
}
@@ -293,11 +331,13 @@ namespace ts.moduleSpecifiers {
return { getCanonicalFileName, importingSourceFileName, sourceDirectory };
}
- function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOptions: CompilerOptions, host: ModuleSpecifierResolutionHost, importMode: SourceFile["impliedNodeFormat"], { ending, relativePreference }: Preferences): string {
+ function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOptions: CompilerOptions, host: ModuleSpecifierResolutionHost, importMode: SourceFile["impliedNodeFormat"], { getAllowedEndingsInPrefererredOrder, relativePreference }: Preferences): string {
const { baseUrl, paths, rootDirs } = compilerOptions;
const { sourceDirectory, getCanonicalFileName } = info;
+ const allowedEndings = getAllowedEndingsInPrefererredOrder(importMode);
+ const ending = allowedEndings[0];
const relativePath = rootDirs && tryGetModuleNameFromRootDirs(rootDirs, moduleFileName, sourceDirectory, getCanonicalFileName, ending, compilerOptions) ||
- removeExtensionAndIndexPostFix(ensurePathIsNonModuleName(getRelativePathFromDirectory(sourceDirectory, moduleFileName, getCanonicalFileName)), ending, compilerOptions);
+ processEnding(ensurePathIsNonModuleName(getRelativePathFromDirectory(sourceDirectory, moduleFileName, getCanonicalFileName)), ending, compilerOptions);
if (!baseUrl && !paths || relativePreference === RelativePreference.Relative) {
return relativePath;
}
@@ -308,8 +348,8 @@ namespace ts.moduleSpecifiers {
return relativePath;
}
- const fromPaths = paths && tryGetModuleNameFromPaths(relativeToBaseUrl, paths, getAllowedEndings(ending, compilerOptions, importMode), host, compilerOptions);
- const nonRelative = fromPaths === undefined && baseUrl !== undefined ? removeExtensionAndIndexPostFix(relativeToBaseUrl, ending, compilerOptions) : fromPaths;
+ const fromPaths = paths && tryGetModuleNameFromPaths(relativeToBaseUrl, paths, allowedEndings, host, compilerOptions);
+ const nonRelative = fromPaths === undefined && baseUrl !== undefined ? processEnding(relativeToBaseUrl, ending, compilerOptions) : fromPaths;
if (!nonRelative) {
return relativePath;
}
@@ -369,8 +409,8 @@ namespace ts.moduleSpecifiers {
return count;
}
- function usesJsExtensionOnImports({ imports }: SourceFile): boolean {
- return firstDefined(imports, ({ text }) => pathIsRelative(text) ? hasJSFileExtension(text) : undefined) || false;
+ function usesExtensionsOnImports({ imports }: SourceFile): boolean {
+ return firstDefined(imports, ({ text }) => pathIsRelative(text) ? (hasJSFileExtension(text) || hasTSFileExtension(text)) : undefined) || false;
}
function comparePathsByRedirectAndNumberOfDirectorySeparators(a: ModulePath, b: ModulePath) {
@@ -558,18 +598,6 @@ namespace ts.moduleSpecifiers {
}
}
- function getAllowedEndings(preferredEnding: Ending, compilerOptions: CompilerOptions, importMode: SourceFile["impliedNodeFormat"]) {
- if (getEmitModuleResolutionKind(compilerOptions) >= ModuleResolutionKind.Node16 && importMode === ModuleKind.ESNext) {
- return [Ending.JsExtension];
- }
- switch (preferredEnding) {
- case Ending.JsExtension: return [Ending.JsExtension, Ending.Minimal, Ending.Index];
- case Ending.Index: return [Ending.Index, Ending.Minimal, Ending.JsExtension];
- case Ending.Minimal: return [Ending.Minimal, Ending.Index, Ending.JsExtension];
- default: Debug.assertNever(preferredEnding);
- }
- }
-
function tryGetModuleNameFromPaths(relativeToBaseUrl: string, paths: MapLike, allowedEndings: Ending[], host: ModuleSpecifierResolutionHost, compilerOptions: CompilerOptions): string | undefined {
for (const key in paths) {
for (const patternText of paths[key]) {
@@ -613,7 +641,7 @@ namespace ts.moduleSpecifiers {
// sorted among the others for a particular value of `importModuleSpecifierEnding`.
const candidates: { ending: Ending | undefined, value: string }[] = allowedEndings.map(ending => ({
ending,
- value: removeExtensionAndIndexPostFix(relativeToBaseUrl, ending, compilerOptions)
+ value: processEnding(relativeToBaseUrl, ending, compilerOptions)
}));
if (tryGetExtensionFromPath(pattern)) {
candidates.push({ ending: undefined, value: relativeToBaseUrl });
@@ -650,7 +678,7 @@ namespace ts.moduleSpecifiers {
// `Ending.Index` result, which should already be in the list of candidates if `Minimal` was. (Note: the assumption here is
// that every module resolution mode that supports dropping extensions also supports dropping `/index`. Like literally
// everything else in this file, this logic needs to be updated if that's not true in some future module resolution mode.)
- return ending !== Ending.Minimal || value === removeExtensionAndIndexPostFix(relativeToBaseUrl, ending, compilerOptions, host);
+ return ending !== Ending.Minimal || value === processEnding(relativeToBaseUrl, ending, compilerOptions, host);
}
}
@@ -733,13 +761,11 @@ namespace ts.moduleSpecifiers {
const normalizedSourcePath = getPathRelativeToRootDirs(sourceDirectory, rootDirs, getCanonicalFileName);
const relativePath = normalizedSourcePath !== undefined ? ensurePathIsNonModuleName(getRelativePathFromDirectory(normalizedSourcePath, normalizedTargetPath, getCanonicalFileName)) : normalizedTargetPath;
- return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeJs
- ? removeExtensionAndIndexPostFix(relativePath, ending, compilerOptions)
- : removeFileExtension(relativePath);
+ return processEnding(relativePath, ending, compilerOptions);
}
function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCanonicalFileName, sourceDirectory }: Info, importingSourceFile: SourceFile , host: ModuleSpecifierResolutionHost, options: CompilerOptions, userPreferences: UserPreferences, packageNameOnly?: boolean, overrideMode?: ModuleKind.ESNext | ModuleKind.CommonJS): string | undefined {
- if (!host.fileExists || !host.readFile) {
+ if (!host.fileExists || !host.readFile || getEmitModuleResolutionKind(options) === ModuleResolutionKind.Minimal) {
return undefined;
}
const parts: NodeModulePathParts = getNodeModulePathParts(path)!;
@@ -750,6 +776,7 @@ namespace ts.moduleSpecifiers {
// Simplify the full file path to something that can be resolved by Node.
const preferences = getPreferences(host, userPreferences, options, importingSourceFile);
+ const allowedEndings = preferences.getAllowedEndingsInPrefererredOrder();
let moduleSpecifier = path;
let isPackageRootPath = false;
if (!packageNameOnly) {
@@ -776,7 +803,7 @@ namespace ts.moduleSpecifiers {
// try with next level of directory
packageRootIndex = path.indexOf(directorySeparator, packageRootIndex + 1);
if (packageRootIndex === -1) {
- moduleSpecifier = removeExtensionAndIndexPostFix(moduleFileName, preferences.ending, options, host);
+ moduleSpecifier = processEnding(moduleFileName, allowedEndings[0], options, host);
break;
}
}
@@ -832,7 +859,7 @@ namespace ts.moduleSpecifiers {
const fromPaths = tryGetModuleNameFromPaths(
subModuleName,
versionPaths.paths,
- getAllowedEndings(preferences.ending, options, importMode),
+ allowedEndings,
host,
options
);
@@ -889,7 +916,7 @@ namespace ts.moduleSpecifiers {
});
}
- function removeExtensionAndIndexPostFix(fileName: string, ending: Ending, options: CompilerOptions, host?: ModuleSpecifierResolutionHost): string {
+ function processEnding(fileName: string, ending: Ending, options: CompilerOptions, host?: ModuleSpecifierResolutionHost): string {
if (fileExtensionIsOneOf(fileName, [Extension.Json, Extension.Mjs, Extension.Cjs])) return fileName;
const noExtension = removeFileExtension(fileName);
if (fileName === noExtension) return fileName;
@@ -907,6 +934,8 @@ namespace ts.moduleSpecifiers {
return noExtension;
case Ending.JsExtension:
return noExtension + getJSExtensionForFile(fileName, options);
+ case Ending.TsExtension:
+ return fileName;
default:
return Debug.assertNever(ending);
}
diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index 74abd84b43665..174a0fea3383b 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -3657,6 +3657,10 @@ namespace ts {
createOptionValueDiagnostic("importsNotUsedAsValues", Diagnostics.Option_preserveValueImports_can_only_be_used_when_module_is_set_to_es2015_or_later);
}
+ if (options.allowImportingTsExtensions && !(getEmitModuleResolutionKind(options) === ModuleResolutionKind.Minimal && (options.noEmit || options.emitDeclarationOnly))) {
+ createOptionValueDiagnostic("allowImportingTsExtensions", Diagnostics.Option_allowImportingTsExtensions_can_only_be_used_when_moduleResolution_is_set_to_minimal_and_either_noEmit_or_emitDeclarationOnly_is_set);
+ }
+
// If the emit is enabled make sure that every output file is unique and not overwriting any of the input files
if (!options.noEmit && !options.suppressOutputPathCheck) {
const emitHost = getEmitHost();
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index 66e55ab58b381..36beab983c43a 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -6483,6 +6483,8 @@ namespace ts {
// In turn, we offer both a `NodeNext` moving resolution target, and a `Node16` version-anchored resolution target
Node16 = 3,
NodeNext = 99, // Not simply `Node16` so that compiled code linked against TS can use the `Next` value reliably (same as with `ModuleKind`)
+
+ Minimal = 100,
}
export enum ModuleDetectionKind {
@@ -6542,6 +6544,7 @@ namespace ts {
export interface CompilerOptions {
/*@internal*/ all?: boolean;
+ allowImportingTsExtensions?: boolean;
allowJs?: boolean;
/*@internal*/ allowNonTsExtensions?: boolean;
allowSyntheticDefaultImports?: boolean;
@@ -7088,6 +7091,11 @@ namespace ts {
resolvedFileName: string;
/** True if `resolvedFileName` comes from `node_modules`. */
isExternalLibraryImport?: boolean;
+ /**
+ * True if the original module reference used a .ts extension to refer directly to a .ts file,
+ * which should produce an error during checking if emit is enabled.
+ */
+ resolvedUsingTsExtension: boolean;
}
/**
diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts
index 72ceb827adf95..c1537c5b8b089 100644
--- a/src/harness/fourslashImpl.ts
+++ b/src/harness/fourslashImpl.ts
@@ -798,16 +798,20 @@ namespace FourSlash {
});
}
- private renderMarkers(markers: { text: string, fileName: string, position: number }[]) {
+ private renderMarkers(markers: { text: string, fileName: string, position: number }[], useTerminalBoldSequence = true) {
const filesToDisplay = ts.deduplicate(markers.map(m => m.fileName), ts.equateValues);
return filesToDisplay.map(fileName => {
const markersToRender = markers.filter(m => m.fileName === fileName).sort((a, b) => b.position - a.position);
let fileContent = this.tryGetFileContent(fileName) || "";
for (const marker of markersToRender) {
- fileContent = fileContent.slice(0, marker.position) + `\x1b[1;4m/*${marker.text}*/\x1b[0;31m` + fileContent.slice(marker.position);
+ fileContent = fileContent.slice(0, marker.position) + bold(`/*${marker.text}*/`) + fileContent.slice(marker.position);
}
return `// @Filename: ${fileName}\n${fileContent}`;
}).join("\n\n");
+
+ function bold(text: string) {
+ return useTerminalBoldSequence ? `\x1b[1;4m${text}\x1b[0;31m` : text;
+ }
}
private verifyDefinitionTextSpan(defs: ts.DefinitionInfoAndBoundSpan, startMarkerName: string) {
@@ -3127,6 +3131,48 @@ namespace FourSlash {
assert.deepEqual(actualModuleSpecifiers, moduleSpecifiers);
}
+ public baselineAutoImports(markerName: string, preferences?: ts.UserPreferences) {
+ const marker = this.getMarkerByName(markerName);
+ const baselineFile = this.getBaselineFileNameForContainingTestFile(`.baseline.md`);
+ const completionPreferences = {
+ includeCompletionsForModuleExports: true,
+ includeCompletionsWithInsertText: true,
+ allowIncompleteCompletions: true,
+ includeCompletionsWithSnippetText: true,
+ ...preferences
+ };
+
+ const ext = ts.getAnyExtensionFromPath(this.activeFile.fileName).slice(1);
+ const lang = ["mts", "cts"].includes(ext) ? "ts" : ext;
+ let baselineText = codeFence(this.renderMarkers([{ text: "|", fileName: marker.fileName, position: marker.position }], /*useTerminalBoldSequence*/ false), lang) + "\n\n";
+ this.goToMarker(marker);
+
+ const completions = this.getCompletionListAtCaret(completionPreferences)!;
+
+ const autoImportCompletions = completions.entries.filter(c => c.hasAction && c.source && c.sortText === ts.Completions.SortText.AutoImportSuggestions);
+ if (autoImportCompletions.length) {
+ baselineText += `## From completions\n\n${autoImportCompletions.map(c => `- \`${c.name}\` from \`"${c.source}"\``).join("\n")}\n\n`;
+ autoImportCompletions.forEach(c => {
+ const details = this.getCompletionEntryDetails(c.name, c.source, c.data, completionPreferences);
+ assert(details?.codeActions, `Entry '${c.name}' from "${c.source}" returned no code actions from completion details request`);
+ assert(details.codeActions.length === 1, `Entry '${c.name}' from "${c.source}" returned more than one code action`);
+ assert(details.codeActions[0].changes.length === 1, `Entry '${c.name}' from "${c.source}" returned a code action changing more than one file`);
+ assert(details.codeActions[0].changes[0].fileName === this.activeFile.fileName, `Entry '${c.name}' from "${c.source}" returned a code action changing a different file`);
+ const changes = details.codeActions[0].changes[0].textChanges;
+ const completionChange: ts.TextChange = { newText: c.insertText || c.name, span: c.replacementSpan || completions.optionalReplacementSpan || { start: marker.position, length: 0 } };
+ const sortedChanges = [...changes, completionChange].sort((a, b) => a.span.start - b.span.start);
+ let newFileContent = this.activeFile.content;
+ for (let i = sortedChanges.length - 1; i >= 0; i--) {
+ newFileContent = newFileContent.substring(0, sortedChanges[i].span.start) + sortedChanges[i].newText + newFileContent.substring(sortedChanges[i].span.start + sortedChanges[i].span.length);
+ }
+ baselineText += codeFence(newFileContent, lang) + "\n\n";
+ });
+ }
+
+ // TODO: do codefixes too
+ Harness.Baseline.runBaseline(baselineFile, baselineText);
+ }
+
public verifyDocCommentTemplate(expected: ts.TextInsertion | undefined, options?: ts.DocCommentTemplateOptions) {
const name = "verifyDocCommentTemplate";
const actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition, options || { generateReturnInDocTemplate: true })!;
@@ -4598,10 +4644,10 @@ namespace FourSlash {
}
return ranges;
- }
+ }
- // Adds an _ when the source string and the target string have a whitespace difference
- function highlightDifferenceBetweenStrings(source: string, target: string) {
+ // Adds an _ when the source string and the target string have a whitespace difference
+ function highlightDifferenceBetweenStrings(source: string, target: string) {
const ranges = rangesOfDiffBetweenTwoStrings(source, target);
let emTarget = target;
ranges.forEach((range, index) => {
@@ -4613,9 +4659,13 @@ namespace FourSlash {
range.start + 1 + additionalOffset,
range.start + range.length + 1 + additionalOffset
);
- const after = emTarget.slice(range.start + range.length + 1 + additionalOffset, emTarget.length);
+ const after = emTarget.slice(range.start + range.length + 1 + additionalOffset, emTarget.length);
emTarget = before + lhs + between + rhs + after;
});
return emTarget;
- }
+ }
+
+ function codeFence(code: string, lang?: string) {
+ return `\`\`\`${lang || ""}\n${code}\n\`\`\``;
+ }
}
diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts
index 52acb7d347eec..41377bd360296 100644
--- a/src/harness/fourslashInterfaceImpl.ts
+++ b/src/harness/fourslashInterfaceImpl.ts
@@ -486,6 +486,10 @@ namespace FourSlashInterface {
this.state.verifyImportFixModuleSpecifiers(marker, moduleSpecifiers, preferences);
}
+ public baselineAutoImports(marker: string, preferences?: ts.UserPreferences) {
+ this.state.baselineAutoImports(marker, preferences);
+ }
+
public navigationBar(json: any, options?: { checkSpans?: boolean }) {
this.state.verifyNavigationBar(json, options);
}
diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts
index 496a5d888a194..11e9d13f8bdf0 100644
--- a/src/services/codefixes/importFixes.ts
+++ b/src/services/codefixes/importFixes.ts
@@ -662,7 +662,8 @@ namespace ts.codefix {
const compilerOptions = program.getCompilerOptions();
const moduleSpecifierResolutionHost = createModuleSpecifierResolutionHost(program, host);
const getChecker = createGetChecker(program, host);
- const rejectNodeModulesRelativePaths = moduleResolutionUsesNodeModules(getEmitModuleResolutionKind(compilerOptions));
+ const moduleResolution = getEmitModuleResolutionKind(compilerOptions);
+ const rejectNodeModulesRelativePaths = moduleResolutionUsesNodeModules(moduleResolution) || moduleResolution === ModuleResolutionKind.Minimal;
const getModuleSpecifiers = fromCacheOnly
? (moduleSymbol: Symbol) => ({ moduleSpecifiers: moduleSpecifiers.tryGetModuleSpecifiersFromCache(moduleSymbol, sourceFile, moduleSpecifierResolutionHost, preferences), computedWithoutCache: false })
: (moduleSymbol: Symbol, checker: TypeChecker) => moduleSpecifiers.getModuleSpecifiersWithCacheInfo(moduleSymbol, checker, compilerOptions, sourceFile, moduleSpecifierResolutionHost, preferences);
diff --git a/src/services/completions.ts b/src/services/completions.ts
index bff90e2d3e7c5..d23fab3aa0957 100644
--- a/src/services/completions.ts
+++ b/src/services/completions.ts
@@ -169,7 +169,7 @@ namespace ts.Completions {
const enum GlobalsSearch { Continue, Success, Fail }
- interface ModuleSpecifierResolutioContext {
+ interface ModuleSpecifierResolutionContext {
tryResolve: (exportInfo: readonly SymbolExportInfo[], symbolName: string, isFromAmbientModule: boolean) => ModuleSpecifierResolutionResult;
resolvedAny: () => boolean;
skippedAny: () => boolean;
@@ -190,15 +190,20 @@ namespace ts.Completions {
preferences: UserPreferences,
isForImportStatementCompletion: boolean,
isValidTypeOnlyUseSite: boolean,
- cb: (context: ModuleSpecifierResolutioContext) => TReturn,
+ cb: (context: ModuleSpecifierResolutionContext) => TReturn,
): TReturn {
const start = timestamp();
+ const moduleResolution = getEmitModuleResolutionKind(program.getCompilerOptions());
// Under `--moduleResolution nodenext`, we have to resolve module specifiers up front, because
// package.json exports can mean we *can't* resolve a module specifier (that doesn't include a
// relative path into node_modules), and we want to filter those completions out entirely.
+ // Under `--moduleResolution minimal`, we want to reject relative module specifiers into
+ // node_modules, so need to exhaust any other possibilities for how those can be referenced.
// Import statement completions always need specifier resolution because the module specifier is
// part of their `insertText`, not the `codeActions` creating edits away from the cursor.
- const needsFullResolution = isForImportStatementCompletion || moduleResolutionRespectsExports(getEmitModuleResolutionKind(program.getCompilerOptions()));
+ const needsFullResolution = isForImportStatementCompletion
+ || moduleResolutionRespectsExports(moduleResolution)
+ || moduleResolution === ModuleResolutionKind.Minimal;
let skippedAny = false;
let ambientCount = 0;
let resolvedCount = 0;
diff --git a/src/services/shims.ts b/src/services/shims.ts
index af0f424a736ff..d3935a9082f1b 100644
--- a/src/services/shims.ts
+++ b/src/services/shims.ts
@@ -362,7 +362,7 @@ namespace ts {
const resolutionsInFile = JSON.parse(this.shimHost.getModuleResolutionsForFile!(containingFile)) as MapLike; // TODO: GH#18217
return map(moduleNames, name => {
const result = getProperty(resolutionsInFile, name);
- return result ? { resolvedFileName: result, extension: extensionFromPath(result), isExternalLibraryImport: false } : undefined;
+ return result ? { resolvedFileName: result, extension: extensionFromPath(result), isExternalLibraryImport: false, resolvedUsingTsExtension: false } : undefined;
});
};
}
diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts
index 33b508017683a..239089c47991d 100644
--- a/src/services/stringCompletions.ts
+++ b/src/services/stringCompletions.ts
@@ -377,8 +377,16 @@ namespace ts.Completions.StringCompletions {
: getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, mode, compilerOptions, host, getIncludeExtensionOption(), typeChecker);
function getIncludeExtensionOption() {
+ const moduleResolution = getEmitModuleResolutionKind(compilerOptions);
+ if (moduleResolution === ModuleResolutionKind.Minimal) {
+ return shouldAllowImportingTsExtension(compilerOptions)
+ ? IncludeExtensionsOption.Include
+ : IncludeExtensionsOption.ModuleSpecifierCompletion;
+ }
const mode = isStringLiteralLike(node) ? getModeForUsageLocation(sourceFile, node) : undefined;
- return preferences.importModuleSpecifierEnding === "js" || mode === ModuleKind.ESNext ? IncludeExtensionsOption.ModuleSpecifierCompletion : IncludeExtensionsOption.Exclude;
+ return preferences.importModuleSpecifierEnding === "js" || mode === ModuleKind.ESNext
+ ? IncludeExtensionsOption.ModuleSpecifierCompletion
+ : IncludeExtensionsOption.Exclude;
}
}
@@ -396,24 +404,14 @@ namespace ts.Completions.StringCompletions {
compilerOptions.rootDirs, literalValue, scriptDirectory, extensionOptions, compilerOptions, host, scriptPath);
}
else {
- return arrayFrom(getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, extensionOptions, host, scriptPath).values());
+ return arrayFrom(getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, extensionOptions, host, /*moduleSpecifierIsRelative*/ false, scriptPath).values());
}
}
- function isEmitResolutionKindUsingNodeModules(compilerOptions: CompilerOptions): boolean {
- return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeJs ||
- getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node16 ||
- getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext;
- }
-
- function isEmitModuleResolutionRespectingExportMaps(compilerOptions: CompilerOptions) {
- return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node16 ||
- getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext;
- }
-
function getSupportedExtensionsForModuleResolution(compilerOptions: CompilerOptions): readonly Extension[][] {
const extensions = getSupportedExtensions(compilerOptions);
- return isEmitResolutionKindUsingNodeModules(compilerOptions) ?
+ const moduleResolution = getEmitModuleResolutionKind(compilerOptions);
+ return moduleResolutionUsesNodeModules(moduleResolution) ?
getSupportedExtensionsWithJsonIfResolveJsonModule(compilerOptions, extensions) :
extensions;
}
@@ -441,7 +439,7 @@ namespace ts.Completions.StringCompletions {
const basePath = compilerOptions.project || host.getCurrentDirectory();
const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames());
const baseDirectories = getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptDirectory, ignoreCase);
- return flatMap(baseDirectories, baseDirectory => arrayFrom(getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensionOptions, host, exclude).values()));
+ return flatMap(baseDirectories, baseDirectory => arrayFrom(getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensionOptions, host, /*moduleSpecifierIsRelative*/ true, exclude).values()));
}
const enum IncludeExtensionsOption {
@@ -454,9 +452,10 @@ namespace ts.Completions.StringCompletions {
*/
function getCompletionEntriesForDirectoryFragment(
fragment: string,
- scriptPath: string,
+ scriptDirectory: string,
extensionOptions: ExtensionOptions,
host: LanguageServiceHost,
+ moduleSpecifierIsRelative: boolean,
exclude?: string,
result = createNameAndKindSet()
): NameAndKindSet {
@@ -480,23 +479,25 @@ namespace ts.Completions.StringCompletions {
fragment = ensureTrailingDirectorySeparator(fragment);
- const absolutePath = resolvePath(scriptPath, fragment);
+ const absolutePath = resolvePath(scriptDirectory, fragment);
const baseDirectory = hasTrailingDirectorySeparator(absolutePath) ? absolutePath : getDirectoryPath(absolutePath);
- // check for a version redirect
- const packageJsonPath = findPackageJson(baseDirectory, host);
- if (packageJsonPath) {
- const packageJson = readJson(packageJsonPath, host as { readFile: (filename: string) => string | undefined });
- const typesVersions = (packageJson as any).typesVersions;
- if (typeof typesVersions === "object") {
- const versionPaths = getPackageJsonTypesVersionsPaths(typesVersions)?.paths;
- if (versionPaths) {
- const packageDirectory = getDirectoryPath(packageJsonPath);
- const pathInPackage = absolutePath.slice(ensureTrailingDirectorySeparator(packageDirectory).length);
- if (addCompletionEntriesFromPaths(result, pathInPackage, packageDirectory, extensionOptions, host, versionPaths)) {
- // A true result means one of the `versionPaths` was matched, which will block relative resolution
- // to files and folders from here. All reachable paths given the pattern match are already added.
- return result;
+ if (!moduleSpecifierIsRelative) {
+ // check for a version redirect
+ const packageJsonPath = findPackageJson(baseDirectory, host);
+ if (packageJsonPath) {
+ const packageJson = readJson(packageJsonPath, host as { readFile: (filename: string) => string | undefined });
+ const typesVersions = (packageJson as any).typesVersions;
+ if (typeof typesVersions === "object") {
+ const versionPaths = getPackageJsonTypesVersionsPaths(typesVersions)?.paths;
+ if (versionPaths) {
+ const packageDirectory = getDirectoryPath(packageJsonPath);
+ const pathInPackage = absolutePath.slice(ensureTrailingDirectorySeparator(packageDirectory).length);
+ if (addCompletionEntriesFromPaths(result, pathInPackage, packageDirectory, extensionOptions, host, versionPaths)) {
+ // A true result means one of the `versionPaths` was matched, which will block relative resolution
+ // to files and folders from here. All reachable paths given the pattern match are already added.
+ return result;
+ }
}
}
}
@@ -511,7 +512,7 @@ namespace ts.Completions.StringCompletions {
if (files) {
for (let filePath of files) {
filePath = normalizePath(filePath);
- if (exclude && comparePaths(filePath, exclude, scriptPath, ignoreCase) === Comparison.EqualTo) {
+ if (exclude && comparePaths(filePath, exclude, scriptDirectory, ignoreCase) === Comparison.EqualTo) {
continue;
}
@@ -524,9 +525,10 @@ namespace ts.Completions.StringCompletions {
const directories = tryGetDirectories(host, baseDirectory);
if (directories) {
+ const moduleResolution = getEmitModuleResolutionKind(host.getCompilationSettings());
for (const directory of directories) {
const directoryName = getBaseFileName(normalizePath(directory));
- if (directoryName !== "@types") {
+ if (directoryName !== "@types" && !(directoryName === "node_modules" && moduleResolution === ModuleResolutionKind.Minimal)) {
result.add(directoryResult(directoryName));
}
}
@@ -638,11 +640,12 @@ namespace ts.Completions.StringCompletions {
const { baseUrl, paths } = compilerOptions;
const result = createNameAndKindSet();
+ const moduleResolution = getEmitModuleResolutionKind(compilerOptions);
const extensionOptions = getExtensionOptions(compilerOptions, includeExtensionsOption);
if (baseUrl) {
const projectDir = compilerOptions.project || host.getCurrentDirectory();
const absolute = normalizePath(combinePaths(projectDir, baseUrl));
- getCompletionEntriesForDirectoryFragment(fragment, absolute, extensionOptions, host, /*exclude*/ undefined, result);
+ getCompletionEntriesForDirectoryFragment(fragment, absolute, extensionOptions, host, /*moduleSpecifierIsRelative*/ false, /*exclude*/ undefined, result);
if (paths) {
addCompletionEntriesFromPaths(result, fragment, absolute, extensionOptions, host, paths);
}
@@ -653,9 +656,11 @@ namespace ts.Completions.StringCompletions {
result.add(nameAndKind(ambientName, ScriptElementKind.externalModuleName, /*extension*/ undefined));
}
- getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, fragmentDirectory, extensionOptions, result);
+ if (moduleResolution !== ModuleResolutionKind.Minimal) {
+ getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, fragmentDirectory, extensionOptions, result);
+ }
- if (isEmitResolutionKindUsingNodeModules(compilerOptions)) {
+ if (moduleResolutionUsesNodeModules(moduleResolution)) {
// If looking for a global package name, don't just include everything in `node_modules` because that includes dependencies' own dependencies.
// (But do if we didn't find anything, e.g. 'package.json' missing.)
let foundGlobal = false;
@@ -672,10 +677,10 @@ namespace ts.Completions.StringCompletions {
let ancestorLookup: (directory: string) => void | undefined = ancestor => {
const nodeModules = combinePaths(ancestor, "node_modules");
if (tryDirectoryExists(host, nodeModules)) {
- getCompletionEntriesForDirectoryFragment(fragment, nodeModules, extensionOptions, host, /*exclude*/ undefined, result);
+ getCompletionEntriesForDirectoryFragment(fragment, nodeModules, extensionOptions, host, /*moduleSpecifierIsRelative*/ false, /*exclude*/ undefined, result);
}
};
- if (fragmentDirectory && isEmitModuleResolutionRespectingExportMaps(compilerOptions)) {
+ if (fragmentDirectory && moduleResolutionRespectsExports(moduleResolution)) {
const nodeModulesDirectoryLookup = ancestorLookup;
ancestorLookup = ancestor => {
const components = getPathComponents(fragment);
@@ -876,7 +881,7 @@ namespace ts.Completions.StringCompletions {
const [, prefix, kind, toComplete] = match;
const scriptPath = getDirectoryPath(sourceFile.path);
- const names = kind === "path" ? getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getExtensionOptions(compilerOptions, IncludeExtensionsOption.Include), host, sourceFile.path)
+ const names = kind === "path" ? getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getExtensionOptions(compilerOptions, IncludeExtensionsOption.Include), host, /*moduleSpecifierIsRelative*/ true, sourceFile.path)
: kind === "types" ? getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, getFragmentDirectory(toComplete), getExtensionOptions(compilerOptions))
: Debug.fail();
return addReplacementSpans(toComplete, range.pos + prefix.length, arrayFrom(names.values()));
@@ -917,7 +922,7 @@ namespace ts.Completions.StringCompletions {
const baseDirectory = combinePaths(directory, typeDirectoryName);
const remainingFragment = tryRemoveDirectoryPrefix(fragmentDirectory, packageName, hostGetCanonicalFileName(host));
if (remainingFragment !== undefined) {
- getCompletionEntriesForDirectoryFragment(remainingFragment, baseDirectory, extensionOptions, host, /*exclude*/ undefined, result);
+ getCompletionEntriesForDirectoryFragment(remainingFragment, baseDirectory, extensionOptions, host, /*moduleSpecifierIsRelative*/ false, /*exclude*/ undefined, result);
}
}
}
diff --git a/src/services/utilities.ts b/src/services/utilities.ts
index 4d24e57d051ee..b021cd350d563 100644
--- a/src/services/utilities.ts
+++ b/src/services/utilities.ts
@@ -1909,8 +1909,9 @@ namespace ts {
export function programContainsEsModules(program: Program): boolean {
return program.getSourceFiles().some(s => !s.isDeclarationFile && !program.isSourceFileFromExternalLibrary(s) && !!s.externalModuleIndicator);
}
+ // TODO: this function is, at best, poorly named. Use sites are pretty suspicious.
export function compilerOptionsIndicateEsModules(compilerOptions: CompilerOptions): boolean {
- return !!compilerOptions.module || getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2015 || !!compilerOptions.noEmit;
+ return !!compilerOptions.module || getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2015 || !!compilerOptions.noEmit || getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Minimal;
}
export function createModuleSpecifierResolutionHost(program: Program, host: LanguageServiceHost): ModuleSpecifierResolutionHost {
diff --git a/src/testRunner/compilerRunner.ts b/src/testRunner/compilerRunner.ts
index ced86a57713c4..22ae1b9c6e469 100644
--- a/src/testRunner/compilerRunner.ts
+++ b/src/testRunner/compilerRunner.ts
@@ -119,8 +119,10 @@ namespace Harness {
"module",
"moduleResolution",
"moduleDetection",
+ "allowImportingTsExtensions",
"target",
"jsx",
+ "noEmit",
"removeComments",
"importHelpers",
"importHelpers",
diff --git a/src/testRunner/unittests/config/commandLineParsing.ts b/src/testRunner/unittests/config/commandLineParsing.ts
index e2b48977106b6..07ecbb7393328 100644
--- a/src/testRunner/unittests/config/commandLineParsing.ts
+++ b/src/testRunner/unittests/config/commandLineParsing.ts
@@ -237,7 +237,7 @@ namespace ts {
start: undefined,
length: undefined,
}, {
- messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic', 'node16', 'nodenext'.",
+ messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic', 'node16', 'nodenext', 'minimal'.",
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
diff --git a/src/testRunner/unittests/moduleResolution.ts b/src/testRunner/unittests/moduleResolution.ts
index 1f85f97827c16..abf0c48773385 100644
--- a/src/testRunner/unittests/moduleResolution.ts
+++ b/src/testRunner/unittests/moduleResolution.ts
@@ -24,8 +24,8 @@ namespace ts {
assert.deepEqual(actual.failedLookupLocations, expectedFailedLookupLocations, `Failed lookup locations should match - expected has ${expectedFailedLookupLocations.length}, actual has ${actual.failedLookupLocations.length}`);
}
- export function createResolvedModule(resolvedFileName: string, isExternalLibraryImport = false): ResolvedModuleFull {
- return { resolvedFileName, extension: extensionFromPath(resolvedFileName), isExternalLibraryImport };
+ export function createResolvedModule(resolvedFileName: string, isExternalLibraryImport = false, resolvedUsingTsExtension = false): ResolvedModuleFull {
+ return { resolvedFileName, extension: extensionFromPath(resolvedFileName), isExternalLibraryImport, resolvedUsingTsExtension };
}
interface File {
@@ -214,6 +214,7 @@ namespace ts {
resolvedFileName: "/sub/node_modules/a/index.ts",
isExternalLibraryImport: true,
extension: Extension.Ts,
+ resolvedUsingTsExtension: false,
},
failedLookupLocations: [],
affectingLocations: [],
@@ -229,6 +230,7 @@ namespace ts {
resolvedFileName: "/sub/directory/node_modules/b/index.ts",
isExternalLibraryImport: true,
extension: Extension.Ts,
+ resolvedUsingTsExtension: false,
},
failedLookupLocations: [],
affectingLocations: [],
@@ -246,6 +248,7 @@ namespace ts {
resolvedFileName: "/bar/node_modules/c/index.ts",
isExternalLibraryImport: true,
extension: Extension.Ts,
+ resolvedUsingTsExtension: false,
},
failedLookupLocations: [],
affectingLocations: [],
@@ -262,6 +265,7 @@ namespace ts {
resolvedFileName: "/foo/index.ts",
isExternalLibraryImport: true,
extension: Extension.Ts,
+ resolvedUsingTsExtension: false,
},
failedLookupLocations: [],
affectingLocations: [],
@@ -277,6 +281,7 @@ namespace ts {
resolvedFileName: "d:/bar/node_modules/e/index.ts",
isExternalLibraryImport: true,
extension: Extension.Ts,
+ resolvedUsingTsExtension: false,
},
failedLookupLocations: [],
affectingLocations: [],
diff --git a/src/testRunner/unittests/tscWatch/watchApi.ts b/src/testRunner/unittests/tscWatch/watchApi.ts
index 8182e276d9617..02d9f1b0a1dca 100644
--- a/src/testRunner/unittests/tscWatch/watchApi.ts
+++ b/src/testRunner/unittests/tscWatch/watchApi.ts
@@ -34,6 +34,7 @@ namespace ts.tscWatch {
resolvedFileName: resolvedModule.resolvedFileName,
isExternalLibraryImport: resolvedModule.isExternalLibraryImport,
originalFileName: resolvedModule.originalPath,
+ resolvedUsingTsExtension: false,
};
});
const watch = createWatchProgram(host);
diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts
index 575116ceed587..a976eb443e2b1 100644
--- a/tests/baselines/reference/api/tsserverlibrary.d.ts
+++ b/tests/baselines/reference/api/tsserverlibrary.d.ts
@@ -2941,7 +2941,8 @@ declare namespace ts {
Classic = 1,
NodeJs = 2,
Node16 = 3,
- NodeNext = 99
+ NodeNext = 99,
+ Minimal = 100
}
export enum ModuleDetectionKind {
/**
@@ -2992,6 +2993,7 @@ declare namespace ts {
}
export type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | ProjectReference[] | null | undefined;
export interface CompilerOptions {
+ allowImportingTsExtensions?: boolean;
allowJs?: boolean;
allowSyntheticDefaultImports?: boolean;
allowUmdGlobalAccess?: boolean;
@@ -3236,6 +3238,11 @@ declare namespace ts {
resolvedFileName: string;
/** True if `resolvedFileName` comes from `node_modules`. */
isExternalLibraryImport?: boolean;
+ /**
+ * True if the original module reference used a .ts extension to refer directly to a .ts file,
+ * which should produce an error during checking if emit is enabled.
+ */
+ resolvedUsingTsExtension: boolean;
}
/**
* ResolvedModule with an explicitly provided `extension` property.
@@ -5053,6 +5060,9 @@ declare namespace ts {
export function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, resolutionMode?: ModuleKind.CommonJS | ModuleKind.ESNext): ResolvedModuleWithFailedLookupLocations;
export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations;
export function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations;
+ export function minimalModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations;
+ export function shouldResolveTsExtension(compilerOptions: CompilerOptions): boolean;
+ export function shouldAllowImportingTsExtension(compilerOptions: CompilerOptions, fromFileName?: string): boolean | "" | undefined;
export {};
}
declare namespace ts {
diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts
index 0e6b2559af02e..94e3cced1c674 100644
--- a/tests/baselines/reference/api/typescript.d.ts
+++ b/tests/baselines/reference/api/typescript.d.ts
@@ -2941,7 +2941,8 @@ declare namespace ts {
Classic = 1,
NodeJs = 2,
Node16 = 3,
- NodeNext = 99
+ NodeNext = 99,
+ Minimal = 100
}
export enum ModuleDetectionKind {
/**
@@ -2992,6 +2993,7 @@ declare namespace ts {
}
export type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | ProjectReference[] | null | undefined;
export interface CompilerOptions {
+ allowImportingTsExtensions?: boolean;
allowJs?: boolean;
allowSyntheticDefaultImports?: boolean;
allowUmdGlobalAccess?: boolean;
@@ -3236,6 +3238,11 @@ declare namespace ts {
resolvedFileName: string;
/** True if `resolvedFileName` comes from `node_modules`. */
isExternalLibraryImport?: boolean;
+ /**
+ * True if the original module reference used a .ts extension to refer directly to a .ts file,
+ * which should produce an error during checking if emit is enabled.
+ */
+ resolvedUsingTsExtension: boolean;
}
/**
* ResolvedModule with an explicitly provided `extension` property.
@@ -5053,6 +5060,9 @@ declare namespace ts {
export function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, resolutionMode?: ModuleKind.CommonJS | ModuleKind.ESNext): ResolvedModuleWithFailedLookupLocations;
export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations;
export function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations;
+ export function minimalModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations;
+ export function shouldResolveTsExtension(compilerOptions: CompilerOptions): boolean;
+ export function shouldAllowImportingTsExtension(compilerOptions: CompilerOptions, fromFileName?: string): boolean | "" | undefined;
export {};
}
declare namespace ts {
diff --git a/tests/baselines/reference/autoImportsMinimal1.baseline.md b/tests/baselines/reference/autoImportsMinimal1.baseline.md
new file mode 100644
index 0000000000000..c0a6fb0eeaaaa
--- /dev/null
+++ b/tests/baselines/reference/autoImportsMinimal1.baseline.md
@@ -0,0 +1,22 @@
+```ts
+// @Filename: /main.ts
+/*|*/
+```
+
+## From completions
+
+- `Component` from `"./Component.js"`
+- `fromLocal` from `"./local.js"`
+
+```ts
+import { Component } from "./Component.js";
+
+Component
+```
+
+```ts
+import { fromLocal } from "./local.js";
+
+fromLocal
+```
+
diff --git a/tests/baselines/reference/autoImportsMinimal2.baseline.md b/tests/baselines/reference/autoImportsMinimal2.baseline.md
new file mode 100644
index 0000000000000..35b129182eab9
--- /dev/null
+++ b/tests/baselines/reference/autoImportsMinimal2.baseline.md
@@ -0,0 +1,22 @@
+```ts
+// @Filename: /main.ts
+/*|*/
+```
+
+## From completions
+
+- `Component` from `"./Component.tsx"`
+- `fromLocal` from `"./local.ts"`
+
+```ts
+import { Component } from "./Component.tsx";
+
+Component
+```
+
+```ts
+import { fromLocal } from "./local.ts";
+
+fromLocal
+```
+
diff --git a/tests/baselines/reference/minimal_nodeModules.errors.txt b/tests/baselines/reference/minimal_nodeModules.errors.txt
new file mode 100644
index 0000000000000..91a4356bf0505
--- /dev/null
+++ b/tests/baselines/reference/minimal_nodeModules.errors.txt
@@ -0,0 +1,26 @@
+/main.ts(1,16): error TS2307: Cannot find module 'foo' or its corresponding type declarations.
+/main.ts(2,16): error TS2847: Relative imports into 'node_modules' are not allowed.
+/main.ts(3,21): error TS2847: Relative imports into 'node_modules' are not allowed.
+
+
+==== /node_modules/foo/index.d.ts (0 errors) ====
+ import {} from "./other.js";
+ export {};
+
+==== /node_modules/foo/other.d.ts (0 errors) ====
+ export {};
+
+==== /node_modules/@types/foo/index.d.ts (0 errors) ====
+ export {};
+
+==== /main.ts (3 errors) ====
+ import {} from "foo";
+ ~~~~~
+!!! error TS2307: Cannot find module 'foo' or its corresponding type declarations.
+ import {} from "./node_modules/foo/index.js";
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+!!! error TS2847: Relative imports into 'node_modules' are not allowed.
+ import type {} from "./node_modules/@types/foo/index.d.ts";
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+!!! error TS2847: Relative imports into 'node_modules' are not allowed.
+
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_nodeModules.js b/tests/baselines/reference/minimal_nodeModules.js
new file mode 100644
index 0000000000000..25b341dfcd7e8
--- /dev/null
+++ b/tests/baselines/reference/minimal_nodeModules.js
@@ -0,0 +1,21 @@
+//// [tests/cases/conformance/moduleResolution/minimal_nodeModules.ts] ////
+
+//// [index.d.ts]
+import {} from "./other.js";
+export {};
+
+//// [other.d.ts]
+export {};
+
+//// [index.d.ts]
+export {};
+
+//// [main.ts]
+import {} from "foo";
+import {} from "./node_modules/foo/index.js";
+import type {} from "./node_modules/@types/foo/index.d.ts";
+
+
+//// [main.js]
+"use strict";
+exports.__esModule = true;
diff --git a/tests/baselines/reference/minimal_nodeModules.symbols b/tests/baselines/reference/minimal_nodeModules.symbols
new file mode 100644
index 0000000000000..584f016b4b220
--- /dev/null
+++ b/tests/baselines/reference/minimal_nodeModules.symbols
@@ -0,0 +1,16 @@
+=== /node_modules/foo/index.d.ts ===
+import {} from "./other.js";
+No type information for this code.export {};
+No type information for this code.
+No type information for this code.=== /node_modules/foo/other.d.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /node_modules/@types/foo/index.d.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /main.ts ===
+import {} from "foo";
+No type information for this code.import {} from "./node_modules/foo/index.js";
+No type information for this code.import type {} from "./node_modules/@types/foo/index.d.ts";
+No type information for this code.
+No type information for this code.
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_nodeModules.types b/tests/baselines/reference/minimal_nodeModules.types
new file mode 100644
index 0000000000000..584f016b4b220
--- /dev/null
+++ b/tests/baselines/reference/minimal_nodeModules.types
@@ -0,0 +1,16 @@
+=== /node_modules/foo/index.d.ts ===
+import {} from "./other.js";
+No type information for this code.export {};
+No type information for this code.
+No type information for this code.=== /node_modules/foo/other.d.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /node_modules/@types/foo/index.d.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /main.ts ===
+import {} from "foo";
+No type information for this code.import {} from "./node_modules/foo/index.js";
+No type information for this code.import type {} from "./node_modules/@types/foo/index.d.ts";
+No type information for this code.
+No type information for this code.
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_nodeModules_declarationEmit.errors.txt b/tests/baselines/reference/minimal_nodeModules_declarationEmit.errors.txt
new file mode 100644
index 0000000000000..d0ce84ea82c5c
--- /dev/null
+++ b/tests/baselines/reference/minimal_nodeModules_declarationEmit.errors.txt
@@ -0,0 +1,17 @@
+/main.ts(1,14): error TS2742: The inferred type of 'boom' cannot be named without a reference to './node_modules/foo/module.js'. This is likely not portable. A type annotation is necessary.
+
+
+==== /node_modules/foo/module.d.ts (0 errors) ====
+ export declare class SomeExportedClass {
+ private foo: any;
+ }
+
+ declare global {
+ function returnsPrivateClassOhNo(): SomeExportedClass;
+ }
+
+==== /main.ts (1 errors) ====
+ export const boom = returnsPrivateClassOhNo();
+ ~~~~
+!!! error TS2742: The inferred type of 'boom' cannot be named without a reference to './node_modules/foo/module.js'. This is likely not portable. A type annotation is necessary.
+
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_nodeModules_declarationEmit.js b/tests/baselines/reference/minimal_nodeModules_declarationEmit.js
new file mode 100644
index 0000000000000..b31f1936f6f13
--- /dev/null
+++ b/tests/baselines/reference/minimal_nodeModules_declarationEmit.js
@@ -0,0 +1,20 @@
+//// [tests/cases/conformance/moduleResolution/minimal_nodeModules_declarationEmit.ts] ////
+
+//// [module.d.ts]
+export declare class SomeExportedClass {
+ private foo: any;
+}
+
+declare global {
+ function returnsPrivateClassOhNo(): SomeExportedClass;
+}
+
+//// [main.ts]
+export const boom = returnsPrivateClassOhNo();
+
+
+//// [main.js]
+"use strict";
+exports.__esModule = true;
+exports.boom = void 0;
+exports.boom = returnsPrivateClassOhNo();
diff --git a/tests/baselines/reference/minimal_nodeModules_declarationEmit.symbols b/tests/baselines/reference/minimal_nodeModules_declarationEmit.symbols
new file mode 100644
index 0000000000000..1930da5f26c77
--- /dev/null
+++ b/tests/baselines/reference/minimal_nodeModules_declarationEmit.symbols
@@ -0,0 +1,21 @@
+=== /node_modules/foo/module.d.ts ===
+export declare class SomeExportedClass {
+>SomeExportedClass : Symbol(SomeExportedClass, Decl(module.d.ts, 0, 0))
+
+ private foo: any;
+>foo : Symbol(SomeExportedClass.foo, Decl(module.d.ts, 0, 40))
+}
+
+declare global {
+>global : Symbol(global, Decl(module.d.ts, 2, 1))
+
+ function returnsPrivateClassOhNo(): SomeExportedClass;
+>returnsPrivateClassOhNo : Symbol(returnsPrivateClassOhNo, Decl(module.d.ts, 4, 16))
+>SomeExportedClass : Symbol(SomeExportedClass, Decl(module.d.ts, 0, 0))
+}
+
+=== /main.ts ===
+export const boom = returnsPrivateClassOhNo();
+>boom : Symbol(boom, Decl(main.ts, 0, 12))
+>returnsPrivateClassOhNo : Symbol(returnsPrivateClassOhNo, Decl(module.d.ts, 4, 16))
+
diff --git a/tests/baselines/reference/minimal_nodeModules_declarationEmit.types b/tests/baselines/reference/minimal_nodeModules_declarationEmit.types
new file mode 100644
index 0000000000000..ab1b8fd4423c6
--- /dev/null
+++ b/tests/baselines/reference/minimal_nodeModules_declarationEmit.types
@@ -0,0 +1,21 @@
+=== /node_modules/foo/module.d.ts ===
+export declare class SomeExportedClass {
+>SomeExportedClass : SomeExportedClass
+
+ private foo: any;
+>foo : any
+}
+
+declare global {
+>global : typeof global
+
+ function returnsPrivateClassOhNo(): SomeExportedClass;
+>returnsPrivateClassOhNo : () => SomeExportedClass
+}
+
+=== /main.ts ===
+export const boom = returnsPrivateClassOhNo();
+>boom : import("/node_modules/foo/module").SomeExportedClass
+>returnsPrivateClassOhNo() : import("/node_modules/foo/module").SomeExportedClass
+>returnsPrivateClassOhNo : () => import("/node_modules/foo/module").SomeExportedClass
+
diff --git a/tests/baselines/reference/minimal_nonRelative.errors.txt b/tests/baselines/reference/minimal_nonRelative.errors.txt
new file mode 100644
index 0000000000000..9229d86fe597c
--- /dev/null
+++ b/tests/baselines/reference/minimal_nonRelative.errors.txt
@@ -0,0 +1,18 @@
+/main.ts(1,16): error TS2307: Cannot find module 'foo' or its corresponding type declarations.
+/main.ts(2,16): error TS2307: Cannot find module 'bar' or its corresponding type declarations.
+
+
+==== /node_modules/@types/foo/index.d.ts (0 errors) ====
+ export {};
+
+==== /node_modules/bar/index.d.ts (0 errors) ====
+ export {};
+
+==== /main.ts (2 errors) ====
+ import {} from "foo";
+ ~~~~~
+!!! error TS2307: Cannot find module 'foo' or its corresponding type declarations.
+ import {} from "bar";
+ ~~~~~
+!!! error TS2307: Cannot find module 'bar' or its corresponding type declarations.
+
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_nonRelative.trace.json b/tests/baselines/reference/minimal_nonRelative.trace.json
new file mode 100644
index 0000000000000..769cebfe4261f
--- /dev/null
+++ b/tests/baselines/reference/minimal_nonRelative.trace.json
@@ -0,0 +1,14 @@
+[
+ "======== Resolving module 'foo' from '/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name 'foo' was not resolved. ========",
+ "======== Resolving module 'bar' from '/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name 'bar' was not resolved. ========",
+ "======== Resolving type reference directive 'foo', containing file '__inferred type names__.ts', root directory '/node_modules/@types'. ========",
+ "Resolving with primary search path '/node_modules/@types'.",
+ "File '/node_modules/@types/foo/package.json' does not exist.",
+ "File '/node_modules/@types/foo/index.d.ts' exist - use it as a name resolution result.",
+ "Resolving real path for '/node_modules/@types/foo/index.d.ts', result '/node_modules/@types/foo/index.d.ts'.",
+ "======== Type reference directive 'foo' was successfully resolved to '/node_modules/@types/foo/index.d.ts', primary: true. ========"
+]
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_pathsAndBaseUrl.errors.txt b/tests/baselines/reference/minimal_pathsAndBaseUrl.errors.txt
new file mode 100644
index 0000000000000..31490691952d2
--- /dev/null
+++ b/tests/baselines/reference/minimal_pathsAndBaseUrl.errors.txt
@@ -0,0 +1,39 @@
+/main.ts(4,16): error TS2307: Cannot find module 'hello' or its corresponding type declarations.
+
+
+==== /tsconfig.json (0 errors) ====
+ {
+ "compilerOptions": {
+ "moduleResolution": "minimal",
+ "noEmit": true,
+ "allowImportingTsExtensions": true,
+ "baseUrl": ".",
+ "paths": {
+ "*": [
+ "*",
+ "./vendor/*",
+ "./vendor/*/index.d.ts",
+ "./apps/*"
+ ]
+ }
+ }
+ }
+
+==== /vendor/foo/index.d.ts (0 errors) ====
+ export {};
+
+==== /apps/hello.ts (0 errors) ====
+ export {};
+
+==== /foo.ts (0 errors) ====
+ export {};
+
+==== /main.ts (1 errors) ====
+ import {} from "foo";
+ import {} from "foo/index.js";
+ import {} from "hello.ts";
+ import {} from "hello";
+ ~~~~~~~
+!!! error TS2307: Cannot find module 'hello' or its corresponding type declarations.
+ import {} from "foo.js";
+
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_pathsAndBaseUrl.trace.json b/tests/baselines/reference/minimal_pathsAndBaseUrl.trace.json
new file mode 100644
index 0000000000000..9d8aa1165d31a
--- /dev/null
+++ b/tests/baselines/reference/minimal_pathsAndBaseUrl.trace.json
@@ -0,0 +1,73 @@
+[
+ "======== Resolving module 'foo' from '/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "'baseUrl' option is set to '/', using this value to resolve non-relative module name 'foo'.",
+ "'paths' option is specified, looking for a pattern to match module name 'foo'.",
+ "Module name 'foo', matched pattern '*'.",
+ "Trying substitution '*', candidate module location: 'foo'.",
+ "Trying substitution './vendor/*', candidate module location: './vendor/foo'.",
+ "Trying substitution './vendor/*/index.d.ts', candidate module location: './vendor/foo/index.d.ts'.",
+ "File '/vendor/foo/index.d.ts' exist - use it as a name resolution result.",
+ "======== Module name 'foo' was successfully resolved to '/vendor/foo/index.d.ts'. ========",
+ "======== Resolving module 'foo/index.js' from '/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "'baseUrl' option is set to '/', using this value to resolve non-relative module name 'foo/index.js'.",
+ "'paths' option is specified, looking for a pattern to match module name 'foo/index.js'.",
+ "Module name 'foo/index.js', matched pattern '*'.",
+ "Trying substitution '*', candidate module location: 'foo/index.js'.",
+ "File name '/foo/index.js' has a '.js' extension - stripping it.",
+ "Trying substitution './vendor/*', candidate module location: './vendor/foo/index.js'.",
+ "File name '/vendor/foo/index.js' has a '.js' extension - stripping it.",
+ "File '/vendor/foo/index.ts' does not exist.",
+ "File '/vendor/foo/index.tsx' does not exist.",
+ "File '/vendor/foo/index.d.ts' exist - use it as a name resolution result.",
+ "======== Module name 'foo/index.js' was successfully resolved to '/vendor/foo/index.d.ts'. ========",
+ "======== Resolving module 'hello.ts' from '/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "'baseUrl' option is set to '/', using this value to resolve non-relative module name 'hello.ts'.",
+ "'paths' option is specified, looking for a pattern to match module name 'hello.ts'.",
+ "Module name 'hello.ts', matched pattern '*'.",
+ "Trying substitution '*', candidate module location: 'hello.ts'.",
+ "File name '/hello.ts' has a '.ts' extension - stripping it.",
+ "File '/hello.ts' does not exist.",
+ "Trying substitution './vendor/*', candidate module location: './vendor/hello.ts'.",
+ "File name '/vendor/hello.ts' has a '.ts' extension - stripping it.",
+ "File '/vendor/hello.ts' does not exist.",
+ "Trying substitution './vendor/*/index.d.ts', candidate module location: './vendor/hello.ts/index.d.ts'.",
+ "File '/vendor/hello.ts/index.d.ts' does not exist.",
+ "File name '/vendor/hello.ts/index.d.ts' has a '.d.ts' extension - stripping it.",
+ "Trying substitution './apps/*', candidate module location: './apps/hello.ts'.",
+ "File name '/apps/hello.ts' has a '.ts' extension - stripping it.",
+ "File '/apps/hello.ts' exist - use it as a name resolution result.",
+ "======== Module name 'hello.ts' was successfully resolved to '/apps/hello.ts'. ========",
+ "======== Resolving module 'hello' from '/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "'baseUrl' option is set to '/', using this value to resolve non-relative module name 'hello'.",
+ "'paths' option is specified, looking for a pattern to match module name 'hello'.",
+ "Module name 'hello', matched pattern '*'.",
+ "Trying substitution '*', candidate module location: 'hello'.",
+ "Trying substitution './vendor/*', candidate module location: './vendor/hello'.",
+ "Trying substitution './vendor/*/index.d.ts', candidate module location: './vendor/hello/index.d.ts'.",
+ "File '/vendor/hello/index.d.ts' does not exist.",
+ "File name '/vendor/hello/index.d.ts' has a '.d.ts' extension - stripping it.",
+ "Trying substitution './apps/*', candidate module location: './apps/hello'.",
+ "'baseUrl' option is set to '/', using this value to resolve non-relative module name 'hello'.",
+ "'paths' option is specified, looking for a pattern to match module name 'hello'.",
+ "Module name 'hello', matched pattern '*'.",
+ "Trying substitution '*', candidate module location: 'hello'.",
+ "Trying substitution './vendor/*', candidate module location: './vendor/hello'.",
+ "Trying substitution './vendor/*/index.d.ts', candidate module location: './vendor/hello/index.d.ts'.",
+ "File '/vendor/hello/index.d.ts' does not exist.",
+ "File name '/vendor/hello/index.d.ts' has a '.d.ts' extension - stripping it.",
+ "Trying substitution './apps/*', candidate module location: './apps/hello'.",
+ "======== Module name 'hello' was not resolved. ========",
+ "======== Resolving module 'foo.js' from '/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "'baseUrl' option is set to '/', using this value to resolve non-relative module name 'foo.js'.",
+ "'paths' option is specified, looking for a pattern to match module name 'foo.js'.",
+ "Module name 'foo.js', matched pattern '*'.",
+ "Trying substitution '*', candidate module location: 'foo.js'.",
+ "File name '/foo.js' has a '.js' extension - stripping it.",
+ "File '/foo.ts' exist - use it as a name resolution result.",
+ "======== Module name 'foo.js' was successfully resolved to '/foo.ts'. ========"
+]
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=false).errors.txt b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=false).errors.txt
new file mode 100644
index 0000000000000..5aa51b4e3c2f0
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=false).errors.txt
@@ -0,0 +1,107 @@
+error TS5056: Cannot write file 'dist/c.js' because it would be overwritten by multiple input files.
+error TS6231: Could not resolve the path '/project/e' with the extensions: '.ts', '.tsx', '.d.ts', '.cts', '.d.cts', '.mts', '.d.mts'.
+ The file is in the program because:
+ Root file specified for compilation
+error TS6504: File '/project/b.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
+ The file is in the program because:
+ Root file specified for compilation
+/project/main.ts(1,16): error TS2307: Cannot find module './a' or its corresponding type declarations.
+/project/main.ts(3,16): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
+/project/main.ts(5,16): error TS2307: Cannot find module './b' or its corresponding type declarations.
+/project/main.ts(7,16): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
+/project/main.ts(8,16): error TS2846: A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file './b.js' instead?
+/project/main.ts(11,16): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
+/project/main.ts(12,16): error TS5097: An import path can only end with a '.tsx' extension when 'allowImportingTsExtensions' is enabled.
+/project/main.ts(12,16): error TS6142: Module './c.tsx' was resolved to '/project/c.tsx', but '--jsx' is not set.
+/project/main.ts(14,16): error TS2307: Cannot find module './d' or its corresponding type declarations.
+/project/main.ts(15,16): error TS2307: Cannot find module './d/index' or its corresponding type declarations.
+/project/main.ts(16,16): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
+/project/main.ts(18,16): error TS2307: Cannot find module './e' or its corresponding type declarations.
+/project/types.d.ts(2,16): error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './a.js' instead.
+/project/types.d.ts(3,21): error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './a.js' instead.
+
+
+!!! error TS5056: Cannot write file 'dist/c.js' because it would be overwritten by multiple input files.
+!!! error TS6231: Could not resolve the path '/project/e' with the extensions: '.ts', '.tsx', '.d.ts', '.cts', '.d.cts', '.mts', '.d.mts'.
+!!! error TS6231: The file is in the program because:
+!!! error TS6231: Root file specified for compilation
+!!! error TS6504: File '/project/b.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
+!!! error TS6504: The file is in the program because:
+!!! error TS6504: Root file specified for compilation
+==== /project/a.ts (0 errors) ====
+ export {};
+
+==== /project/b.ts (0 errors) ====
+ export {};
+
+==== /project/b.js (0 errors) ====
+ export {};
+
+==== /project/b.d.ts (0 errors) ====
+ export {};
+
+==== /project/c.ts (0 errors) ====
+ export {};
+
+==== /project/c.tsx (0 errors) ====
+ export {};
+
+==== /project/d/index.ts (0 errors) ====
+ export {};
+
+==== /project/e (0 errors) ====
+ export {};
+
+==== /project/main.ts (12 errors) ====
+ import {} from "./a";
+ ~~~~~
+!!! error TS2307: Cannot find module './a' or its corresponding type declarations.
+ import {} from "./a.js";
+ import {} from "./a.ts";
+ ~~~~~~~~
+!!! error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
+
+ import {} from "./b";
+ ~~~~~
+!!! error TS2307: Cannot find module './b' or its corresponding type declarations.
+ import {} from "./b.js";
+ import {} from "./b.ts";
+ ~~~~~~~~
+!!! error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
+ import {} from "./b.d.ts";
+ ~~~~~~~~~~
+!!! error TS2846: A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file './b.js' instead?
+ import type {} from "./b.d.ts";
+
+ import {} from "./c.ts";
+ ~~~~~~~~
+!!! error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
+ import {} from "./c.tsx";
+ ~~~~~~~~~
+!!! error TS5097: An import path can only end with a '.tsx' extension when 'allowImportingTsExtensions' is enabled.
+ ~~~~~~~~~
+!!! error TS6142: Module './c.tsx' was resolved to '/project/c.tsx', but '--jsx' is not set.
+
+ import {} from "./d";
+ ~~~~~
+!!! error TS2307: Cannot find module './d' or its corresponding type declarations.
+ import {} from "./d/index";
+ ~~~~~~~~~~~
+!!! error TS2307: Cannot find module './d/index' or its corresponding type declarations.
+ import {} from "./d/index.ts";
+ ~~~~~~~~~~~~~~
+!!! error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
+
+ import {} from "./e";
+ ~~~~~
+!!! error TS2307: Cannot find module './e' or its corresponding type declarations.
+
+==== /project/types.d.ts (2 errors) ====
+ import {} from "./a.ts";
+ import {} from "./a.d.ts";
+ ~~~~~~~~~~
+!!! error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './a.js' instead.
+ import type {} from "./a.d.ts";
+ ~~~~~~~~~~
+!!! error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './a.js' instead.
+
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=false).js b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=false).js
new file mode 100644
index 0000000000000..2eeeabf051a24
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=false).js
@@ -0,0 +1,64 @@
+//// [tests/cases/conformance/moduleResolution/minimal_relative.ts] ////
+
+//// [a.ts]
+export {};
+
+//// [b.ts]
+export {};
+
+//// [b.js]
+export {};
+
+//// [b.d.ts]
+export {};
+
+//// [c.ts]
+export {};
+
+//// [c.tsx]
+export {};
+
+//// [index.ts]
+export {};
+
+//// [e]
+export {};
+
+//// [main.ts]
+import {} from "./a";
+import {} from "./a.js";
+import {} from "./a.ts";
+
+import {} from "./b";
+import {} from "./b.js";
+import {} from "./b.ts";
+import {} from "./b.d.ts";
+import type {} from "./b.d.ts";
+
+import {} from "./c.ts";
+import {} from "./c.tsx";
+
+import {} from "./d";
+import {} from "./d/index";
+import {} from "./d/index.ts";
+
+import {} from "./e";
+
+//// [types.d.ts]
+import {} from "./a.ts";
+import {} from "./a.d.ts";
+import type {} from "./a.d.ts";
+
+
+//// [a.js]
+"use strict";
+exports.__esModule = true;
+//// [b.js]
+"use strict";
+exports.__esModule = true;
+//// [index.js]
+"use strict";
+exports.__esModule = true;
+//// [main.js]
+"use strict";
+exports.__esModule = true;
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=false).symbols b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=false).symbols
new file mode 100644
index 0000000000000..8087e521944d1
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=false).symbols
@@ -0,0 +1,44 @@
+=== /project/a.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.d.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.tsx ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/d/index.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/main.ts ===
+import {} from "./a";
+No type information for this code.import {} from "./a.js";
+No type information for this code.import {} from "./a.ts";
+No type information for this code.
+No type information for this code.import {} from "./b";
+No type information for this code.import {} from "./b.js";
+No type information for this code.import {} from "./b.ts";
+No type information for this code.import {} from "./b.d.ts";
+No type information for this code.import type {} from "./b.d.ts";
+No type information for this code.
+No type information for this code.import {} from "./c.ts";
+No type information for this code.import {} from "./c.tsx";
+No type information for this code.
+No type information for this code.import {} from "./d";
+No type information for this code.import {} from "./d/index";
+No type information for this code.import {} from "./d/index.ts";
+No type information for this code.
+No type information for this code.import {} from "./e";
+No type information for this code.
+No type information for this code.=== /project/types.d.ts ===
+import {} from "./a.ts";
+No type information for this code.import {} from "./a.d.ts";
+No type information for this code.import type {} from "./a.d.ts";
+No type information for this code.
+No type information for this code.
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=false).trace.json b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=false).trace.json
new file mode 100644
index 0000000000000..40a02fe86a714
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=false).trace.json
@@ -0,0 +1,68 @@
+[
+ "======== Resolving module './a' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './a' was not resolved. ========",
+ "======== Resolving module './a.js' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/a.js' has a '.js' extension - stripping it.",
+ "File '/project/a.ts' exist - use it as a name resolution result.",
+ "======== Module name './a.js' was successfully resolved to '/project/a.ts'. ========",
+ "======== Resolving module './a.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/a.ts' has a '.ts' extension - stripping it.",
+ "File '/project/a.ts' exist - use it as a name resolution result.",
+ "======== Module name './a.ts' was successfully resolved to '/project/a.ts'. ========",
+ "======== Resolving module './b' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './b' was not resolved. ========",
+ "======== Resolving module './b.js' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.js' has a '.js' extension - stripping it.",
+ "File '/project/b.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.js' was successfully resolved to '/project/b.ts'. ========",
+ "======== Resolving module './b.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.ts' has a '.ts' extension - stripping it.",
+ "File '/project/b.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.ts' was successfully resolved to '/project/b.ts'. ========",
+ "======== Resolving module './b.d.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.d.ts' has a '.d.ts' extension - stripping it.",
+ "File '/project/b.d.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.d.ts' was successfully resolved to '/project/b.d.ts'. ========",
+ "======== Resolving module './c.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/c.ts' has a '.ts' extension - stripping it.",
+ "File '/project/c.ts' exist - use it as a name resolution result.",
+ "======== Module name './c.ts' was successfully resolved to '/project/c.ts'. ========",
+ "======== Resolving module './c.tsx' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/c.tsx' has a '.tsx' extension - stripping it.",
+ "File '/project/c.tsx' exist - use it as a name resolution result.",
+ "======== Module name './c.tsx' was successfully resolved to '/project/c.tsx'. ========",
+ "======== Resolving module './d' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './d' was not resolved. ========",
+ "======== Resolving module './d/index' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './d/index' was not resolved. ========",
+ "======== Resolving module './d/index.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/d/index.ts' has a '.ts' extension - stripping it.",
+ "File '/project/d/index.ts' exist - use it as a name resolution result.",
+ "======== Module name './d/index.ts' was successfully resolved to '/project/d/index.ts'. ========",
+ "======== Resolving module './e' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './e' was not resolved. ========",
+ "======== Resolving module './a.ts' from '/project/types.d.ts'. ========",
+ "Resolution for module './a.ts' was found in cache from location '/project'.",
+ "======== Module name './a.ts' was successfully resolved to '/project/a.ts'. ========",
+ "======== Resolving module './a.d.ts' from '/project/types.d.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/a.d.ts' has a '.d.ts' extension - stripping it.",
+ "File '/project/a.d.ts' does not exist.",
+ "File name '/project/a.d.ts' has a '.d.ts' extension - stripping it.",
+ "File '/project/a.js' does not exist.",
+ "File '/project/a.jsx' does not exist.",
+ "======== Module name './a.d.ts' was not resolved. ========"
+]
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=false).types b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=false).types
new file mode 100644
index 0000000000000..8087e521944d1
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=false).types
@@ -0,0 +1,44 @@
+=== /project/a.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.d.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.tsx ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/d/index.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/main.ts ===
+import {} from "./a";
+No type information for this code.import {} from "./a.js";
+No type information for this code.import {} from "./a.ts";
+No type information for this code.
+No type information for this code.import {} from "./b";
+No type information for this code.import {} from "./b.js";
+No type information for this code.import {} from "./b.ts";
+No type information for this code.import {} from "./b.d.ts";
+No type information for this code.import type {} from "./b.d.ts";
+No type information for this code.
+No type information for this code.import {} from "./c.ts";
+No type information for this code.import {} from "./c.tsx";
+No type information for this code.
+No type information for this code.import {} from "./d";
+No type information for this code.import {} from "./d/index";
+No type information for this code.import {} from "./d/index.ts";
+No type information for this code.
+No type information for this code.import {} from "./e";
+No type information for this code.
+No type information for this code.=== /project/types.d.ts ===
+import {} from "./a.ts";
+No type information for this code.import {} from "./a.d.ts";
+No type information for this code.import type {} from "./a.d.ts";
+No type information for this code.
+No type information for this code.
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=true).errors.txt b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=true).errors.txt
new file mode 100644
index 0000000000000..d7335e31c3223
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=true).errors.txt
@@ -0,0 +1,105 @@
+error TS6231: Could not resolve the path '/project/e' with the extensions: '.ts', '.tsx', '.d.ts', '.cts', '.d.cts', '.mts', '.d.mts'.
+ The file is in the program because:
+ Root file specified for compilation
+error TS6504: File '/project/b.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
+ The file is in the program because:
+ Root file specified for compilation
+/project/main.ts(1,16): error TS2307: Cannot find module './a' or its corresponding type declarations.
+/project/main.ts(3,16): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
+/project/main.ts(5,16): error TS2307: Cannot find module './b' or its corresponding type declarations.
+/project/main.ts(7,16): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
+/project/main.ts(8,16): error TS2846: A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file './b.js' instead?
+/project/main.ts(11,16): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
+/project/main.ts(12,16): error TS5097: An import path can only end with a '.tsx' extension when 'allowImportingTsExtensions' is enabled.
+/project/main.ts(12,16): error TS6142: Module './c.tsx' was resolved to '/project/c.tsx', but '--jsx' is not set.
+/project/main.ts(14,16): error TS2307: Cannot find module './d' or its corresponding type declarations.
+/project/main.ts(15,16): error TS2307: Cannot find module './d/index' or its corresponding type declarations.
+/project/main.ts(16,16): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
+/project/main.ts(18,16): error TS2307: Cannot find module './e' or its corresponding type declarations.
+/project/types.d.ts(2,16): error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './a.js' instead.
+/project/types.d.ts(3,21): error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './a.js' instead.
+
+
+!!! error TS6231: Could not resolve the path '/project/e' with the extensions: '.ts', '.tsx', '.d.ts', '.cts', '.d.cts', '.mts', '.d.mts'.
+!!! error TS6231: The file is in the program because:
+!!! error TS6231: Root file specified for compilation
+!!! error TS6504: File '/project/b.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
+!!! error TS6504: The file is in the program because:
+!!! error TS6504: Root file specified for compilation
+==== /project/a.ts (0 errors) ====
+ export {};
+
+==== /project/b.ts (0 errors) ====
+ export {};
+
+==== /project/b.js (0 errors) ====
+ export {};
+
+==== /project/b.d.ts (0 errors) ====
+ export {};
+
+==== /project/c.ts (0 errors) ====
+ export {};
+
+==== /project/c.tsx (0 errors) ====
+ export {};
+
+==== /project/d/index.ts (0 errors) ====
+ export {};
+
+==== /project/e (0 errors) ====
+ export {};
+
+==== /project/main.ts (12 errors) ====
+ import {} from "./a";
+ ~~~~~
+!!! error TS2307: Cannot find module './a' or its corresponding type declarations.
+ import {} from "./a.js";
+ import {} from "./a.ts";
+ ~~~~~~~~
+!!! error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
+
+ import {} from "./b";
+ ~~~~~
+!!! error TS2307: Cannot find module './b' or its corresponding type declarations.
+ import {} from "./b.js";
+ import {} from "./b.ts";
+ ~~~~~~~~
+!!! error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
+ import {} from "./b.d.ts";
+ ~~~~~~~~~~
+!!! error TS2846: A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file './b.js' instead?
+ import type {} from "./b.d.ts";
+
+ import {} from "./c.ts";
+ ~~~~~~~~
+!!! error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
+ import {} from "./c.tsx";
+ ~~~~~~~~~
+!!! error TS5097: An import path can only end with a '.tsx' extension when 'allowImportingTsExtensions' is enabled.
+ ~~~~~~~~~
+!!! error TS6142: Module './c.tsx' was resolved to '/project/c.tsx', but '--jsx' is not set.
+
+ import {} from "./d";
+ ~~~~~
+!!! error TS2307: Cannot find module './d' or its corresponding type declarations.
+ import {} from "./d/index";
+ ~~~~~~~~~~~
+!!! error TS2307: Cannot find module './d/index' or its corresponding type declarations.
+ import {} from "./d/index.ts";
+ ~~~~~~~~~~~~~~
+!!! error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
+
+ import {} from "./e";
+ ~~~~~
+!!! error TS2307: Cannot find module './e' or its corresponding type declarations.
+
+==== /project/types.d.ts (2 errors) ====
+ import {} from "./a.ts";
+ import {} from "./a.d.ts";
+ ~~~~~~~~~~
+!!! error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './a.js' instead.
+ import type {} from "./a.d.ts";
+ ~~~~~~~~~~
+!!! error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './a.js' instead.
+
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=true).symbols b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=true).symbols
new file mode 100644
index 0000000000000..8087e521944d1
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=true).symbols
@@ -0,0 +1,44 @@
+=== /project/a.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.d.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.tsx ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/d/index.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/main.ts ===
+import {} from "./a";
+No type information for this code.import {} from "./a.js";
+No type information for this code.import {} from "./a.ts";
+No type information for this code.
+No type information for this code.import {} from "./b";
+No type information for this code.import {} from "./b.js";
+No type information for this code.import {} from "./b.ts";
+No type information for this code.import {} from "./b.d.ts";
+No type information for this code.import type {} from "./b.d.ts";
+No type information for this code.
+No type information for this code.import {} from "./c.ts";
+No type information for this code.import {} from "./c.tsx";
+No type information for this code.
+No type information for this code.import {} from "./d";
+No type information for this code.import {} from "./d/index";
+No type information for this code.import {} from "./d/index.ts";
+No type information for this code.
+No type information for this code.import {} from "./e";
+No type information for this code.
+No type information for this code.=== /project/types.d.ts ===
+import {} from "./a.ts";
+No type information for this code.import {} from "./a.d.ts";
+No type information for this code.import type {} from "./a.d.ts";
+No type information for this code.
+No type information for this code.
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=true).trace.json b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=true).trace.json
new file mode 100644
index 0000000000000..40a02fe86a714
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=true).trace.json
@@ -0,0 +1,68 @@
+[
+ "======== Resolving module './a' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './a' was not resolved. ========",
+ "======== Resolving module './a.js' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/a.js' has a '.js' extension - stripping it.",
+ "File '/project/a.ts' exist - use it as a name resolution result.",
+ "======== Module name './a.js' was successfully resolved to '/project/a.ts'. ========",
+ "======== Resolving module './a.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/a.ts' has a '.ts' extension - stripping it.",
+ "File '/project/a.ts' exist - use it as a name resolution result.",
+ "======== Module name './a.ts' was successfully resolved to '/project/a.ts'. ========",
+ "======== Resolving module './b' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './b' was not resolved. ========",
+ "======== Resolving module './b.js' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.js' has a '.js' extension - stripping it.",
+ "File '/project/b.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.js' was successfully resolved to '/project/b.ts'. ========",
+ "======== Resolving module './b.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.ts' has a '.ts' extension - stripping it.",
+ "File '/project/b.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.ts' was successfully resolved to '/project/b.ts'. ========",
+ "======== Resolving module './b.d.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.d.ts' has a '.d.ts' extension - stripping it.",
+ "File '/project/b.d.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.d.ts' was successfully resolved to '/project/b.d.ts'. ========",
+ "======== Resolving module './c.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/c.ts' has a '.ts' extension - stripping it.",
+ "File '/project/c.ts' exist - use it as a name resolution result.",
+ "======== Module name './c.ts' was successfully resolved to '/project/c.ts'. ========",
+ "======== Resolving module './c.tsx' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/c.tsx' has a '.tsx' extension - stripping it.",
+ "File '/project/c.tsx' exist - use it as a name resolution result.",
+ "======== Module name './c.tsx' was successfully resolved to '/project/c.tsx'. ========",
+ "======== Resolving module './d' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './d' was not resolved. ========",
+ "======== Resolving module './d/index' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './d/index' was not resolved. ========",
+ "======== Resolving module './d/index.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/d/index.ts' has a '.ts' extension - stripping it.",
+ "File '/project/d/index.ts' exist - use it as a name resolution result.",
+ "======== Module name './d/index.ts' was successfully resolved to '/project/d/index.ts'. ========",
+ "======== Resolving module './e' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './e' was not resolved. ========",
+ "======== Resolving module './a.ts' from '/project/types.d.ts'. ========",
+ "Resolution for module './a.ts' was found in cache from location '/project'.",
+ "======== Module name './a.ts' was successfully resolved to '/project/a.ts'. ========",
+ "======== Resolving module './a.d.ts' from '/project/types.d.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/a.d.ts' has a '.d.ts' extension - stripping it.",
+ "File '/project/a.d.ts' does not exist.",
+ "File name '/project/a.d.ts' has a '.d.ts' extension - stripping it.",
+ "File '/project/a.js' does not exist.",
+ "File '/project/a.jsx' does not exist.",
+ "======== Module name './a.d.ts' was not resolved. ========"
+]
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=true).types b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=true).types
new file mode 100644
index 0000000000000..8087e521944d1
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=false,noemit=true).types
@@ -0,0 +1,44 @@
+=== /project/a.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.d.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.tsx ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/d/index.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/main.ts ===
+import {} from "./a";
+No type information for this code.import {} from "./a.js";
+No type information for this code.import {} from "./a.ts";
+No type information for this code.
+No type information for this code.import {} from "./b";
+No type information for this code.import {} from "./b.js";
+No type information for this code.import {} from "./b.ts";
+No type information for this code.import {} from "./b.d.ts";
+No type information for this code.import type {} from "./b.d.ts";
+No type information for this code.
+No type information for this code.import {} from "./c.ts";
+No type information for this code.import {} from "./c.tsx";
+No type information for this code.
+No type information for this code.import {} from "./d";
+No type information for this code.import {} from "./d/index";
+No type information for this code.import {} from "./d/index.ts";
+No type information for this code.
+No type information for this code.import {} from "./e";
+No type information for this code.
+No type information for this code.=== /project/types.d.ts ===
+import {} from "./a.ts";
+No type information for this code.import {} from "./a.d.ts";
+No type information for this code.import type {} from "./a.d.ts";
+No type information for this code.
+No type information for this code.
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=false).errors.txt b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=false).errors.txt
new file mode 100644
index 0000000000000..f995ec83d1e1f
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=false).errors.txt
@@ -0,0 +1,94 @@
+error TS5056: Cannot write file 'dist/c.js' because it would be overwritten by multiple input files.
+error TS5096: Option 'allowImportingTsExtensions' can only be used when 'moduleResolution' is set to 'minimal' and either 'noEmit' or 'emitDeclarationOnly' is set.
+error TS6231: Could not resolve the path '/project/e' with the extensions: '.ts', '.tsx', '.d.ts', '.cts', '.d.cts', '.mts', '.d.mts'.
+ The file is in the program because:
+ Root file specified for compilation
+error TS6504: File '/project/b.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
+ The file is in the program because:
+ Root file specified for compilation
+/project/main.ts(1,16): error TS2307: Cannot find module './a' or its corresponding type declarations.
+/project/main.ts(5,16): error TS2307: Cannot find module './b' or its corresponding type declarations.
+/project/main.ts(8,16): error TS2846: A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file './b.js' instead?
+/project/main.ts(12,16): error TS6142: Module './c.tsx' was resolved to '/project/c.tsx', but '--jsx' is not set.
+/project/main.ts(14,16): error TS2307: Cannot find module './d' or its corresponding type declarations.
+/project/main.ts(15,16): error TS2307: Cannot find module './d/index' or its corresponding type declarations.
+/project/main.ts(18,16): error TS2307: Cannot find module './e' or its corresponding type declarations.
+/project/types.d.ts(2,16): error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './a.js' instead.
+/project/types.d.ts(3,21): error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './a.js' instead.
+
+
+!!! error TS5056: Cannot write file 'dist/c.js' because it would be overwritten by multiple input files.
+!!! error TS5096: Option 'allowImportingTsExtensions' can only be used when 'moduleResolution' is set to 'minimal' and either 'noEmit' or 'emitDeclarationOnly' is set.
+!!! error TS6231: Could not resolve the path '/project/e' with the extensions: '.ts', '.tsx', '.d.ts', '.cts', '.d.cts', '.mts', '.d.mts'.
+!!! error TS6231: The file is in the program because:
+!!! error TS6231: Root file specified for compilation
+!!! error TS6504: File '/project/b.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
+!!! error TS6504: The file is in the program because:
+!!! error TS6504: Root file specified for compilation
+==== /project/a.ts (0 errors) ====
+ export {};
+
+==== /project/b.ts (0 errors) ====
+ export {};
+
+==== /project/b.js (0 errors) ====
+ export {};
+
+==== /project/b.d.ts (0 errors) ====
+ export {};
+
+==== /project/c.ts (0 errors) ====
+ export {};
+
+==== /project/c.tsx (0 errors) ====
+ export {};
+
+==== /project/d/index.ts (0 errors) ====
+ export {};
+
+==== /project/e (0 errors) ====
+ export {};
+
+==== /project/main.ts (7 errors) ====
+ import {} from "./a";
+ ~~~~~
+!!! error TS2307: Cannot find module './a' or its corresponding type declarations.
+ import {} from "./a.js";
+ import {} from "./a.ts";
+
+ import {} from "./b";
+ ~~~~~
+!!! error TS2307: Cannot find module './b' or its corresponding type declarations.
+ import {} from "./b.js";
+ import {} from "./b.ts";
+ import {} from "./b.d.ts";
+ ~~~~~~~~~~
+!!! error TS2846: A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file './b.js' instead?
+ import type {} from "./b.d.ts";
+
+ import {} from "./c.ts";
+ import {} from "./c.tsx";
+ ~~~~~~~~~
+!!! error TS6142: Module './c.tsx' was resolved to '/project/c.tsx', but '--jsx' is not set.
+
+ import {} from "./d";
+ ~~~~~
+!!! error TS2307: Cannot find module './d' or its corresponding type declarations.
+ import {} from "./d/index";
+ ~~~~~~~~~~~
+!!! error TS2307: Cannot find module './d/index' or its corresponding type declarations.
+ import {} from "./d/index.ts";
+
+ import {} from "./e";
+ ~~~~~
+!!! error TS2307: Cannot find module './e' or its corresponding type declarations.
+
+==== /project/types.d.ts (2 errors) ====
+ import {} from "./a.ts";
+ import {} from "./a.d.ts";
+ ~~~~~~~~~~
+!!! error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './a.js' instead.
+ import type {} from "./a.d.ts";
+ ~~~~~~~~~~
+!!! error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './a.js' instead.
+
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=false).js b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=false).js
new file mode 100644
index 0000000000000..2eeeabf051a24
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=false).js
@@ -0,0 +1,64 @@
+//// [tests/cases/conformance/moduleResolution/minimal_relative.ts] ////
+
+//// [a.ts]
+export {};
+
+//// [b.ts]
+export {};
+
+//// [b.js]
+export {};
+
+//// [b.d.ts]
+export {};
+
+//// [c.ts]
+export {};
+
+//// [c.tsx]
+export {};
+
+//// [index.ts]
+export {};
+
+//// [e]
+export {};
+
+//// [main.ts]
+import {} from "./a";
+import {} from "./a.js";
+import {} from "./a.ts";
+
+import {} from "./b";
+import {} from "./b.js";
+import {} from "./b.ts";
+import {} from "./b.d.ts";
+import type {} from "./b.d.ts";
+
+import {} from "./c.ts";
+import {} from "./c.tsx";
+
+import {} from "./d";
+import {} from "./d/index";
+import {} from "./d/index.ts";
+
+import {} from "./e";
+
+//// [types.d.ts]
+import {} from "./a.ts";
+import {} from "./a.d.ts";
+import type {} from "./a.d.ts";
+
+
+//// [a.js]
+"use strict";
+exports.__esModule = true;
+//// [b.js]
+"use strict";
+exports.__esModule = true;
+//// [index.js]
+"use strict";
+exports.__esModule = true;
+//// [main.js]
+"use strict";
+exports.__esModule = true;
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=false).symbols b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=false).symbols
new file mode 100644
index 0000000000000..8087e521944d1
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=false).symbols
@@ -0,0 +1,44 @@
+=== /project/a.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.d.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.tsx ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/d/index.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/main.ts ===
+import {} from "./a";
+No type information for this code.import {} from "./a.js";
+No type information for this code.import {} from "./a.ts";
+No type information for this code.
+No type information for this code.import {} from "./b";
+No type information for this code.import {} from "./b.js";
+No type information for this code.import {} from "./b.ts";
+No type information for this code.import {} from "./b.d.ts";
+No type information for this code.import type {} from "./b.d.ts";
+No type information for this code.
+No type information for this code.import {} from "./c.ts";
+No type information for this code.import {} from "./c.tsx";
+No type information for this code.
+No type information for this code.import {} from "./d";
+No type information for this code.import {} from "./d/index";
+No type information for this code.import {} from "./d/index.ts";
+No type information for this code.
+No type information for this code.import {} from "./e";
+No type information for this code.
+No type information for this code.=== /project/types.d.ts ===
+import {} from "./a.ts";
+No type information for this code.import {} from "./a.d.ts";
+No type information for this code.import type {} from "./a.d.ts";
+No type information for this code.
+No type information for this code.
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=false).trace.json b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=false).trace.json
new file mode 100644
index 0000000000000..40a02fe86a714
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=false).trace.json
@@ -0,0 +1,68 @@
+[
+ "======== Resolving module './a' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './a' was not resolved. ========",
+ "======== Resolving module './a.js' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/a.js' has a '.js' extension - stripping it.",
+ "File '/project/a.ts' exist - use it as a name resolution result.",
+ "======== Module name './a.js' was successfully resolved to '/project/a.ts'. ========",
+ "======== Resolving module './a.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/a.ts' has a '.ts' extension - stripping it.",
+ "File '/project/a.ts' exist - use it as a name resolution result.",
+ "======== Module name './a.ts' was successfully resolved to '/project/a.ts'. ========",
+ "======== Resolving module './b' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './b' was not resolved. ========",
+ "======== Resolving module './b.js' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.js' has a '.js' extension - stripping it.",
+ "File '/project/b.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.js' was successfully resolved to '/project/b.ts'. ========",
+ "======== Resolving module './b.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.ts' has a '.ts' extension - stripping it.",
+ "File '/project/b.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.ts' was successfully resolved to '/project/b.ts'. ========",
+ "======== Resolving module './b.d.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.d.ts' has a '.d.ts' extension - stripping it.",
+ "File '/project/b.d.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.d.ts' was successfully resolved to '/project/b.d.ts'. ========",
+ "======== Resolving module './c.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/c.ts' has a '.ts' extension - stripping it.",
+ "File '/project/c.ts' exist - use it as a name resolution result.",
+ "======== Module name './c.ts' was successfully resolved to '/project/c.ts'. ========",
+ "======== Resolving module './c.tsx' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/c.tsx' has a '.tsx' extension - stripping it.",
+ "File '/project/c.tsx' exist - use it as a name resolution result.",
+ "======== Module name './c.tsx' was successfully resolved to '/project/c.tsx'. ========",
+ "======== Resolving module './d' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './d' was not resolved. ========",
+ "======== Resolving module './d/index' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './d/index' was not resolved. ========",
+ "======== Resolving module './d/index.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/d/index.ts' has a '.ts' extension - stripping it.",
+ "File '/project/d/index.ts' exist - use it as a name resolution result.",
+ "======== Module name './d/index.ts' was successfully resolved to '/project/d/index.ts'. ========",
+ "======== Resolving module './e' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './e' was not resolved. ========",
+ "======== Resolving module './a.ts' from '/project/types.d.ts'. ========",
+ "Resolution for module './a.ts' was found in cache from location '/project'.",
+ "======== Module name './a.ts' was successfully resolved to '/project/a.ts'. ========",
+ "======== Resolving module './a.d.ts' from '/project/types.d.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/a.d.ts' has a '.d.ts' extension - stripping it.",
+ "File '/project/a.d.ts' does not exist.",
+ "File name '/project/a.d.ts' has a '.d.ts' extension - stripping it.",
+ "File '/project/a.js' does not exist.",
+ "File '/project/a.jsx' does not exist.",
+ "======== Module name './a.d.ts' was not resolved. ========"
+]
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=false).types b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=false).types
new file mode 100644
index 0000000000000..8087e521944d1
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=false).types
@@ -0,0 +1,44 @@
+=== /project/a.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.d.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.tsx ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/d/index.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/main.ts ===
+import {} from "./a";
+No type information for this code.import {} from "./a.js";
+No type information for this code.import {} from "./a.ts";
+No type information for this code.
+No type information for this code.import {} from "./b";
+No type information for this code.import {} from "./b.js";
+No type information for this code.import {} from "./b.ts";
+No type information for this code.import {} from "./b.d.ts";
+No type information for this code.import type {} from "./b.d.ts";
+No type information for this code.
+No type information for this code.import {} from "./c.ts";
+No type information for this code.import {} from "./c.tsx";
+No type information for this code.
+No type information for this code.import {} from "./d";
+No type information for this code.import {} from "./d/index";
+No type information for this code.import {} from "./d/index.ts";
+No type information for this code.
+No type information for this code.import {} from "./e";
+No type information for this code.
+No type information for this code.=== /project/types.d.ts ===
+import {} from "./a.ts";
+No type information for this code.import {} from "./a.d.ts";
+No type information for this code.import type {} from "./a.d.ts";
+No type information for this code.
+No type information for this code.
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=true).errors.txt b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=true).errors.txt
new file mode 100644
index 0000000000000..96f418edbce5b
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=true).errors.txt
@@ -0,0 +1,90 @@
+error TS6231: Could not resolve the path '/project/e' with the extensions: '.ts', '.tsx', '.d.ts', '.cts', '.d.cts', '.mts', '.d.mts'.
+ The file is in the program because:
+ Root file specified for compilation
+error TS6504: File '/project/b.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
+ The file is in the program because:
+ Root file specified for compilation
+/project/main.ts(1,16): error TS2307: Cannot find module './a' or its corresponding type declarations.
+/project/main.ts(5,16): error TS2307: Cannot find module './b' or its corresponding type declarations.
+/project/main.ts(8,16): error TS2846: A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file './b.js' instead?
+/project/main.ts(12,16): error TS6142: Module './c.tsx' was resolved to '/project/c.tsx', but '--jsx' is not set.
+/project/main.ts(14,16): error TS2307: Cannot find module './d' or its corresponding type declarations.
+/project/main.ts(15,16): error TS2307: Cannot find module './d/index' or its corresponding type declarations.
+/project/main.ts(18,16): error TS2307: Cannot find module './e' or its corresponding type declarations.
+/project/types.d.ts(2,16): error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './a.js' instead.
+/project/types.d.ts(3,21): error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './a.js' instead.
+
+
+!!! error TS6231: Could not resolve the path '/project/e' with the extensions: '.ts', '.tsx', '.d.ts', '.cts', '.d.cts', '.mts', '.d.mts'.
+!!! error TS6231: The file is in the program because:
+!!! error TS6231: Root file specified for compilation
+!!! error TS6504: File '/project/b.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
+!!! error TS6504: The file is in the program because:
+!!! error TS6504: Root file specified for compilation
+==== /project/a.ts (0 errors) ====
+ export {};
+
+==== /project/b.ts (0 errors) ====
+ export {};
+
+==== /project/b.js (0 errors) ====
+ export {};
+
+==== /project/b.d.ts (0 errors) ====
+ export {};
+
+==== /project/c.ts (0 errors) ====
+ export {};
+
+==== /project/c.tsx (0 errors) ====
+ export {};
+
+==== /project/d/index.ts (0 errors) ====
+ export {};
+
+==== /project/e (0 errors) ====
+ export {};
+
+==== /project/main.ts (7 errors) ====
+ import {} from "./a";
+ ~~~~~
+!!! error TS2307: Cannot find module './a' or its corresponding type declarations.
+ import {} from "./a.js";
+ import {} from "./a.ts";
+
+ import {} from "./b";
+ ~~~~~
+!!! error TS2307: Cannot find module './b' or its corresponding type declarations.
+ import {} from "./b.js";
+ import {} from "./b.ts";
+ import {} from "./b.d.ts";
+ ~~~~~~~~~~
+!!! error TS2846: A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file './b.js' instead?
+ import type {} from "./b.d.ts";
+
+ import {} from "./c.ts";
+ import {} from "./c.tsx";
+ ~~~~~~~~~
+!!! error TS6142: Module './c.tsx' was resolved to '/project/c.tsx', but '--jsx' is not set.
+
+ import {} from "./d";
+ ~~~~~
+!!! error TS2307: Cannot find module './d' or its corresponding type declarations.
+ import {} from "./d/index";
+ ~~~~~~~~~~~
+!!! error TS2307: Cannot find module './d/index' or its corresponding type declarations.
+ import {} from "./d/index.ts";
+
+ import {} from "./e";
+ ~~~~~
+!!! error TS2307: Cannot find module './e' or its corresponding type declarations.
+
+==== /project/types.d.ts (2 errors) ====
+ import {} from "./a.ts";
+ import {} from "./a.d.ts";
+ ~~~~~~~~~~
+!!! error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './a.js' instead.
+ import type {} from "./a.d.ts";
+ ~~~~~~~~~~
+!!! error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './a.js' instead.
+
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=true).symbols b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=true).symbols
new file mode 100644
index 0000000000000..8087e521944d1
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=true).symbols
@@ -0,0 +1,44 @@
+=== /project/a.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.d.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.tsx ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/d/index.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/main.ts ===
+import {} from "./a";
+No type information for this code.import {} from "./a.js";
+No type information for this code.import {} from "./a.ts";
+No type information for this code.
+No type information for this code.import {} from "./b";
+No type information for this code.import {} from "./b.js";
+No type information for this code.import {} from "./b.ts";
+No type information for this code.import {} from "./b.d.ts";
+No type information for this code.import type {} from "./b.d.ts";
+No type information for this code.
+No type information for this code.import {} from "./c.ts";
+No type information for this code.import {} from "./c.tsx";
+No type information for this code.
+No type information for this code.import {} from "./d";
+No type information for this code.import {} from "./d/index";
+No type information for this code.import {} from "./d/index.ts";
+No type information for this code.
+No type information for this code.import {} from "./e";
+No type information for this code.
+No type information for this code.=== /project/types.d.ts ===
+import {} from "./a.ts";
+No type information for this code.import {} from "./a.d.ts";
+No type information for this code.import type {} from "./a.d.ts";
+No type information for this code.
+No type information for this code.
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=true).trace.json b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=true).trace.json
new file mode 100644
index 0000000000000..40a02fe86a714
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=true).trace.json
@@ -0,0 +1,68 @@
+[
+ "======== Resolving module './a' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './a' was not resolved. ========",
+ "======== Resolving module './a.js' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/a.js' has a '.js' extension - stripping it.",
+ "File '/project/a.ts' exist - use it as a name resolution result.",
+ "======== Module name './a.js' was successfully resolved to '/project/a.ts'. ========",
+ "======== Resolving module './a.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/a.ts' has a '.ts' extension - stripping it.",
+ "File '/project/a.ts' exist - use it as a name resolution result.",
+ "======== Module name './a.ts' was successfully resolved to '/project/a.ts'. ========",
+ "======== Resolving module './b' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './b' was not resolved. ========",
+ "======== Resolving module './b.js' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.js' has a '.js' extension - stripping it.",
+ "File '/project/b.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.js' was successfully resolved to '/project/b.ts'. ========",
+ "======== Resolving module './b.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.ts' has a '.ts' extension - stripping it.",
+ "File '/project/b.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.ts' was successfully resolved to '/project/b.ts'. ========",
+ "======== Resolving module './b.d.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.d.ts' has a '.d.ts' extension - stripping it.",
+ "File '/project/b.d.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.d.ts' was successfully resolved to '/project/b.d.ts'. ========",
+ "======== Resolving module './c.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/c.ts' has a '.ts' extension - stripping it.",
+ "File '/project/c.ts' exist - use it as a name resolution result.",
+ "======== Module name './c.ts' was successfully resolved to '/project/c.ts'. ========",
+ "======== Resolving module './c.tsx' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/c.tsx' has a '.tsx' extension - stripping it.",
+ "File '/project/c.tsx' exist - use it as a name resolution result.",
+ "======== Module name './c.tsx' was successfully resolved to '/project/c.tsx'. ========",
+ "======== Resolving module './d' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './d' was not resolved. ========",
+ "======== Resolving module './d/index' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './d/index' was not resolved. ========",
+ "======== Resolving module './d/index.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/d/index.ts' has a '.ts' extension - stripping it.",
+ "File '/project/d/index.ts' exist - use it as a name resolution result.",
+ "======== Module name './d/index.ts' was successfully resolved to '/project/d/index.ts'. ========",
+ "======== Resolving module './e' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './e' was not resolved. ========",
+ "======== Resolving module './a.ts' from '/project/types.d.ts'. ========",
+ "Resolution for module './a.ts' was found in cache from location '/project'.",
+ "======== Module name './a.ts' was successfully resolved to '/project/a.ts'. ========",
+ "======== Resolving module './a.d.ts' from '/project/types.d.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/a.d.ts' has a '.d.ts' extension - stripping it.",
+ "File '/project/a.d.ts' does not exist.",
+ "File name '/project/a.d.ts' has a '.d.ts' extension - stripping it.",
+ "File '/project/a.js' does not exist.",
+ "File '/project/a.jsx' does not exist.",
+ "======== Module name './a.d.ts' was not resolved. ========"
+]
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=true).types b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=true).types
new file mode 100644
index 0000000000000..8087e521944d1
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(allowimportingtsextensions=true,noemit=true).types
@@ -0,0 +1,44 @@
+=== /project/a.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.d.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.tsx ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/d/index.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/main.ts ===
+import {} from "./a";
+No type information for this code.import {} from "./a.js";
+No type information for this code.import {} from "./a.ts";
+No type information for this code.
+No type information for this code.import {} from "./b";
+No type information for this code.import {} from "./b.js";
+No type information for this code.import {} from "./b.ts";
+No type information for this code.import {} from "./b.d.ts";
+No type information for this code.import type {} from "./b.d.ts";
+No type information for this code.
+No type information for this code.import {} from "./c.ts";
+No type information for this code.import {} from "./c.tsx";
+No type information for this code.
+No type information for this code.import {} from "./d";
+No type information for this code.import {} from "./d/index";
+No type information for this code.import {} from "./d/index.ts";
+No type information for this code.
+No type information for this code.import {} from "./e";
+No type information for this code.
+No type information for this code.=== /project/types.d.ts ===
+import {} from "./a.ts";
+No type information for this code.import {} from "./a.d.ts";
+No type information for this code.import type {} from "./a.d.ts";
+No type information for this code.
+No type information for this code.
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(noemit=false).errors.txt b/tests/baselines/reference/minimal_relative(noemit=false).errors.txt
new file mode 100644
index 0000000000000..04640dbdd2934
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(noemit=false).errors.txt
@@ -0,0 +1,96 @@
+error TS5056: Cannot write file 'dist/c.js' because it would be overwritten by multiple input files.
+error TS6231: Could not resolve the path '/project/e' with the extensions: '.ts', '.tsx', '.d.ts', '.cts', '.d.cts', '.mts', '.d.mts'.
+ The file is in the program because:
+ Root file specified for compilation
+error TS6504: File '/project/b.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
+ The file is in the program because:
+ Root file specified for compilation
+/project/main.ts(1,16): error TS2307: Cannot find module './a' or its corresponding type declarations.
+/project/main.ts(3,16): error TS2691: An import path cannot end with a '.ts' extension. Consider importing './a.js' instead.
+/project/main.ts(5,16): error TS2307: Cannot find module './b' or its corresponding type declarations.
+/project/main.ts(7,16): error TS2691: An import path cannot end with a '.ts' extension. Consider importing './b.js' instead.
+/project/main.ts(8,16): error TS2845: A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file './b.js' instead?
+/project/main.ts(11,16): error TS2691: An import path cannot end with a '.ts' extension. Consider importing './c.js' instead.
+/project/main.ts(12,16): error TS2691: An import path cannot end with a '.tsx' extension. Consider importing './c.js' instead.
+/project/main.ts(12,16): error TS6142: Module './c.tsx' was resolved to '/project/c.tsx', but '--jsx' is not set.
+/project/main.ts(14,16): error TS2307: Cannot find module './d' or its corresponding type declarations.
+/project/main.ts(15,16): error TS2307: Cannot find module './d/index' or its corresponding type declarations.
+/project/main.ts(16,16): error TS2691: An import path cannot end with a '.ts' extension. Consider importing './d/index.js' instead.
+/project/main.ts(18,16): error TS2307: Cannot find module './e' or its corresponding type declarations.
+
+
+!!! error TS5056: Cannot write file 'dist/c.js' because it would be overwritten by multiple input files.
+!!! error TS6231: Could not resolve the path '/project/e' with the extensions: '.ts', '.tsx', '.d.ts', '.cts', '.d.cts', '.mts', '.d.mts'.
+!!! error TS6231: The file is in the program because:
+!!! error TS6231: Root file specified for compilation
+!!! error TS6504: File '/project/b.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
+!!! error TS6504: The file is in the program because:
+!!! error TS6504: Root file specified for compilation
+==== /project/a.ts (0 errors) ====
+ export {};
+
+==== /project/b.ts (0 errors) ====
+ export {};
+
+==== /project/b.js (0 errors) ====
+ export {};
+
+==== /project/b.d.ts (0 errors) ====
+ export {};
+
+==== /project/c.ts (0 errors) ====
+ export {};
+
+==== /project/c.tsx (0 errors) ====
+ export {};
+
+==== /project/d/index.ts (0 errors) ====
+ export {};
+
+==== /project/e (0 errors) ====
+ export {};
+
+==== /project/main.ts (12 errors) ====
+ import {} from "./a";
+ ~~~~~
+!!! error TS2307: Cannot find module './a' or its corresponding type declarations.
+ import {} from "./a.js";
+ import {} from "./a.ts";
+ ~~~~~~~~
+!!! error TS2691: An import path cannot end with a '.ts' extension. Consider importing './a.js' instead.
+
+ import {} from "./b";
+ ~~~~~
+!!! error TS2307: Cannot find module './b' or its corresponding type declarations.
+ import {} from "./b.js";
+ import {} from "./b.ts";
+ ~~~~~~~~
+!!! error TS2691: An import path cannot end with a '.ts' extension. Consider importing './b.js' instead.
+ import {} from "./b.d.ts";
+ ~~~~~~~~~~
+!!! error TS2845: A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file './b.js' instead?
+ import type {} from "./b.d.ts";
+
+ import {} from "./c.ts";
+ ~~~~~~~~
+!!! error TS2691: An import path cannot end with a '.ts' extension. Consider importing './c.js' instead.
+ import {} from "./c.tsx";
+ ~~~~~~~~~
+!!! error TS2691: An import path cannot end with a '.tsx' extension. Consider importing './c.js' instead.
+ ~~~~~~~~~
+!!! error TS6142: Module './c.tsx' was resolved to '/project/c.tsx', but '--jsx' is not set.
+
+ import {} from "./d";
+ ~~~~~
+!!! error TS2307: Cannot find module './d' or its corresponding type declarations.
+ import {} from "./d/index";
+ ~~~~~~~~~~~
+!!! error TS2307: Cannot find module './d/index' or its corresponding type declarations.
+ import {} from "./d/index.ts";
+ ~~~~~~~~~~~~~~
+!!! error TS2691: An import path cannot end with a '.ts' extension. Consider importing './d/index.js' instead.
+
+ import {} from "./e";
+ ~~~~~
+!!! error TS2307: Cannot find module './e' or its corresponding type declarations.
+
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(noemit=false).js b/tests/baselines/reference/minimal_relative(noemit=false).js
new file mode 100644
index 0000000000000..4044dbad4adb8
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(noemit=false).js
@@ -0,0 +1,59 @@
+//// [tests/cases/conformance/moduleResolution/minimal_relative.ts] ////
+
+//// [a.ts]
+export {};
+
+//// [b.ts]
+export {};
+
+//// [b.js]
+export {};
+
+//// [b.d.ts]
+export {};
+
+//// [c.ts]
+export {};
+
+//// [c.tsx]
+export {};
+
+//// [index.ts]
+export {};
+
+//// [e]
+export {};
+
+//// [main.ts]
+import {} from "./a";
+import {} from "./a.js";
+import {} from "./a.ts";
+
+import {} from "./b";
+import {} from "./b.js";
+import {} from "./b.ts";
+import {} from "./b.d.ts";
+import type {} from "./b.d.ts";
+
+import {} from "./c.ts";
+import {} from "./c.tsx";
+
+import {} from "./d";
+import {} from "./d/index";
+import {} from "./d/index.ts";
+
+import {} from "./e";
+
+
+//// [a.js]
+"use strict";
+exports.__esModule = true;
+//// [b.js]
+"use strict";
+exports.__esModule = true;
+//// [index.js]
+"use strict";
+exports.__esModule = true;
+//// [main.js]
+"use strict";
+exports.__esModule = true;
diff --git a/tests/baselines/reference/minimal_relative(noemit=false).symbols b/tests/baselines/reference/minimal_relative(noemit=false).symbols
new file mode 100644
index 0000000000000..13a097c71c1b7
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(noemit=false).symbols
@@ -0,0 +1,39 @@
+=== /project/a.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.d.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.tsx ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/d/index.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/main.ts ===
+import {} from "./a";
+No type information for this code.import {} from "./a.js";
+No type information for this code.import {} from "./a.ts";
+No type information for this code.
+No type information for this code.import {} from "./b";
+No type information for this code.import {} from "./b.js";
+No type information for this code.import {} from "./b.ts";
+No type information for this code.import {} from "./b.d.ts";
+No type information for this code.import type {} from "./b.d.ts";
+No type information for this code.
+No type information for this code.import {} from "./c.ts";
+No type information for this code.import {} from "./c.tsx";
+No type information for this code.
+No type information for this code.import {} from "./d";
+No type information for this code.import {} from "./d/index";
+No type information for this code.import {} from "./d/index.ts";
+No type information for this code.
+No type information for this code.import {} from "./e";
+No type information for this code.
+No type information for this code.
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(noemit=false).trace.json b/tests/baselines/reference/minimal_relative(noemit=false).trace.json
new file mode 100644
index 0000000000000..33784890cf65f
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(noemit=false).trace.json
@@ -0,0 +1,57 @@
+[
+ "======== Resolving module './a' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './a' was not resolved. ========",
+ "======== Resolving module './a.js' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/a.js' has a '.js' extension - stripping it.",
+ "File '/project/a.ts' exist - use it as a name resolution result.",
+ "======== Module name './a.js' was successfully resolved to '/project/a.ts'. ========",
+ "======== Resolving module './a.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/a.ts' has a '.ts' extension - stripping it.",
+ "File '/project/a.ts' exist - use it as a name resolution result.",
+ "======== Module name './a.ts' was successfully resolved to '/project/a.ts'. ========",
+ "======== Resolving module './b' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './b' was not resolved. ========",
+ "======== Resolving module './b.js' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.js' has a '.js' extension - stripping it.",
+ "File '/project/b.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.js' was successfully resolved to '/project/b.ts'. ========",
+ "======== Resolving module './b.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.ts' has a '.ts' extension - stripping it.",
+ "File '/project/b.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.ts' was successfully resolved to '/project/b.ts'. ========",
+ "======== Resolving module './b.d.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.d.ts' has a '.d.ts' extension - stripping it.",
+ "File '/project/b.d.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.d.ts' was successfully resolved to '/project/b.d.ts'. ========",
+ "======== Resolving module './c.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/c.ts' has a '.ts' extension - stripping it.",
+ "File '/project/c.ts' exist - use it as a name resolution result.",
+ "======== Module name './c.ts' was successfully resolved to '/project/c.ts'. ========",
+ "======== Resolving module './c.tsx' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/c.tsx' has a '.tsx' extension - stripping it.",
+ "File '/project/c.tsx' exist - use it as a name resolution result.",
+ "======== Module name './c.tsx' was successfully resolved to '/project/c.tsx'. ========",
+ "======== Resolving module './d' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './d' was not resolved. ========",
+ "======== Resolving module './d/index' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './d/index' was not resolved. ========",
+ "======== Resolving module './d/index.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/d/index.ts' has a '.ts' extension - stripping it.",
+ "File '/project/d/index.ts' exist - use it as a name resolution result.",
+ "======== Module name './d/index.ts' was successfully resolved to '/project/d/index.ts'. ========",
+ "======== Resolving module './e' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './e' was not resolved. ========"
+]
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(noemit=false).types b/tests/baselines/reference/minimal_relative(noemit=false).types
new file mode 100644
index 0000000000000..13a097c71c1b7
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(noemit=false).types
@@ -0,0 +1,39 @@
+=== /project/a.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.d.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.tsx ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/d/index.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/main.ts ===
+import {} from "./a";
+No type information for this code.import {} from "./a.js";
+No type information for this code.import {} from "./a.ts";
+No type information for this code.
+No type information for this code.import {} from "./b";
+No type information for this code.import {} from "./b.js";
+No type information for this code.import {} from "./b.ts";
+No type information for this code.import {} from "./b.d.ts";
+No type information for this code.import type {} from "./b.d.ts";
+No type information for this code.
+No type information for this code.import {} from "./c.ts";
+No type information for this code.import {} from "./c.tsx";
+No type information for this code.
+No type information for this code.import {} from "./d";
+No type information for this code.import {} from "./d/index";
+No type information for this code.import {} from "./d/index.ts";
+No type information for this code.
+No type information for this code.import {} from "./e";
+No type information for this code.
+No type information for this code.
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(noemit=true).errors.txt b/tests/baselines/reference/minimal_relative(noemit=true).errors.txt
new file mode 100644
index 0000000000000..b5584db1abe5f
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(noemit=true).errors.txt
@@ -0,0 +1,79 @@
+error TS6231: Could not resolve the path '/project/e' with the extensions: '.ts', '.tsx', '.d.ts', '.cts', '.d.cts', '.mts', '.d.mts'.
+ The file is in the program because:
+ Root file specified for compilation
+error TS6504: File '/project/b.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
+ The file is in the program because:
+ Root file specified for compilation
+/project/main.ts(1,16): error TS2307: Cannot find module './a' or its corresponding type declarations.
+/project/main.ts(5,16): error TS2307: Cannot find module './b' or its corresponding type declarations.
+/project/main.ts(8,16): error TS2845: A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file './b.js' instead?
+/project/main.ts(12,16): error TS6142: Module './c.tsx' was resolved to '/project/c.tsx', but '--jsx' is not set.
+/project/main.ts(14,16): error TS2307: Cannot find module './d' or its corresponding type declarations.
+/project/main.ts(15,16): error TS2307: Cannot find module './d/index' or its corresponding type declarations.
+/project/main.ts(18,16): error TS2307: Cannot find module './e' or its corresponding type declarations.
+
+
+!!! error TS6231: Could not resolve the path '/project/e' with the extensions: '.ts', '.tsx', '.d.ts', '.cts', '.d.cts', '.mts', '.d.mts'.
+!!! error TS6231: The file is in the program because:
+!!! error TS6231: Root file specified for compilation
+!!! error TS6504: File '/project/b.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
+!!! error TS6504: The file is in the program because:
+!!! error TS6504: Root file specified for compilation
+==== /project/a.ts (0 errors) ====
+ export {};
+
+==== /project/b.ts (0 errors) ====
+ export {};
+
+==== /project/b.js (0 errors) ====
+ export {};
+
+==== /project/b.d.ts (0 errors) ====
+ export {};
+
+==== /project/c.ts (0 errors) ====
+ export {};
+
+==== /project/c.tsx (0 errors) ====
+ export {};
+
+==== /project/d/index.ts (0 errors) ====
+ export {};
+
+==== /project/e (0 errors) ====
+ export {};
+
+==== /project/main.ts (7 errors) ====
+ import {} from "./a";
+ ~~~~~
+!!! error TS2307: Cannot find module './a' or its corresponding type declarations.
+ import {} from "./a.js";
+ import {} from "./a.ts";
+
+ import {} from "./b";
+ ~~~~~
+!!! error TS2307: Cannot find module './b' or its corresponding type declarations.
+ import {} from "./b.js";
+ import {} from "./b.ts";
+ import {} from "./b.d.ts";
+ ~~~~~~~~~~
+!!! error TS2845: A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file './b.js' instead?
+ import type {} from "./b.d.ts";
+
+ import {} from "./c.ts";
+ import {} from "./c.tsx";
+ ~~~~~~~~~
+!!! error TS6142: Module './c.tsx' was resolved to '/project/c.tsx', but '--jsx' is not set.
+
+ import {} from "./d";
+ ~~~~~
+!!! error TS2307: Cannot find module './d' or its corresponding type declarations.
+ import {} from "./d/index";
+ ~~~~~~~~~~~
+!!! error TS2307: Cannot find module './d/index' or its corresponding type declarations.
+ import {} from "./d/index.ts";
+
+ import {} from "./e";
+ ~~~~~
+!!! error TS2307: Cannot find module './e' or its corresponding type declarations.
+
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(noemit=true).symbols b/tests/baselines/reference/minimal_relative(noemit=true).symbols
new file mode 100644
index 0000000000000..13a097c71c1b7
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(noemit=true).symbols
@@ -0,0 +1,39 @@
+=== /project/a.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.d.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.tsx ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/d/index.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/main.ts ===
+import {} from "./a";
+No type information for this code.import {} from "./a.js";
+No type information for this code.import {} from "./a.ts";
+No type information for this code.
+No type information for this code.import {} from "./b";
+No type information for this code.import {} from "./b.js";
+No type information for this code.import {} from "./b.ts";
+No type information for this code.import {} from "./b.d.ts";
+No type information for this code.import type {} from "./b.d.ts";
+No type information for this code.
+No type information for this code.import {} from "./c.ts";
+No type information for this code.import {} from "./c.tsx";
+No type information for this code.
+No type information for this code.import {} from "./d";
+No type information for this code.import {} from "./d/index";
+No type information for this code.import {} from "./d/index.ts";
+No type information for this code.
+No type information for this code.import {} from "./e";
+No type information for this code.
+No type information for this code.
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(noemit=true).trace.json b/tests/baselines/reference/minimal_relative(noemit=true).trace.json
new file mode 100644
index 0000000000000..33784890cf65f
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(noemit=true).trace.json
@@ -0,0 +1,57 @@
+[
+ "======== Resolving module './a' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './a' was not resolved. ========",
+ "======== Resolving module './a.js' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/a.js' has a '.js' extension - stripping it.",
+ "File '/project/a.ts' exist - use it as a name resolution result.",
+ "======== Module name './a.js' was successfully resolved to '/project/a.ts'. ========",
+ "======== Resolving module './a.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/a.ts' has a '.ts' extension - stripping it.",
+ "File '/project/a.ts' exist - use it as a name resolution result.",
+ "======== Module name './a.ts' was successfully resolved to '/project/a.ts'. ========",
+ "======== Resolving module './b' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './b' was not resolved. ========",
+ "======== Resolving module './b.js' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.js' has a '.js' extension - stripping it.",
+ "File '/project/b.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.js' was successfully resolved to '/project/b.ts'. ========",
+ "======== Resolving module './b.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.ts' has a '.ts' extension - stripping it.",
+ "File '/project/b.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.ts' was successfully resolved to '/project/b.ts'. ========",
+ "======== Resolving module './b.d.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/b.d.ts' has a '.d.ts' extension - stripping it.",
+ "File '/project/b.d.ts' exist - use it as a name resolution result.",
+ "======== Module name './b.d.ts' was successfully resolved to '/project/b.d.ts'. ========",
+ "======== Resolving module './c.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/c.ts' has a '.ts' extension - stripping it.",
+ "File '/project/c.ts' exist - use it as a name resolution result.",
+ "======== Module name './c.ts' was successfully resolved to '/project/c.ts'. ========",
+ "======== Resolving module './c.tsx' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/c.tsx' has a '.tsx' extension - stripping it.",
+ "File '/project/c.tsx' exist - use it as a name resolution result.",
+ "======== Module name './c.tsx' was successfully resolved to '/project/c.tsx'. ========",
+ "======== Resolving module './d' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './d' was not resolved. ========",
+ "======== Resolving module './d/index' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './d/index' was not resolved. ========",
+ "======== Resolving module './d/index.ts' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "File name '/project/d/index.ts' has a '.ts' extension - stripping it.",
+ "File '/project/d/index.ts' exist - use it as a name resolution result.",
+ "======== Module name './d/index.ts' was successfully resolved to '/project/d/index.ts'. ========",
+ "======== Resolving module './e' from '/project/main.ts'. ========",
+ "Explicitly specified module resolution kind: 'Minimal'.",
+ "======== Module name './e' was not resolved. ========"
+]
\ No newline at end of file
diff --git a/tests/baselines/reference/minimal_relative(noemit=true).types b/tests/baselines/reference/minimal_relative(noemit=true).types
new file mode 100644
index 0000000000000..13a097c71c1b7
--- /dev/null
+++ b/tests/baselines/reference/minimal_relative(noemit=true).types
@@ -0,0 +1,39 @@
+=== /project/a.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/b.d.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/c.tsx ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/d/index.ts ===
+export {};
+No type information for this code.
+No type information for this code.=== /project/main.ts ===
+import {} from "./a";
+No type information for this code.import {} from "./a.js";
+No type information for this code.import {} from "./a.ts";
+No type information for this code.
+No type information for this code.import {} from "./b";
+No type information for this code.import {} from "./b.js";
+No type information for this code.import {} from "./b.ts";
+No type information for this code.import {} from "./b.d.ts";
+No type information for this code.import type {} from "./b.d.ts";
+No type information for this code.
+No type information for this code.import {} from "./c.ts";
+No type information for this code.import {} from "./c.tsx";
+No type information for this code.
+No type information for this code.import {} from "./d";
+No type information for this code.import {} from "./d/index";
+No type information for this code.import {} from "./d/index.ts";
+No type information for this code.
+No type information for this code.import {} from "./e";
+No type information for this code.
+No type information for this code.
\ No newline at end of file
diff --git a/tests/baselines/reference/showConfig/Shows tsconfig for single option/allowImportingTsExtensions/tsconfig.json b/tests/baselines/reference/showConfig/Shows tsconfig for single option/allowImportingTsExtensions/tsconfig.json
new file mode 100644
index 0000000000000..88c95f9eb8307
--- /dev/null
+++ b/tests/baselines/reference/showConfig/Shows tsconfig for single option/allowImportingTsExtensions/tsconfig.json
@@ -0,0 +1,5 @@
+{
+ "compilerOptions": {
+ "allowImportingTsExtensions": true
+ }
+}
diff --git a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json
index 75dcaeac2e2b9..5cad175ba34fa 100644
--- a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json
+++ b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json
@@ -35,6 +35,7 @@
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with --help/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with --help/tsconfig.json
index 75dcaeac2e2b9..5cad175ba34fa 100644
--- a/tests/baselines/reference/tsConfig/Initialized TSConfig with --help/tsconfig.json
+++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with --help/tsconfig.json
@@ -35,6 +35,7 @@
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with --watch/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with --watch/tsconfig.json
index 75dcaeac2e2b9..5cad175ba34fa 100644
--- a/tests/baselines/reference/tsConfig/Initialized TSConfig with --watch/tsconfig.json
+++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with --watch/tsconfig.json
@@ -35,6 +35,7 @@
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json
index ce36f2a0fcfd7..e1b9e67e7b66d 100644
--- a/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json
+++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json
@@ -35,6 +35,7 @@
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json
index a4be57dd3410e..cc29170683efb 100644
--- a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json
+++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json
@@ -35,6 +35,7 @@
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json
index faa350ae98575..0b6e055e0a2cd 100644
--- a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json
+++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json
@@ -35,6 +35,7 @@
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json
index 09587994ffbcd..01830a8f79b49 100644
--- a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json
+++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json
@@ -35,6 +35,7 @@
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json
index abb2dfd47088b..6798430ea05ee 100644
--- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json
+++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json
@@ -35,6 +35,7 @@
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json
index 75dcaeac2e2b9..5cad175ba34fa 100644
--- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json
+++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json
@@ -35,6 +35,7 @@
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json
index 04aa9196bfc65..6bae69884ebdb 100644
--- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json
+++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json
@@ -35,6 +35,7 @@
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json
index 4eb9bb8aa4b84..c6de1fdcc3575 100644
--- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json
+++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json
@@ -35,6 +35,7 @@
"types": ["jquery","mocha"], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js
index 2cf43a8189e28..782dc8bc57911 100644
--- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js
+++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js
@@ -56,6 +56,7 @@ interface Array { length: number; [n: number]: T; }
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js
index 0bdc2d356c5e3..54e482fe2570b 100644
--- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js
+++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js
@@ -56,6 +56,7 @@ interface Array { length: number; [n: number]: T; }
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js
index 673a8e6669886..5b88985795b6e 100644
--- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js
+++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js
@@ -56,6 +56,7 @@ interface Array { length: number; [n: number]: T; }
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js
index 83e6548b002fb..482495d68b2c7 100644
--- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js
+++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js
@@ -56,6 +56,7 @@ interface Array { length: number; [n: number]: T; }
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js
index c87baf238012c..a80a8e8c3c89e 100644
--- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js
+++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js
@@ -56,6 +56,7 @@ interface Array { length: number; [n: number]: T; }
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js
index 82310b617cd3d..b1b8e8a3eaedf 100644
--- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js
+++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js
@@ -56,6 +56,7 @@ interface Array { length: number; [n: number]: T; }
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution minimal' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
diff --git a/tests/cases/conformance/moduleResolution/minimal_nodeModules.ts b/tests/cases/conformance/moduleResolution/minimal_nodeModules.ts
new file mode 100644
index 0000000000000..1ddb7f9153345
--- /dev/null
+++ b/tests/cases/conformance/moduleResolution/minimal_nodeModules.ts
@@ -0,0 +1,16 @@
+// @moduleResolution: minimal
+
+// @Filename: /node_modules/foo/index.d.ts
+import {} from "./other.js";
+export {};
+
+// @Filename: /node_modules/foo/other.d.ts
+export {};
+
+// @Filename: /node_modules/@types/foo/index.d.ts
+export {};
+
+// @Filename: /main.ts
+import {} from "foo";
+import {} from "./node_modules/foo/index.js";
+import type {} from "./node_modules/@types/foo/index.d.ts";
diff --git a/tests/cases/conformance/moduleResolution/minimal_nodeModules_declarationEmit.ts b/tests/cases/conformance/moduleResolution/minimal_nodeModules_declarationEmit.ts
new file mode 100644
index 0000000000000..b621aeab6431f
--- /dev/null
+++ b/tests/cases/conformance/moduleResolution/minimal_nodeModules_declarationEmit.ts
@@ -0,0 +1,14 @@
+// @moduleResolution: minimal
+// @declaration: true
+
+// @Filename: /node_modules/foo/module.d.ts
+export declare class SomeExportedClass {
+ private foo: any;
+}
+
+declare global {
+ function returnsPrivateClassOhNo(): SomeExportedClass;
+}
+
+// @Filename: /main.ts
+export const boom = returnsPrivateClassOhNo();
diff --git a/tests/cases/conformance/moduleResolution/minimal_nonRelative.ts b/tests/cases/conformance/moduleResolution/minimal_nonRelative.ts
new file mode 100644
index 0000000000000..e055574fc2739
--- /dev/null
+++ b/tests/cases/conformance/moduleResolution/minimal_nonRelative.ts
@@ -0,0 +1,14 @@
+// @moduleResolution: minimal
+// @noEmit: true
+// @traceResolution: true
+// @noTypesAndSymbols: true
+
+// @Filename: /node_modules/@types/foo/index.d.ts
+export {};
+
+// @Filename: /node_modules/bar/index.d.ts
+export {};
+
+// @Filename: /main.ts
+import {} from "foo";
+import {} from "bar";
diff --git a/tests/cases/conformance/moduleResolution/minimal_pathsAndBaseUrl.ts b/tests/cases/conformance/moduleResolution/minimal_pathsAndBaseUrl.ts
new file mode 100644
index 0000000000000..74ae8ffcde21e
--- /dev/null
+++ b/tests/cases/conformance/moduleResolution/minimal_pathsAndBaseUrl.ts
@@ -0,0 +1,36 @@
+// @traceResolution: true
+// @noTypesAndSymbols: true
+
+// @Filename: /tsconfig.json
+{
+ "compilerOptions": {
+ "moduleResolution": "minimal",
+ "noEmit": true,
+ "allowImportingTsExtensions": true,
+ "baseUrl": ".",
+ "paths": {
+ "*": [
+ "*",
+ "./vendor/*",
+ "./vendor/*/index.d.ts",
+ "./apps/*"
+ ]
+ }
+ }
+}
+
+// @Filename: /vendor/foo/index.d.ts
+export {};
+
+// @Filename: /apps/hello.ts
+export {};
+
+// @Filename: /foo.ts
+export {};
+
+// @Filename: /main.ts
+import {} from "foo";
+import {} from "foo/index.js";
+import {} from "hello.ts";
+import {} from "hello";
+import {} from "foo.js";
diff --git a/tests/cases/conformance/moduleResolution/minimal_relative.ts b/tests/cases/conformance/moduleResolution/minimal_relative.ts
new file mode 100644
index 0000000000000..21eb4828223f5
--- /dev/null
+++ b/tests/cases/conformance/moduleResolution/minimal_relative.ts
@@ -0,0 +1,54 @@
+// @moduleResolution: minimal
+// @outDir: dist
+// @noEmit: true,false
+// @allowImportingTsExtensions: true,false
+// @traceResolution: true
+
+// @Filename: /project/a.ts
+export {};
+
+// @Filename: /project/b.ts
+export {};
+
+// @Filename: /project/b.js
+export {};
+
+// @Filename: /project/b.d.ts
+export {};
+
+// @Filename: /project/c.ts
+export {};
+
+// @Filename: /project/c.tsx
+export {};
+
+// @Filename: /project/d/index.ts
+export {};
+
+// @Filename: /project/e
+export {};
+
+// @Filename: /project/main.ts
+import {} from "./a";
+import {} from "./a.js";
+import {} from "./a.ts";
+
+import {} from "./b";
+import {} from "./b.js";
+import {} from "./b.ts";
+import {} from "./b.d.ts";
+import type {} from "./b.d.ts";
+
+import {} from "./c.ts";
+import {} from "./c.tsx";
+
+import {} from "./d";
+import {} from "./d/index";
+import {} from "./d/index.ts";
+
+import {} from "./e";
+
+// @Filename: /project/types.d.ts
+import {} from "./a.ts";
+import {} from "./a.d.ts";
+import type {} from "./a.d.ts";
diff --git a/tests/cases/fourslash/autoImportsMinimal1.ts b/tests/cases/fourslash/autoImportsMinimal1.ts
new file mode 100644
index 0000000000000..1796a03b00f28
--- /dev/null
+++ b/tests/cases/fourslash/autoImportsMinimal1.ts
@@ -0,0 +1,20 @@
+///
+
+// @moduleResolution: minimal
+
+// @Filename: /node_modules/@types/foo/index.d.ts
+//// export const fromAtTypesFoo: number;
+
+// @Filename: /node_modules/bar/index.d.ts
+//// export const fromBar: number;
+
+// @Filename: /local.ts
+//// export const fromLocal: number;
+
+// @Filename: /Component.tsx
+//// export function Component() { return null; }
+
+// @Filename: /main.ts
+//// /**/
+
+verify.baselineAutoImports("");
diff --git a/tests/cases/fourslash/autoImportsMinimal2.ts b/tests/cases/fourslash/autoImportsMinimal2.ts
new file mode 100644
index 0000000000000..c98a84aa859be
--- /dev/null
+++ b/tests/cases/fourslash/autoImportsMinimal2.ts
@@ -0,0 +1,22 @@
+///
+
+// @moduleResolution: minimal
+// @allowImportingTsExtensions: true
+// @noEmit: true
+
+// @Filename: /node_modules/@types/foo/index.d.ts
+//// export const fromAtTypesFoo: number;
+
+// @Filename: /node_modules/bar/index.d.ts
+//// export const fromBar: number;
+
+// @Filename: /local.ts
+//// export const fromLocal: number;
+
+// @Filename: /Component.tsx
+//// export function Component() { return null; }
+
+// @Filename: /main.ts
+//// /**/
+
+verify.baselineAutoImports("");
diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts
index 76ca5d33314d7..058632b616992 100644
--- a/tests/cases/fourslash/fourslash.ts
+++ b/tests/cases/fourslash/fourslash.ts
@@ -370,6 +370,7 @@ declare namespace FourSlashInterface {
getAndApplyCodeFix(errorCode?: number, index?: number): void;
importFixAtPosition(expectedTextArray: string[], errorCode?: number, options?: UserPreferences): void;
importFixModuleSpecifiers(marker: string, moduleSpecifiers: string[], options?: UserPreferences): void;
+ baselineAutoImports(marker: string, options?: UserPreferences): void;
navigationBar(json: any, options?: { checkSpans?: boolean }): void;
navigationTree(json: any, options?: { checkSpans?: boolean }): void;
diff --git a/tests/cases/fourslash/pathCompletionsMinimal1.ts b/tests/cases/fourslash/pathCompletionsMinimal1.ts
new file mode 100644
index 0000000000000..a3843b535f648
--- /dev/null
+++ b/tests/cases/fourslash/pathCompletionsMinimal1.ts
@@ -0,0 +1,31 @@
+///
+
+// @moduleResolution: minimal
+
+// @Filename: /project/node_modules/@types/foo/index.d.ts
+//// export const fromAtTypesFoo: number;
+
+// @Filename: /project/node_modules/bar/index.d.ts
+//// export const fromBar: number;
+
+// @Filename: /project/local.ts
+//// export const fromLocal: number;
+
+// @Filename: /project/Component.tsx
+//// export function Component() { return null; }
+
+// @Filename: /project/main.ts
+//// import {} from "/**/";
+
+verify.completions({
+ isNewIdentifierLocation: true,
+ marker: "",
+ exact: []
+});
+
+edit.insert("./");
+
+verify.completions({
+ isNewIdentifierLocation: true,
+ exact: ["Component.js", "local.js"],
+});
diff --git a/tests/cases/fourslash/pathCompletionsMinimal2.ts b/tests/cases/fourslash/pathCompletionsMinimal2.ts
new file mode 100644
index 0000000000000..e9a27356b02b3
--- /dev/null
+++ b/tests/cases/fourslash/pathCompletionsMinimal2.ts
@@ -0,0 +1,33 @@
+///
+
+// @moduleResolution: minimal
+// @allowImportingTsExtensions: true
+// @noEmit: true
+
+// @Filename: /project/node_modules/@types/foo/index.d.ts
+//// export const fromAtTypesFoo: number;
+
+// @Filename: /project/node_modules/bar/index.d.ts
+//// export const fromBar: number;
+
+// @Filename: /project/local.ts
+//// export const fromLocal: number;
+
+// @Filename: /project/Component.tsx
+//// export function Component() { return null; }
+
+// @Filename: /project/main.ts
+//// import {} from "/**/";
+
+verify.completions({
+ isNewIdentifierLocation: true,
+ marker: "",
+ exact: []
+});
+
+edit.insert("./");
+
+verify.completions({
+ isNewIdentifierLocation: true,
+ exact: ["Component.tsx", "local.ts"],
+});