Skip to content

Commit 6b1da23

Browse files
committed
Merge branch 'module-resolution/esm-types-resolution-diagnostic' into try-bundler
2 parents 33a3d9f + fd1ad49 commit 6b1da23

7 files changed

+482
-41
lines changed

src/compiler/checker.ts

+26-39
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,6 @@ import {
311311
getOwnKeys,
312312
getParameterSymbolFromJSDoc,
313313
getParseTreeNode,
314-
getPathComponents,
315314
getPropertyAssignmentAliasLikeExpression,
316315
getPropertyNameForPropertyNameNode,
317316
getResolutionDiagnostic,
@@ -4767,7 +4766,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
47674766

47684767
if (sourceFile.symbol) {
47694768
if (resolvedModule.isExternalLibraryImport && !resolutionExtensionIsTSOrJson(resolvedModule.extension)) {
4770-
errorOnImplicitAnyModule(/*isError*/ false, errorNode, resolvedModule, moduleReference);
4769+
errorOnImplicitAnyModule(/*isError*/ false, errorNode, currentSourceFile, mode, resolvedModule, moduleReference);
47714770
}
47724771
if (moduleResolutionKind === ModuleResolutionKind.Node16 || moduleResolutionKind === ModuleResolutionKind.NodeNext) {
47734772
const isSyncImport = (currentSourceFile.impliedNodeFormat === ModuleKind.CommonJS && !findAncestor(location, isImportCall)) || !!findAncestor(location, isImportEqualsDeclaration);
@@ -4855,7 +4854,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
48554854
error(errorNode, diag, moduleReference, resolvedModule!.resolvedFileName);
48564855
}
48574856
else {
4858-
errorOnImplicitAnyModule(/*isError*/ noImplicitAny && !!moduleNotFoundError, errorNode, resolvedModule!, moduleReference);
4857+
errorOnImplicitAnyModule(/*isError*/ noImplicitAny && !!moduleNotFoundError, errorNode, currentSourceFile, mode, resolvedModule!, moduleReference);
48594858
}
48604859
// Failed imports and untyped modules are both treated in an untyped manner; only difference is whether we give a diagnostic first.
48614860
return undefined;
@@ -4901,27 +4900,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
49014900
}
49024901
}
49034902
else {
4904-
const legacyResult = currentSourceFile.resolvedModules?.get(moduleReference, mode)?.legacyResult;
4905-
if (legacyResult) {
4906-
const isInTypesScope = legacyResult.indexOf(nodeModulesPathPart + "@types/") > -1;
4907-
const moduleNameParts = getPathComponents(moduleReference);
4908-
moduleNameParts.shift(); // Empty string for nonrelative module name
4909-
if (moduleNameParts.length > 1 && moduleNameParts[0] === "@types") {
4910-
moduleNameParts.shift();
4911-
}
4912-
const isScopedLibrary = moduleNameParts.length > 1 && startsWith(moduleNameParts[0], "@");
4913-
const libraryName = isScopedLibrary ? `${moduleNameParts[0]}/${moduleNameParts[1]}` : moduleNameParts[0];
4914-
const details = chainDiagnosticMessages(
4915-
/*details*/ undefined,
4916-
Diagnostics.There_are_types_at_0_but_this_result_could_not_be_resolved_when_respecting_package_json_exports_The_1_library_may_need_to_update_its_package_json,
4917-
legacyResult,
4918-
isInTypesScope ? `@types/${mangleScopedPackageName(libraryName)}` : libraryName
4919-
);
4920-
diagnostics.add(createDiagnosticForNodeFromMessageChain(errorNode, chainDiagnosticMessages(details, moduleNotFoundError, moduleReference)));
4921-
}
4922-
else {
4923-
error(errorNode, moduleNotFoundError, moduleReference);
4924-
}
4903+
error(errorNode, moduleNotFoundError, moduleReference);
49254904
}
49264905
}
49274906
}
@@ -4945,25 +4924,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
49454924
}
49464925
}
49474926

