Skip to content

Commit 7afd14f

Browse files
authored
Update error messages for CJS imports resolving to ES modules (microsoft#50088)
* Update error messages for CJS imports resolving to ES modules * Update error message * Use package scope from source file * Update baselines * Issue error for JSX/TSX files * Switch from related info to message chain
1 parent b1176ce commit 7afd14f

File tree

51 files changed

+708
-407
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+708
-407
lines changed

src/compiler/checker.ts

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3576,7 +3576,51 @@ namespace ts {
35763576
// An override clause will take effect for type-only imports and import types, and allows importing the types across formats, regardless of
35773577
// normal mode restrictions
35783578
if (isSyncImport && sourceFile.impliedNodeFormat === ModuleKind.ESNext && !getResolutionModeOverrideForClause(overrideClause)) {
3579-
error(errorNode, Diagnostics.Module_0_cannot_be_imported_using_this_construct_The_specifier_only_resolves_to_an_ES_module_which_cannot_be_imported_synchronously_Use_dynamic_import_instead, moduleReference);
3579+
if (findAncestor(location, isImportEqualsDeclaration)) {
3580+
// ImportEquals in a ESM file resolving to another ESM file
3581+
error(errorNode, Diagnostics.Module_0_cannot_be_imported_using_this_construct_The_specifier_only_resolves_to_an_ES_module_which_cannot_be_imported_with_require_Use_an_ECMAScript_import_instead, moduleReference);
3582+
}
3583+
else {
3584+
// CJS file resolving to an ESM file
3585+
let diagnosticDetails;
3586+
const ext = tryGetExtensionFromPath(currentSourceFile.fileName);
3587+
if (ext === Extension.Ts || ext === Extension.Js || ext === Extension.Tsx || ext === Extension.Jsx) {
3588+
const scope = currentSourceFile.packageJsonScope;
3589+
const targetExt = ext === Extension.Ts ? Extension.Mts : ext === Extension.Js ? Extension.Mjs : undefined;
3590+
if (scope && !scope.packageJsonContent.type) {
3591+
if (targetExt) {
3592+
diagnosticDetails = chainDiagnosticMessages(
3593+
/*details*/ undefined,
3594+
Diagnostics.To_convert_this_file_to_an_ECMAScript_module_change_its_file_extension_to_0_or_add_the_field_type_Colon_module_to_1,
3595+
targetExt,
3596+
combinePaths(scope.packageDirectory, "package.json"));
3597+
}
3598+
else {
3599+
diagnosticDetails = chainDiagnosticMessages(
3600+
/*details*/ undefined,
3601+
Diagnostics.To_convert_this_file_to_an_ECMAScript_module_add_the_field_type_Colon_module_to_0,
3602+
combinePaths(scope.packageDirectory, "package.json"));
3603+
}
3604+
}
3605+
else {
3606+
if (targetExt) {
3607+
diagnosticDetails = chainDiagnosticMessages(
3608+
/*details*/ undefined,
3609+
Diagnostics.To_convert_this_file_to_an_ECMAScript_module_change_its_file_extension_to_0_or_create_a_local_package_json_file_with_type_Colon_module,
3610+
targetExt);
3611+
}
3612+
else {
3613+
diagnosticDetails = chainDiagnosticMessages(
3614+
/*details*/ undefined,
3615+
Diagnostics.To_convert_this_file_to_an_ECMAScript_module_create_a_local_package_json_file_with_type_Colon_module);
3616+
}
3617+
}
3618+
}
3619+
diagnostics.add(createDiagnosticForNodeFromMessageChain(errorNode, chainDiagnosticMessages(
3620+
diagnosticDetails,
3621+
Diagnostics.The_current_file_is_a_CommonJS_module_whose_imports_will_produce_require_calls_however_the_referenced_file_is_an_ECMAScript_module_and_cannot_be_imported_with_require_Consider_writing_a_dynamic_import_0_call_instead,
3622+
moduleReference)));
3623+
}
35803624
}
35813625
}
35823626
// merged symbol is module declaration symbol combined with all augmentations

src/compiler/diagnosticMessages.json

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1485,7 +1485,7 @@
14851485
"category": "Error",
14861486
"code": 1470
14871487
},
1488-
"Module '{0}' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.": {
1488+
"Module '{0}' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported with 'require'. Use an ECMAScript import instead.": {
14891489
"category": "Error",
14901490
"code": 1471
14911491
},
@@ -1517,6 +1517,26 @@
15171517
"category": "Error",
15181518
"code": 1478
15191519
},
1520+
"The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import(\"{0}\")' call instead.": {
1521+
"category": "Error",
1522+
"code": 1479
1523+
},
1524+
"To convert this file to an ECMAScript module, change its file extension to '{0}' or create a local package.json file with `{ \"type\": \"module\" }`.": {
1525+
"category": "Message",
1526+
"code": 1480
1527+
},
1528+
"To convert this file to an ECMAScript module, change its file extension to '{0}', or add the field `\"type\": \"module\"` to '{1}'.": {
1529+
"category": "Message",
1530+
"code": 1481
1531+
},
1532+
"To convert this file to an ECMAScript module, add the field `\"type\": \"module\"` to '{0}'.": {
1533+
"category": "Message",
1534+
"code": 1482
1535+
},
1536+
"To convert this file to an ECMAScript module, create a local package.json file with `{ \"type\": \"module\" }`.": {
1537+
"category": "Message",
1538+
"code": 1483
1539+
},
15201540

