diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 84b111555df7e..c66b079df1cf1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8,6 +8,7 @@ import { addSyntheticLeadingComment, AliasDeclarationNode, AllAccessorDeclarations, + AllowRequireESM, AmbientModuleDeclaration, and, AnonymousType, @@ -138,6 +139,7 @@ import { Decorator, deduplicate, DefaultClause, + DefaultIsModuleExports, defaultMaximumTruncationLength, DeferredTypeReference, DeleteExpression, @@ -245,6 +247,7 @@ import { GetAccessorDeclaration, getAliasDeclarationFromName, getAllJSDocTags, + getAllowRequireESM, getAllowSyntheticDefaultImports, getAncestor, getAssignedExpandoInitializer, @@ -268,6 +271,7 @@ import { getDeclarationsOfKind, getDeclaredExpandoInitializer, getDecorators, + getDefaultIsModuleExports, getDirectoryPath, getEffectiveBaseTypeNode, getEffectiveConstraintOfTypeParameter, @@ -3634,7 +3638,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const usageMode = file && getEmitSyntaxForModuleSpecifierExpression(usage); if (file && usageMode !== undefined) { const targetMode = host.getImpliedNodeFormatForEmit(file); - if (usageMode === ModuleKind.ESNext && targetMode === ModuleKind.CommonJS && ModuleKind.Node16 <= moduleKind && moduleKind <= ModuleKind.NodeNext) { + const defaultIsModuleExports = getDefaultIsModuleExports(compilerOptions); + const usesNodeLikeInteropRules = DefaultIsModuleExports.Node16 <= defaultIsModuleExports && defaultIsModuleExports <= DefaultIsModuleExports.NodeNext; + if (usageMode === ModuleKind.ESNext && targetMode !== ModuleKind.ESNext && usesNodeLikeInteropRules) { // In Node.js, CommonJS modules always have a synthetic default when imported into ESM return true; } @@ -3649,6 +3655,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Declaration files (and ambient modules) if (!file || file.isDeclarationFile) { + // Unambiguously ESM files do not have a synthetic default + if (file && host.getImpliedNodeFormatForEmit(file) === ModuleKind.ESNext) { + return false; + } // Definitely cannot have a synthetic default if they have a syntactic default member specified const defaultExportSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, /*sourceNode*/ undefined, /*dontResolveAlias*/ true); // Dont resolve alias because we want the immediately exported symbol's declaration if (defaultExportSymbol && some(defaultExportSymbol.declarations, isSyntacticDefault)) { @@ -4571,7 +4581,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const mode = contextSpecifier && isStringLiteralLike(contextSpecifier) ? host.getModeForUsageLocation(currentSourceFile, contextSpecifier) : host.getDefaultResolutionModeForFile(currentSourceFile); + const importingFileIsJavaScript = isSourceFileJS(currentSourceFile); const moduleResolutionKind = getEmitModuleResolutionKind(compilerOptions); + const allowRequireESM = getAllowRequireESM(compilerOptions); const resolvedModule = host.getResolvedModule(currentSourceFile, moduleReference, mode)?.resolvedModule; const resolutionDiagnostic = resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule, currentSourceFile); const sourceFile = resolvedModule @@ -4607,12 +4619,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (resolvedModule.isExternalLibraryImport && !resolutionExtensionIsTSOrJson(resolvedModule.extension)) { errorOnImplicitAnyModule(/*isError*/ false, errorNode, currentSourceFile, mode, resolvedModule, moduleReference); } - if (moduleResolutionKind === ModuleResolutionKind.Node16 || moduleResolutionKind === ModuleResolutionKind.NodeNext) { - const isSyncImport = (currentSourceFile.impliedNodeFormat === ModuleKind.CommonJS && !findAncestor(location, isImportCall)) || !!findAncestor(location, isImportEqualsDeclaration); + if (AllowRequireESM.Node16 <= allowRequireESM && allowRequireESM <= AllowRequireESM.NodeNext) { + const isSyncImport = (host.getImpliedNodeFormatForEmit(currentSourceFile) === ModuleKind.CommonJS && !findAncestor(location, isImportCall)) + || !!findAncestor(location, n => isImportEqualsDeclaration(n) || importingFileIsJavaScript && isVariableDeclarationInitializedToBareOrAccessedRequire(n)); const overrideHost = findAncestor(location, l => isImportTypeNode(l) || isExportDeclaration(l) || isImportDeclaration(l)) as ImportTypeNode | ImportDeclaration | ExportDeclaration | undefined; // An override clause will take effect for type-only imports and import types, and allows importing the types across formats, regardless of // normal mode restrictions - if (isSyncImport && sourceFile.impliedNodeFormat === ModuleKind.ESNext && !hasResolutionModeOverride(overrideHost)) { + if (isSyncImport && host.getImpliedNodeFormatForEmit(sourceFile) === ModuleKind.ESNext && !hasResolutionModeOverride(overrideHost)) { if (findAncestor(location, isImportEqualsDeclaration)) { // ImportEquals in a ESM file resolving to another ESM file 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); diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 52db793b070a8..7e9002ffcb739 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1,4 +1,5 @@ import { + AllowRequireESM, AlternateModeDiagnostics, append, arrayFrom, @@ -23,6 +24,7 @@ import { createDiagnosticForNodeInSourceFile, createGetCanonicalFileName, Debug, + DefaultIsModuleExports, Diagnostic, DiagnosticArguments, DiagnosticMessage, @@ -1196,6 +1198,33 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ category: Diagnostics.Modules, description: Diagnostics.Conditions_to_set_in_addition_to_the_resolver_specific_defaults_when_resolving_imports, }, + { + name: "defaultIsModuleExports", + type: new Map(Object.entries({ + auto: DefaultIsModuleExports.Auto, + node16: DefaultIsModuleExports.Node16, + nodenext: DefaultIsModuleExports.NodeNext, + })), + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: Diagnostics.Modules, + description: Diagnostics.Specify_the_target_runtime_s_rules_for_default_imports_targeting_CommonJS_modules, + defaultValueDescription: Diagnostics.node16_when_module_is_node16_nodenext_when_module_is_nodenext_auto_otherwise, + }, + { + name: "allowRequireESM", + type: new Map(Object.entries({ + never: AllowRequireESM.Never, + always: AllowRequireESM.Always, + node16: AllowRequireESM.Node16, + nodenext: AllowRequireESM.NodeNext, + })), + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: Diagnostics.Modules, + description: Diagnostics.Specify_the_target_runtime_s_rules_for_CommonJS_require_calls_targeting_ECMAScript_modules, + defaultValueDescription: Diagnostics.node16_when_module_is_node16_nodenext_when_module_is_nodenext_always_otherwise, + }, // Source Maps { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 1db3b8c70bc30..ed0097d151b2a 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -6392,6 +6392,14 @@ "category": "Message", "code": 6805 }, + "Specify the target runtime's rules for default imports targeting CommonJS modules.": { + "category": "Message", + "code": 6806 + }, + "Specify the target runtime's rules for CommonJS 'require' calls targeting ECMAScript modules.": { + "category": "Message", + "code": 6807 + }, "one of:": { "category": "Message", @@ -6521,6 +6529,14 @@ "category": "Error", "code": 6931 }, + "'node16' when 'module' is 'node16'; 'nodenext' when 'module' is 'nodenext'; 'auto' otherwise.": { + "category": "Message", + "code": 6932 + }, + "'node16' when 'module' is 'node16'; 'nodenext' when 'module' is 'nodenext'; 'always' otherwise.": { + "category": "Message", + "code": 6933 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 1b737bd261363..c3b4d37532eac 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -7227,6 +7227,7 @@ export interface CompilerOptions { allowJs?: boolean; /** @internal */ allowNonTsExtensions?: boolean; allowArbitraryExtensions?: boolean; + allowRequireESM?: AllowRequireESM; allowSyntheticDefaultImports?: boolean; allowUmdGlobalAccess?: boolean; allowUnreachableCode?: boolean; @@ -7254,6 +7255,7 @@ export interface CompilerOptions { declarationMap?: boolean; emitDeclarationOnly?: boolean; declarationDir?: string; + defaultIsModuleExports?: DefaultIsModuleExports; /** @internal */ diagnostics?: boolean; /** @internal */ extendedDiagnostics?: boolean; disableSizeLimit?: boolean; @@ -7423,6 +7425,19 @@ export enum ModuleKind { Preserve = 200, } +export enum DefaultIsModuleExports { + Auto = 1, + Node16 = 100, + NodeNext = 199, +} + +export enum AllowRequireESM { + Never = 0, + Always = 1, + Node16 = 100, + NodeNext = 199, +} + export const enum JsxEmit { None = 0, Preserve = 1, diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 655c35eacf576..4dd758ca57c3d 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -6,6 +6,7 @@ import { affectsDeclarationPathOptionDeclarations, affectsEmitOptionDeclarations, AllAccessorDeclarations, + AllowRequireESM, AmbientModuleDeclaration, AmpersandAmpersandEqualsToken, AnyImportOrBareOrAccessedRequire, @@ -90,6 +91,7 @@ import { DeclarationWithTypeParameters, Decorator, DefaultClause, + DefaultIsModuleExports, DestructuringAssignment, Diagnostic, DiagnosticArguments, @@ -8852,6 +8854,30 @@ export const computedOptions = createComputedCompilerOptions({ computedOptions.module.computeValue(compilerOptions) === ModuleKind.NodeNext ? ModuleDetectionKind.Force : ModuleDetectionKind.Auto); }, }, + defaultIsModuleExports: { + dependencies: ["module", "target"], + computeValue: (compilerOptions): DefaultIsModuleExports => { + if (compilerOptions.defaultIsModuleExports !== undefined) { + return compilerOptions.defaultIsModuleExports; + } + const moduleKind = computedOptions.module.computeValue(compilerOptions); + return moduleKind === ModuleKind.Node16 ? DefaultIsModuleExports.Node16 : + moduleKind === ModuleKind.NodeNext ? DefaultIsModuleExports.NodeNext : + DefaultIsModuleExports.Auto; + }, + }, + allowRequireESM: { + dependencies: ["module", "target"], + computeValue: (compilerOptions): AllowRequireESM => { + if (compilerOptions.allowRequireESM !== undefined) { + return compilerOptions.allowRequireESM; + } + const moduleKind = computedOptions.module.computeValue(compilerOptions); + return moduleKind === ModuleKind.Node16 ? AllowRequireESM.Node16 : + moduleKind === ModuleKind.NodeNext ? AllowRequireESM.NodeNext : + AllowRequireESM.Always; + }, + }, isolatedModules: { dependencies: ["verbatimModuleSyntax"], computeValue: compilerOptions => { @@ -9028,6 +9054,10 @@ export const getEmitModuleResolutionKind = computedOptions.moduleResolution.comp /** @internal */ export const getEmitModuleDetectionKind = computedOptions.moduleDetection.computeValue; /** @internal */ +export const getDefaultIsModuleExports = computedOptions.defaultIsModuleExports.computeValue; +/** @internal */ +export const getAllowRequireESM = computedOptions.allowRequireESM.computeValue; +/** @internal */ export const getIsolatedModules = computedOptions.isolatedModules.computeValue; /** @internal */ export const getESModuleInterop = computedOptions.esModuleInterop.computeValue; diff --git a/src/testRunner/compilerRunner.ts b/src/testRunner/compilerRunner.ts index 93bc55c1159fe..18c9eb679db96 100644 --- a/src/testRunner/compilerRunner.ts +++ b/src/testRunner/compilerRunner.ts @@ -129,8 +129,10 @@ class CompilerTest { private static varyBy: readonly string[] = [ "allowArbitraryExtensions", "allowImportingTsExtensions", + "allowRequireESM", "allowSyntheticDefaultImports", "alwaysStrict", + "defaultIsModuleExports", "downlevelIteration", "experimentalDecorators", "emitDecoratorMetadata", diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index b1ac4827d4fd1..f266a29a4b305 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -6902,6 +6902,7 @@ declare namespace ts { allowImportingTsExtensions?: boolean; allowJs?: boolean; allowArbitraryExtensions?: boolean; + allowRequireESM?: AllowRequireESM; allowSyntheticDefaultImports?: boolean; allowUmdGlobalAccess?: boolean; allowUnreachableCode?: boolean; @@ -6916,6 +6917,7 @@ declare namespace ts { declarationMap?: boolean; emitDeclarationOnly?: boolean; declarationDir?: string; + defaultIsModuleExports?: DefaultIsModuleExports; disableSizeLimit?: boolean; disableSourceOfProjectReferenceRedirect?: boolean; disableSolutionSearching?: boolean; @@ -7044,6 +7046,17 @@ declare namespace ts { NodeNext = 199, Preserve = 200, } + enum DefaultIsModuleExports { + Auto = 1, + Node16 = 100, + NodeNext = 199, + } + enum AllowRequireESM { + Never = 0, + Always = 1, + Node16 = 100, + NodeNext = 199, + } enum JsxEmit { None = 0, Preserve = 1, diff --git a/tests/baselines/reference/config/initTSConfig/Default initialized TSConfig/tsconfig.json b/tests/baselines/reference/config/initTSConfig/Default initialized TSConfig/tsconfig.json index 8bb6097f80145..5f4490bb821c6 100644 --- a/tests/baselines/reference/config/initTSConfig/Default initialized TSConfig/tsconfig.json +++ b/tests/baselines/reference/config/initTSConfig/Default initialized TSConfig/tsconfig.json @@ -39,6 +39,8 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "defaultIsModuleExports": "auto", /* Specify the target runtime's rules for default imports targeting CommonJS modules. */ + // "allowRequireESM": "never", /* Specify the target runtime's rules for CommonJS 'require' calls targeting ECMAScript modules. */ // "resolveJsonModule": true, /* Enable importing .json files. */ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "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/config/initTSConfig/Initialized TSConfig with --help/tsconfig.json b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with --help/tsconfig.json index 8bb6097f80145..5f4490bb821c6 100644 --- a/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with --help/tsconfig.json +++ b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with --help/tsconfig.json @@ -39,6 +39,8 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "defaultIsModuleExports": "auto", /* Specify the target runtime's rules for default imports targeting CommonJS modules. */ + // "allowRequireESM": "never", /* Specify the target runtime's rules for CommonJS 'require' calls targeting ECMAScript modules. */ // "resolveJsonModule": true, /* Enable importing .json files. */ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "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/config/initTSConfig/Initialized TSConfig with --watch/tsconfig.json b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with --watch/tsconfig.json index 8bb6097f80145..5f4490bb821c6 100644 --- a/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with --watch/tsconfig.json +++ b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with --watch/tsconfig.json @@ -39,6 +39,8 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "defaultIsModuleExports": "auto", /* Specify the target runtime's rules for default imports targeting CommonJS modules. */ + // "allowRequireESM": "never", /* Specify the target runtime's rules for CommonJS 'require' calls targeting ECMAScript modules. */ // "resolveJsonModule": true, /* Enable importing .json files. */ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "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/config/initTSConfig/Initialized TSConfig with advanced options/tsconfig.json b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with advanced options/tsconfig.json index b3d05912583d9..a7081180b6039 100644 --- a/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with advanced options/tsconfig.json +++ b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with advanced options/tsconfig.json @@ -39,6 +39,8 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "defaultIsModuleExports": "auto", /* Specify the target runtime's rules for default imports targeting CommonJS modules. */ + // "allowRequireESM": "never", /* Specify the target runtime's rules for CommonJS 'require' calls targeting ECMAScript modules. */ // "resolveJsonModule": true, /* Enable importing .json files. */ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "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/config/initTSConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json index 558f4243438d2..40e046ed10df5 100644 --- a/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json +++ b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json @@ -39,6 +39,8 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "defaultIsModuleExports": "auto", /* Specify the target runtime's rules for default imports targeting CommonJS modules. */ + // "allowRequireESM": "never", /* Specify the target runtime's rules for CommonJS 'require' calls targeting ECMAScript modules. */ // "resolveJsonModule": true, /* Enable importing .json files. */ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "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/config/initTSConfig/Initialized TSConfig with enum value compiler options/tsconfig.json b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with enum value compiler options/tsconfig.json index 5679f8b921cdf..f87bb3feb24db 100644 --- a/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with enum value compiler options/tsconfig.json +++ b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with enum value compiler options/tsconfig.json @@ -39,6 +39,8 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "defaultIsModuleExports": "auto", /* Specify the target runtime's rules for default imports targeting CommonJS modules. */ + // "allowRequireESM": "never", /* Specify the target runtime's rules for CommonJS 'require' calls targeting ECMAScript modules. */ // "resolveJsonModule": true, /* Enable importing .json files. */ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "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/config/initTSConfig/Initialized TSConfig with files options/tsconfig.json b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with files options/tsconfig.json index 535e6a2d97860..1bb17f3d0728d 100644 --- a/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with files options/tsconfig.json +++ b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with files options/tsconfig.json @@ -39,6 +39,8 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "defaultIsModuleExports": "auto", /* Specify the target runtime's rules for default imports targeting CommonJS modules. */ + // "allowRequireESM": "never", /* Specify the target runtime's rules for CommonJS 'require' calls targeting ECMAScript modules. */ // "resolveJsonModule": true, /* Enable importing .json files. */ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "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/config/initTSConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json index da587b6bded7f..4a3e4fa8a8b14 100644 --- a/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json +++ b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json @@ -39,6 +39,8 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "defaultIsModuleExports": "auto", /* Specify the target runtime's rules for default imports targeting CommonJS modules. */ + // "allowRequireESM": "never", /* Specify the target runtime's rules for CommonJS 'require' calls targeting ECMAScript modules. */ // "resolveJsonModule": true, /* Enable importing .json files. */ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "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/config/initTSConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json index 8bb6097f80145..5f4490bb821c6 100644 --- a/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json +++ b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json @@ -39,6 +39,8 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "defaultIsModuleExports": "auto", /* Specify the target runtime's rules for default imports targeting CommonJS modules. */ + // "allowRequireESM": "never", /* Specify the target runtime's rules for CommonJS 'require' calls targeting ECMAScript modules. */ // "resolveJsonModule": true, /* Enable importing .json files. */ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "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/config/initTSConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json index a6e74d92a6a8f..302fe7dd4b7df 100644 --- a/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json +++ b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json @@ -39,6 +39,8 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "defaultIsModuleExports": "auto", /* Specify the target runtime's rules for default imports targeting CommonJS modules. */ + // "allowRequireESM": "never", /* Specify the target runtime's rules for CommonJS 'require' calls targeting ECMAScript modules. */ // "resolveJsonModule": true, /* Enable importing .json files. */ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "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/config/initTSConfig/Initialized TSConfig with list compiler options/tsconfig.json b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with list compiler options/tsconfig.json index 41c2964e0e7fa..9f582764d85d1 100644 --- a/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with list compiler options/tsconfig.json +++ b/tests/baselines/reference/config/initTSConfig/Initialized TSConfig with list compiler options/tsconfig.json @@ -39,6 +39,8 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "defaultIsModuleExports": "auto", /* Specify the target runtime's rules for default imports targeting CommonJS modules. */ + // "allowRequireESM": "never", /* Specify the target runtime's rules for CommonJS 'require' calls targeting ECMAScript modules. */ // "resolveJsonModule": true, /* Enable importing .json files. */ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "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/config/showConfig/Shows tsconfig for single option/allowRequireESM/tsconfig.json b/tests/baselines/reference/config/showConfig/Shows tsconfig for single option/allowRequireESM/tsconfig.json new file mode 100644 index 0000000000000..47369742b654f --- /dev/null +++ b/tests/baselines/reference/config/showConfig/Shows tsconfig for single option/allowRequireESM/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "allowRequireESM": "never" + } +} diff --git a/tests/baselines/reference/config/showConfig/Shows tsconfig for single option/defaultIsModuleExports/tsconfig.json b/tests/baselines/reference/config/showConfig/Shows tsconfig for single option/defaultIsModuleExports/tsconfig.json new file mode 100644 index 0000000000000..313c3e7950b09 --- /dev/null +++ b/tests/baselines/reference/config/showConfig/Shows tsconfig for single option/defaultIsModuleExports/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "defaultIsModuleExports": "auto" + } +} diff --git a/tests/baselines/reference/esbuildInterop(defaultismoduleexports=auto).errors.txt b/tests/baselines/reference/esbuildInterop(defaultismoduleexports=auto).errors.txt new file mode 100644 index 0000000000000..b5bc74655743c --- /dev/null +++ b/tests/baselines/reference/esbuildInterop(defaultismoduleexports=auto).errors.txt @@ -0,0 +1,26 @@ +/index.ts(3,5): error TS2339: Property 'default' does not exist on type 'string'. + + +==== /node_modules/dep/package.json (0 errors) ==== + { + "name": "dep", + "version": "1.0.0", + "main": "index.js" + } + +==== /node_modules/dep/index.d.ts (0 errors) ==== + declare const _default: string; + export default _default; + +==== /package.json (0 errors) ==== + { + "type": "module" + } + +==== /index.ts (1 errors) ==== + import dep from "dep"; + dep.toLowerCase(); // Error in nodenext + dep.default.toLowerCase(); // Error in auto + ~~~~~~~ +!!! error TS2339: Property 'default' does not exist on type 'string'. + \ No newline at end of file diff --git a/tests/baselines/reference/esbuildInterop(defaultismoduleexports=nodenext).errors.txt b/tests/baselines/reference/esbuildInterop(defaultismoduleexports=nodenext).errors.txt new file mode 100644 index 0000000000000..ee0d91b41e490 --- /dev/null +++ b/tests/baselines/reference/esbuildInterop(defaultismoduleexports=nodenext).errors.txt @@ -0,0 +1,26 @@ +/index.ts(2,5): error TS2339: Property 'toLowerCase' does not exist on type 'typeof import("/node_modules/dep/index")'. + + +==== /node_modules/dep/package.json (0 errors) ==== + { + "name": "dep", + "version": "1.0.0", + "main": "index.js" + } + +==== /node_modules/dep/index.d.ts (0 errors) ==== + declare const _default: string; + export default _default; + +==== /package.json (0 errors) ==== + { + "type": "module" + } + +==== /index.ts (1 errors) ==== + import dep from "dep"; + dep.toLowerCase(); // Error in nodenext + ~~~~~~~~~~~ +!!! error TS2339: Property 'toLowerCase' does not exist on type 'typeof import("/node_modules/dep/index")'. + dep.default.toLowerCase(); // Error in auto + \ No newline at end of file diff --git a/tests/baselines/reference/webpackInterop(allowrequireesm=node16).errors.txt b/tests/baselines/reference/webpackInterop(allowrequireesm=node16).errors.txt new file mode 100644 index 0000000000000..70e55cc2d3bbf --- /dev/null +++ b/tests/baselines/reference/webpackInterop(allowrequireesm=node16).errors.txt @@ -0,0 +1,21 @@ +/main2.js(2,20): 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("./marked-esm.mjs")' call instead. + To convert this file to an ECMAScript module, change its file extension to '.mjs' or create a local package.json file with `{ "type": "module" }`. + + +==== /main2.js (1 errors) ==== + const _1 = require("./unmarked-esm.js"); + const _2 = require("./marked-esm.mjs"); + ~~~~~~~~~~~~~~~~~~ +!!! 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("./marked-esm.mjs")' call instead. +!!! error TS1479: To convert this file to an ECMAScript module, change its file extension to '.mjs' or create a local package.json file with `{ "type": "module" }`. + +==== /unmarked-esm.js (0 errors) ==== + export default "unmarked-esm"; + +==== /marked-esm.mjs (0 errors) ==== + export default "marked-esm"; + +==== /main1.js (0 errors) ==== + import unmarked from "./unmarked-esm.js"; + import marked from "./marked-esm.mjs"; + \ No newline at end of file diff --git a/tests/cases/conformance/module/esbuildInterop.ts b/tests/cases/conformance/module/esbuildInterop.ts new file mode 100644 index 0000000000000..5b31ff4f6759e --- /dev/null +++ b/tests/cases/conformance/module/esbuildInterop.ts @@ -0,0 +1,26 @@ +// @module: esnext +// @moduleResolution: bundler +// @defaultIsModuleExports: auto, nodenext +// @noEmit: true +// @noTypesAndSymbols: true + +// @Filename: /node_modules/dep/package.json +{ + "name": "dep", + "version": "1.0.0", + "main": "index.js" +} + +// @Filename: /node_modules/dep/index.d.ts +declare const _default: string; +export default _default; + +// @Filename: /package.json +{ + "type": "module" +} + +// @Filename: /index.ts +import dep from "dep"; +dep.toLowerCase(); // Error in nodenext +dep.default.toLowerCase(); // Error in auto diff --git a/tests/cases/conformance/module/webpackInterop.ts b/tests/cases/conformance/module/webpackInterop.ts new file mode 100644 index 0000000000000..c05df67abc901 --- /dev/null +++ b/tests/cases/conformance/module/webpackInterop.ts @@ -0,0 +1,21 @@ +// @module: preserve +// @moduleResolution: bundler +// @defaultIsModuleExports: node16 +// @allowRequireESM: always, node16 +// @noEmit: true +// @checkJs: true +// @noTypesAndSymbols: true + +// @Filename: /unmarked-esm.js +export default "unmarked-esm"; + +// @Filename: /marked-esm.mjs +export default "marked-esm"; + +// @Filename: /main1.js +import unmarked from "./unmarked-esm.js"; +import marked from "./marked-esm.mjs"; + +// @Filename: /main2.js +const _1 = require("./unmarked-esm.js"); +const _2 = require("./marked-esm.mjs");