4948-
function errorOnImplicitAnyModule(isError: boolean, errorNode: Node, { packageId, resolvedFileName }: ResolvedModuleFull, moduleReference: string): void {
4949-
const errorInfo = !isExternalModuleNameRelative(moduleReference) && packageId
4950-
? typesPackageExists(packageId.name)
4927+
function errorOnImplicitAnyModule(isError: boolean, errorNode: Node, sourceFile: SourceFile, mode: ResolutionMode, { packageId, resolvedFileName }: ResolvedModuleFull, moduleReference: string): void {
4928+
let errorInfo;
4929+
if (!isExternalModuleNameRelative(moduleReference) && packageId) {
4930+
const legacyResult = sourceFile.resolvedModules?.get(moduleReference, mode)?.legacyResult;
4931+
errorInfo = legacyResult
49514932
? chainDiagnosticMessages(
49524933
/*details*/ undefined,
4953-
Diagnostics.If_the_0_package_actually_exposes_this_module_consider_sending_a_pull_request_to_amend_https_Colon_Slash_Slashgithub_com_SlashDefinitelyTyped_SlashDefinitelyTyped_Slashtree_Slashmaster_Slashtypes_Slash_1,
4954-
packageId.name, mangleScopedPackageName(packageId.name))
4955-
: packageBundlesTypes(packageId.name)
4934+
Diagnostics.There_are_types_at_0_but_this_result_could_not_be_resolved_when_respecting_package_json_exports_The_1_library_may_need_to_update_its_package_json,
4935+
legacyResult,
4936+
legacyResult.indexOf(nodeModulesPathPart + "@types/") > -1 ? `@types/${mangleScopedPackageName(packageId.name)}` : packageId.name)
4937+
: typesPackageExists(packageId.name)
49564938
? chainDiagnosticMessages(
49574939
/*details*/ undefined,
4958-
Diagnostics.If_the_0_package_actually_exposes_this_module_try_adding_a_new_declaration_d_ts_file_containing_declare_module_1,
4959-
packageId.name,
4960-
moduleReference)
4961-
: chainDiagnosticMessages(
4962-
/*details*/ undefined,
4963-
Diagnostics.Try_npm_i_save_dev_types_Slash_1_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0,
4964-
moduleReference,
4965-
mangleScopedPackageName(packageId.name))
4966-
: undefined;
4940+
Diagnostics.If_the_0_package_actually_exposes_this_module_consider_sending_a_pull_request_to_amend_https_Colon_Slash_Slashgithub_com_SlashDefinitelyTyped_SlashDefinitelyTyped_Slashtree_Slashmaster_Slashtypes_Slash_1,
4941+
packageId.name, mangleScopedPackageName(packageId.name))
4942+
: packageBundlesTypes(packageId.name)
4943+
? chainDiagnosticMessages(
4944+
/*details*/ undefined,
4945+
Diagnostics.If_the_0_package_actually_exposes_this_module_try_adding_a_new_declaration_d_ts_file_containing_declare_module_1,
4946+
packageId.name,
4947+
moduleReference)
4948+
: chainDiagnosticMessages(
4949+
/*details*/ undefined,
4950+
Diagnostics.Try_npm_i_save_dev_types_Slash_1_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0,
4951+
moduleReference,
4952+
mangleScopedPackageName(packageId.name));
4953+
}
49674954
errorOrSuggestion(isError, errorNode, chainDiagnosticMessages(
49684955
errorInfo,
49694956
Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type,

src/compiler/moduleNameResolver.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -1675,10 +1675,17 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa
16751675
result = tryResolve(extensions, state);
16761676
}
16771677

1678-
// For non-relative names that failed to resolve in modes that look up an "import" condition in package.json "exports",
1678+
// For non-relative names that resolved to JS but no types in modes that look up an "import" condition in package.json "exports",
16791679
// try again with "exports" disabled to try to detect if this is likely a configuration error in a dependency's package.json.
16801680
let legacyResult;
1681-
if (!result && !isConfigLookup && !isExternalModuleNameRelative(moduleName) && features & NodeResolutionFeatures.Exports && conditions.indexOf("import") > -1) {
1681+
if (result?.value?.isExternalLibraryImport
1682+
&& !isConfigLookup
1683+
&& extensions & (Extensions.TypeScript | Extensions.Declaration)
1684+
&& features & NodeResolutionFeatures.Exports
1685+
&& !isExternalModuleNameRelative(moduleName)
1686+
&& !extensionIsOk(Extensions.TypeScript | Extensions.Declaration, result.value.resolved.extension)
1687+
&& conditions.indexOf("import") > -1
1688+
) {
16821689
traceIfEnabled(state, Diagnostics.Resolution_of_non_relative_name_failed_trying_with_modern_Node_resolution_features_disabled_to_see_if_npm_library_needs_configuration_update);
16831690
const diagnosticState = {
16841691
...state,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
error TS6504: File '/node_modules/bar/index.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
2+
The file is in the program because:
3+
Root file specified for compilation
4+
error TS6504: File '/node_modules/bar/index.mjs' is a JavaScript file. Did you mean to enable the 'allowJs' option?
5+
The file is in the program because:
6+
Root file specified for compilation
7+
error TS6504: File '/node_modules/foo/index.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
8+
The file is in the program because:
9+
Root file specified for compilation
10+
error TS6504: File '/node_modules/foo/index.mjs' is a JavaScript file. Did you mean to enable the 'allowJs' option?
11+
The file is in the program because:
12+
Root file specified for compilation
13+
/index.mts(1,21): error TS7016: Could not find a declaration file for module 'foo'. '/node_modules/foo/index.mjs' implicitly has an 'any' type.
14+
There are types at '/node_modules/foo/index.d.ts', but this result could not be resolved when respecting package.json "exports". The 'foo' library may need to update its package.json.
15+
/index.mts(2,21): error TS7016: Could not find a declaration file for module 'bar'. '/node_modules/bar/index.mjs' implicitly has an 'any' type.
16+
There are types at '/node_modules/@types/bar/index.d.ts', but this result could not be resolved when respecting package.json "exports". The '@types/bar' library may need to update its package.json.
17+
18+
19+
!!! error TS6504: File '/node_modules/bar/index.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
20+
!!! error TS6504: The file is in the program because:
21+
!!! error TS6504: Root file specified for compilation
22+
!!! error TS6504: File '/node_modules/bar/index.mjs' is a JavaScript file. Did you mean to enable the 'allowJs' option?
23+
!!! error TS6504: The file is in the program because:
24+
!!! error TS6504: Root file specified for compilation
25+
!!! error TS6504: File '/node_modules/foo/index.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
26+
!!! error TS6504: The file is in the program because:
27+
!!! error TS6504: Root file specified for compilation
28+
!!! error TS6504: File '/node_modules/foo/index.mjs' is a JavaScript file. Did you mean to enable the 'allowJs' option?
29+
!!! error TS6504: The file is in the program because:
30+
!!! error TS6504: Root file specified for compilation
31+
==== /node_modules/foo/package.json (0 errors) ====
32+
{
33+
"name": "foo",
34+
"version": "1.0.0",
35+
"main": "index.js",
36+
"types": "index.d.ts",
37+
"exports": {
38+
".": {
39+
"import": "./index.mjs",
40+
"require": "./index.js"
41+
}
42+
}
43+
}
44+
45+
==== /node_modules/foo/index.js (0 errors) ====
46+
module.exports = { foo: 1 };
47+
48+
==== /node_modules/foo/index.mjs (0 errors) ====
49+
export const foo = 1;
50+
51+
==== /node_modules/foo/index.d.ts (0 errors) ====
52+
export declare const foo: number;
53+
54+
==== /node_modules/@types/bar/package.json (0 errors) ====
55+
{
56+
"name": "@types/bar",
57+
"version": "1.0.0",
58+
"types": "index.d.ts",
59+
"exports": {
60+
".": {
61+
"require": "./index.d.ts"
62+
}
63+
}
64+
}
65+
66+
==== /node_modules/@types/bar/index.d.ts (0 errors) ====
67+
export declare const bar: number;
68+
69+
==== /node_modules/bar/package.json (0 errors) ====
70+
{
71+
"name": "bar",
72+
"version": "1.0.0",
73+
"main": "index.js",
74+
"exports": {
75+
".": {
76+
"import": "./index.mjs",
77+
"require": "./index.js"
78+
}
79+
}
80+
}
81+
82+
==== /node_modules/bar/index.js (0 errors) ====
83+
module.exports = { bar: 1 };
84+
85+
==== /node_modules/bar/index.mjs (0 errors) ====
86+
export const bar = 1;
87+
88+
==== /index.mts (2 errors) ====
89+
import { foo } from "foo";
90+
~~~~~
91+
!!! error TS7016: Could not find a declaration file for module 'foo'. '/node_modules/foo/index.mjs' implicitly has an 'any' type.
92+
!!! error TS7016: There are types at '/node_modules/foo/index.d.ts', but this result could not be resolved when respecting package.json "exports". The 'foo' library may need to update its package.json.
93+
import { bar } from "bar";
94+
~~~~~
95+
!!! error TS7016: Could not find a declaration file for module 'bar'. '/node_modules/bar/index.mjs' implicitly has an 'any' type.
96+
!!! error TS7016: There are types at '/node_modules/@types/bar/index.d.ts', but this result could not be resolved when respecting package.json "exports". The '@types/bar' library may need to update its package.json.

0 commit comments

Comments
 (0)