15211541
"The types of '{0}' are incompatible between these types.": {
15221542
"category": "Error",

tests/baselines/reference/nodeAllowJsPackageSelfName(module=node16).errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error TS2209: The project root is ambiguous, but is required to resolve export map entry '.' in file 'tests/cases/conformance/node/allowJs/package.json'. Supply the `rootDir` compiler option to disambiguate.
2-
tests/cases/conformance/node/allowJs/index.cjs(2,23): error TS1471: Module 'package' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
2+
tests/cases/conformance/node/allowJs/index.cjs(2,23): error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("package")' call instead.
33

44

55
!!! error TS2209: The project root is ambiguous, but is required to resolve export map entry '.' in file 'tests/cases/conformance/node/allowJs/package.json'. Supply the `rootDir` compiler option to disambiguate.
@@ -15,7 +15,7 @@ tests/cases/conformance/node/allowJs/index.cjs(2,23): error TS1471: Module 'pack
1515
// esm format file
1616
import * as self from "package";
1717
~~~~~~~~~
18-
!!! error TS1471: Module 'package' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
18+
!!! error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("package")' call instead.
1919
self;
2020
==== tests/cases/conformance/node/allowJs/package.json (0 errors) ====
2121
{

tests/baselines/reference/nodeAllowJsPackageSelfName(module=nodenext).errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error TS2209: The project root is ambiguous, but is required to resolve export map entry '.' in file 'tests/cases/conformance/node/allowJs/package.json'. Supply the `rootDir` compiler option to disambiguate.
2-
tests/cases/conformance/node/allowJs/index.cjs(2,23): error TS1471: Module 'package' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
2+
tests/cases/conformance/node/allowJs/index.cjs(2,23): error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("package")' call instead.
33

44

55
!!! error TS2209: The project root is ambiguous, but is required to resolve export map entry '.' in file 'tests/cases/conformance/node/allowJs/package.json'. Supply the `rootDir` compiler option to disambiguate.
@@ -15,7 +15,7 @@ tests/cases/conformance/node/allowJs/index.cjs(2,23): error TS1471: Module 'pack
1515
// esm format file
1616
import * as self from "package";
1717
~~~~~~~~~
18-
!!! error TS1471: Module 'package' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
18+
!!! error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("package")' call instead.
1919
self;
2020
==== tests/cases/conformance/node/allowJs/package.json (0 errors) ====
2121
{

0 commit comments

Comments
 (0)